From fc2bac7e45ba92102b7e03bf298c371ce76396a5 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Mon, 5 Jun 2017 17:08:55 -0400 Subject: [PATCH] add null D3D12 backend --- examples/CMakeLists.txt | 6 + examples/D3D12Binding.cpp | 36 ++++ examples/Utils.cpp | 27 ++- generator/main.py | 11 +- src/backend/CMakeLists.txt | 28 +++ src/backend/d3d12/D3D12Backend.cpp | 193 +++++++++++++++++ src/backend/d3d12/D3D12Backend.h | 246 ++++++++++++++++++++++ src/backend/d3d12/GeneratedCodeIncludes.h | 15 ++ 8 files changed, 556 insertions(+), 6 deletions(-) create mode 100644 examples/D3D12Binding.cpp create mode 100644 src/backend/d3d12/D3D12Backend.cpp create mode 100644 src/backend/d3d12/D3D12Backend.h create mode 100644 src/backend/d3d12/GeneratedCodeIncludes.h diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c5e8775946..431b0a28d1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -24,6 +24,12 @@ if (APPLE) ) endif() +if (WIN32) + list(APPEND UTILS_SOURCES + D3D12Binding.cpp + ) +endif() + add_library(utils STATIC ${UTILS_SOURCES}) target_link_libraries(utils nxt_backend nxt_wire shaderc nxtcpp nxt) SetCXX14(utils) diff --git a/examples/D3D12Binding.cpp b/examples/D3D12Binding.cpp new file mode 100644 index 0000000000..a68cf5f8a5 --- /dev/null +++ b/examples/D3D12Binding.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "BackendBinding.h" + +namespace backend { +namespace d3d12 { + void Init(nxtProcTable* procs, nxtDevice* device); +} +} + +class D3D12Binding : public BackendBinding { + public: + void SetupGLFWWindowHints() override { + } + void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override { + backend::d3d12::Init(procs, device); + } + void SwapBuffers() override { + } +}; + +BackendBinding* CreateD3D12Binding() { + return new D3D12Binding; +} diff --git a/examples/Utils.cpp b/examples/Utils.cpp index 9edab258a5..b72d39e5c0 100644 --- a/examples/Utils.cpp +++ b/examples/Utils.cpp @@ -32,6 +32,7 @@ #endif BackendBinding* CreateMetalBinding(); +BackendBinding* CreateD3D12Binding(); namespace backend { namespace opengl { @@ -82,7 +83,6 @@ class NullBinding : public BackendBinding { } }; - void PrintDeviceError(const char* message, nxt::CallbackUserdata) { std::cout << "Device error: " << message << std::endl; } @@ -90,6 +90,7 @@ void PrintDeviceError(const char* message, nxt::CallbackUserdata) { enum class BackendType { OpenGL, Metal, + D3D12, Null, }; @@ -99,7 +100,14 @@ enum class CmdBufType { //TODO(cwallez@chromium.org) double terrible cmdbuf }; +#if defined(__APPLE__) +static BackendType backendType = BackendType::Metal; +#elif defined(_WIN32) +static BackendType backendType = BackendType::D3D12; +#else static BackendType backendType = BackendType::OpenGL; +#endif + static CmdBufType cmdBufType = CmdBufType::Terrible; static BackendBinding* binding = nullptr; @@ -119,7 +127,14 @@ nxt::Device CreateCppNXTDevice() { #if defined(__APPLE__) binding = CreateMetalBinding(); #else - fprintf(stderr, "Metal backend no present on this platform\n"); + fprintf(stderr, "Metal backend not present on this platform\n"); + #endif + break; + case BackendType::D3D12: + #if defined(_WIN32) + binding = CreateD3D12Binding(); + #else + fprintf(stderr, "D3D12 backend not present on this platform\n"); #endif break; case BackendType::Null: @@ -269,11 +284,15 @@ extern "C" { backendType = BackendType::Metal; continue; } + if (i < argc && std::string("d3d12") == argv[i]) { + backendType = BackendType::D3D12; + continue; + } if (i < argc && std::string("null") == argv[i]) { backendType = BackendType::Null; continue; } - fprintf(stderr, "--backend expects a backend name (opengl, metal, null)\n"); + fprintf(stderr, "--backend expects a backend name (opengl, metal, d3d12, null)\n"); return false; } if (std::string("-c") == argv[i] || std::string("--comand-buffer") == argv[i]) { @@ -291,7 +310,7 @@ extern "C" { } if (std::string("-h") == argv[i] || std::string("--help") == argv[i]) { printf("Usage: %s [-b BACKEND] [-c COMMAND_BUFFER]\n", argv[0]); - printf(" BACKEND is one of: opengl, metal, null\n"); + printf(" BACKEND is one of: opengl, metal, d3d12, null\n"); printf(" COMMAND_BUFFER is one of: none, terrible\n"); return false; } diff --git a/generator/main.py b/generator/main.py index c1ddbe3deb..122661992f 100644 --- a/generator/main.py +++ b/generator/main.py @@ -347,7 +347,7 @@ def debug(text): print(text) def main(): - targets = ['nxt', 'nxtcpp', 'mock_nxt', 'opengl', 'metal', 'null', 'wire', 'blink'] + targets = ['nxt', 'nxtcpp', 'mock_nxt', 'opengl', 'metal', 'd3d12', 'null', 'wire', 'blink'] parser = argparse.ArgumentParser( description = 'Generates code for various target for NXT.', @@ -432,10 +432,17 @@ def main(): } renders.append(FileRender('BackendProcTable.cpp', 'metal/ProcTable.mm', base_backend_params + [metal_params])) + if 'd3d12' in targets: + d3d12_params = { + 'namespace': 'd3d12', + } + renders.append(FileRender('BackendProcTable.cpp', 'd3d12/ProcTable.cpp', base_backend_params + [d3d12_params])) + if 'null' in targets: null_params = { 'namespace': 'null', } + renders.append(FileRender('BackendProcTable.cpp', 'null/ProcTable.cpp', base_backend_params + [null_params])) if 'wire' in targets: @@ -459,7 +466,7 @@ def main(): output_separator = '\n' if args.gn else ';' if args.print_dependencies: dependencies = set( - [os.path.abspath(args.template_dir + os.path.sep + render.template) for render in renders] + + [os.path.abspath(args.template_dir + os.path.sep + render.template) for render in renders] + [os.path.abspath(args.json[0])] + [os.path.realpath(__file__)] ) diff --git a/src/backend/CMakeLists.txt b/src/backend/CMakeLists.txt index 88a70ab8d3..46abf6b9c4 100644 --- a/src/backend/CMakeLists.txt +++ b/src/backend/CMakeLists.txt @@ -16,6 +16,7 @@ set(COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/common) set(METAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/metal) set(NULL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/null) set(OPENGL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/opengl) +set(D3D12_DIR ${CMAKE_CURRENT_SOURCE_DIR}/d3d12) set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests) list(APPEND BACKEND_SOURCES @@ -144,10 +145,37 @@ if (APPLE) ) endif() +# D3D12 Backend + +if (WIN32) + Generate( + LIB_NAME d3d12_autogen + LIB_TYPE STATIC + PRINT_NAME "D3D12 backend autogenerated files" + COMMAND_LINE_ARGS + ${GENERATOR_COMMON_ARGS} + -T d3d12 + ) + + target_include_directories(d3d12_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_include_directories(d3d12_autogen PUBLIC ${GENERATED_DIR}) + SetCXX14(d3d12_autogen) + SetPIC(d3d12_autogen) + + list(APPEND BACKEND_SOURCES + ${D3D12_DIR}/D3D12Backend.cpp + ${D3D12_DIR}/D3D12Backend.h + ) +endif() + add_library(nxt_backend STATIC ${BACKEND_SOURCES}) + target_link_libraries(nxt_backend opengl_autogen null_autogen glfw glad spirv-cross) if (APPLE) target_link_libraries(nxt_backend metal_autogen) endif() +if (WIN32) + target_link_libraries(nxt_backend d3d12_autogen) +endif() target_include_directories(nxt_backend PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) SetCXX14(nxt_backend) diff --git a/src/backend/d3d12/D3D12Backend.cpp b/src/backend/d3d12/D3D12Backend.cpp new file mode 100644 index 0000000000..6b1c94daef --- /dev/null +++ b/src/backend/d3d12/D3D12Backend.cpp @@ -0,0 +1,193 @@ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "D3D12Backend.h" + +namespace backend { +namespace d3d12 { + + nxtProcTable GetNonValidatingProcs(); + nxtProcTable GetValidatingProcs(); + + void Init(nxtProcTable* procs, nxtDevice* device) { + *device = nullptr; + *procs = GetValidatingProcs(); + } + + Device::Device() { + } + + Device::~Device() { + } + + BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) { + return new BindGroup(this, builder); + } + BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) { + return new BindGroupLayout(this, builder); + } + BufferBase* Device::CreateBuffer(BufferBuilder* builder) { + return new Buffer(this, builder); + } + BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) { + return new BufferView(this, builder); + } + CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { + return new CommandBuffer(this, builder); + } + DepthStencilStateBase* Device::CreateDepthStencilState(DepthStencilStateBuilder* builder) { + return new DepthStencilState(this, builder); + } + InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { + return new InputState(this, builder); + } + FramebufferBase* Device::CreateFramebuffer(FramebufferBuilder* builder) { + return new Framebuffer(this, builder); + } + PipelineBase* Device::CreatePipeline(PipelineBuilder* builder) { + return new Pipeline(this, builder); + } + PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { + return new PipelineLayout(this, builder); + } + QueueBase* Device::CreateQueue(QueueBuilder* builder) { + return new Queue(this, builder); + } + RenderPassBase* Device::CreateRenderPass(RenderPassBuilder* builder) { + return new RenderPass(this, builder); + } + SamplerBase* Device::CreateSampler(SamplerBuilder* builder) { + return new Sampler(this, builder); + } + ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) { + return new ShaderModule(this, builder); + } + TextureBase* Device::CreateTexture(TextureBuilder* builder) { + return new Texture(this, builder); + } + TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) { + return new TextureView(this, builder); + } + + void Device::Reference() { + } + + void Device::Release() { + } + + // Bind Group + + BindGroup::BindGroup(Device* device, BindGroupBuilder* builder) + : BindGroupBase(builder), device(device) { + } + + // Bind Group Layout + + BindGroupLayout::BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder) + : BindGroupLayoutBase(builder), device(device) { + } + + // Buffer + + Buffer::Buffer(Device* device, BufferBuilder* builder) + : BufferBase(builder), device(device) { + } + + void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) { + } + + // BufferView + + BufferView::BufferView(Device* device, BufferViewBuilder* builder) + : BufferViewBase(builder), device(device) { + } + + // CommandBuffer + + CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder) + : CommandBufferBase(builder), device(device) { + } + + // DepthStencilState + + DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder) + : DepthStencilStateBase(builder), device(device) { + } + + // Framebuffer + + Framebuffer::Framebuffer(Device* device, FramebufferBuilder* builder) + : FramebufferBase(builder), device(device) { + } + + // InputState + + InputState::InputState(Device* device, InputStateBuilder * builder) + : InputStateBase(builder), device(device) { + } + + // Pipeline + + Pipeline::Pipeline(Device* device, PipelineBuilder* builder) + : PipelineBase(builder), device(device) { + } + + // PipelineLayout + + PipelineLayout::PipelineLayout(Device* device, PipelineLayoutBuilder* builder) + : PipelineLayoutBase(builder), device(device) { + } + + // Queue + + Queue::Queue(Device* device, QueueBuilder* builder) + : QueueBase(builder), device(device) { + } + + void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) { + + } + + // RenderPass + + RenderPass::RenderPass(Device* device, RenderPassBuilder* builder) + : RenderPassBase(builder), device(device) { + } + + // Sampler + + Sampler::Sampler(Device* device, SamplerBuilder* builder) + : SamplerBase(builder), device(device) { + } + + // ShaderModule + + ShaderModule::ShaderModule(Device* device, ShaderModuleBuilder* builder) + : ShaderModuleBase(builder), device(device) { + } + + // Texture + + Texture::Texture(Device* device, TextureBuilder* builder) + : TextureBase(builder), device(device) { + } + + // TextureView + + TextureView::TextureView(Device* device, TextureViewBuilder* builder) + : TextureViewBase(builder), device(device) { + } + +} +} diff --git a/src/backend/d3d12/D3D12Backend.h b/src/backend/d3d12/D3D12Backend.h new file mode 100644 index 0000000000..1615bb00ec --- /dev/null +++ b/src/backend/d3d12/D3D12Backend.h @@ -0,0 +1,246 @@ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_D3D12_D3D12BACKEND_H_ +#define BACKEND_D3D12_D3D12BACKEND_H_ + +#include "nxt/nxtcpp.h" + +#include "common/Buffer.h" +#include "common/BindGroup.h" +#include "common/BindGroupLayout.h" +#include "common/CommandBuffer.h" +#include "common/Device.h" +#include "common/Framebuffer.h" +#include "common/DepthStencilState.h" +#include "common/InputState.h" +#include "common/Pipeline.h" +#include "common/PipelineLayout.h" +#include "common/Queue.h" +#include "common/RenderPass.h" +#include "common/Sampler.h" +#include "common/ShaderModule.h" +#include "common/Texture.h" +#include "common/ToBackend.h" + +namespace backend { +namespace d3d12 { + + class BindGroup; + class BindGroupLayout; + class Buffer; + class BufferView; + class CommandBuffer; + class DepthStencilState; + class InputState; + class Pipeline; + class PipelineLayout; + class Queue; + class Sampler; + class ShaderModule; + class Texture; + class TextureView; + class Framebuffer; + class RenderPass; + + struct D3D12BackendTraits { + using BindGroupType = BindGroup; + using BindGroupLayoutType = BindGroupLayout; + using BufferType = Buffer; + using BufferViewType = BufferView; + using CommandBufferType = CommandBuffer; + using DepthStencilStateType = DepthStencilState; + using InputStateType = InputState; + using PipelineType = Pipeline; + using PipelineLayoutType = PipelineLayout; + using QueueType = Queue; + using SamplerType = Sampler; + using ShaderModuleType = ShaderModule; + using TextureType = Texture; + using TextureViewType = TextureView; + using FramebufferType = Framebuffer; + using RenderPassType = RenderPass; + }; + + template + auto ToBackend(T&& common) -> decltype(ToBackendBase(common)) { + return ToBackendBase(common); + } + + // Definition of backend types + class Device : public DeviceBase { + public: + Device(); + ~Device(); + + BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override; + BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override; + BufferBase* CreateBuffer(BufferBuilder* builder) override; + BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override; + CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; + DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override; + InputStateBase* CreateInputState(InputStateBuilder* builder) override; + FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override; + PipelineBase* CreatePipeline(PipelineBuilder* builder) override; + PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override; + QueueBase* CreateQueue(QueueBuilder* builder) override; + RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override; + SamplerBase* CreateSampler(SamplerBuilder* builder) override; + ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override; + TextureBase* CreateTexture(TextureBuilder* builder) override; + TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override; + + // NXT API + void Reference(); + void Release(); + }; + + + class BindGroup : public BindGroupBase { + public: + BindGroup(Device* device, BindGroupBuilder* builder); + + private: + Device* device; + }; + + class BindGroupLayout : public BindGroupLayoutBase { + public: + BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder); + + private: + Device* device; + }; + + class Buffer : public BufferBase { + public: + Buffer(Device* device, BufferBuilder* builder); + + private: + void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override; + + Device* device; + }; + + class BufferView : public BufferViewBase { + public: + BufferView(Device* device, BufferViewBuilder* builder); + + private: + Device* device; + }; + + class CommandBuffer : public CommandBufferBase { + public: + CommandBuffer(Device* device, CommandBufferBuilder* buidler); + + private: + Device* device; + }; + + class Framebuffer : public FramebufferBase { + public: + Framebuffer(Device* device, FramebufferBuilder* builder); + + private: + Device* device; + }; + + class DepthStencilState : public DepthStencilStateBase { + public: + DepthStencilState(Device* device, DepthStencilStateBuilder* builder); + + private: + Device* device; + }; + + class InputState : public InputStateBase { + public: + InputState(Device* device, InputStateBuilder* builder); + + private: + Device* device; + }; + + class Pipeline : public PipelineBase { + public: + Pipeline(Device* device, PipelineBuilder* buidler); + + private: + Device* device; + }; + + class PipelineLayout : public PipelineLayoutBase { + public: + PipelineLayout(Device* device, PipelineLayoutBuilder* builder); + + private: + Device* device; + }; + + class Queue : public QueueBase { + public: + Queue(Device* device, QueueBuilder* builder); + + // NXT API + void Submit(uint32_t numCommands, CommandBuffer* const * commands); + + private: + Device* device; + }; + + class RenderPass : public RenderPassBase { + public: + RenderPass(Device* device, RenderPassBuilder* builder); + + private: + Device* device; + }; + + class Sampler : public SamplerBase { + public: + Sampler(Device* device, SamplerBuilder* builder); + + private: + Device* device; + }; + + class ShaderModule : public ShaderModuleBase { + public: + ShaderModule(Device* device, ShaderModuleBuilder* builder); + + private: + Device* device; + }; + + class Texture : public TextureBase { + public: + Texture(Device* device, TextureBuilder* builder); + + private: + Device* device; + }; + + class TextureView : public TextureViewBase { + public: + TextureView(Device* device, TextureViewBuilder* builder); + + private: + Device* device; + }; + +} +} + +#endif // BACKEND_D3D12_D3D12BACKEND_H_ diff --git a/src/backend/d3d12/GeneratedCodeIncludes.h b/src/backend/d3d12/GeneratedCodeIncludes.h new file mode 100644 index 0000000000..1f553548ed --- /dev/null +++ b/src/backend/d3d12/GeneratedCodeIncludes.h @@ -0,0 +1,15 @@ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "D3D12Backend.h"