diff --git a/src/backend/CMakeLists.txt b/src/backend/CMakeLists.txt index 06eddafce2..3b9abc3988 100644 --- a/src/backend/CMakeLists.txt +++ b/src/backend/CMakeLists.txt @@ -214,8 +214,18 @@ if (WIN32) SetPIC(d3d12_autogen) list(APPEND BACKEND_SOURCES + ${D3D12_DIR}/CommandBufferD3D12.cpp + ${D3D12_DIR}/CommandBufferD3D12.h ${D3D12_DIR}/D3D12Backend.cpp ${D3D12_DIR}/D3D12Backend.h + ${D3D12_DIR}/PipelineD3D12.cpp + ${D3D12_DIR}/PipelineD3D12.h + ${D3D12_DIR}/PipelineLayoutD3D12.cpp + ${D3D12_DIR}/PipelineLayoutD3D12.h + ${D3D12_DIR}/QueueD3D12.cpp + ${D3D12_DIR}/QueueD3D12.h + ${D3D12_DIR}/ShaderModuleD3D12.cpp + ${D3D12_DIR}/ShaderModuleD3D12.h ) endif() diff --git a/src/backend/common/Framebuffer.cpp b/src/backend/common/Framebuffer.cpp index a6ee4551f7..53b5a7b4a1 100644 --- a/src/backend/common/Framebuffer.cpp +++ b/src/backend/common/Framebuffer.cpp @@ -36,6 +36,14 @@ namespace backend { return textureViews[index].Get(); } + uint32_t FramebufferBase::GetWidth() const { + return width; + } + + uint32_t FramebufferBase::GetHeight() const { + return height; + } + // FramebufferBuilder enum FramebufferSetProperties { diff --git a/src/backend/common/Framebuffer.h b/src/backend/common/Framebuffer.h index 1c3af07fe1..53c23aa340 100644 --- a/src/backend/common/Framebuffer.h +++ b/src/backend/common/Framebuffer.h @@ -32,6 +32,8 @@ namespace backend { RenderPassBase* GetRenderPass(); TextureViewBase* GetTextureView(uint32_t index); + uint32_t GetWidth() const; + uint32_t GetHeight() const; private: Ref renderPass; diff --git a/src/backend/d3d12/CommandBufferD3D12.cpp b/src/backend/d3d12/CommandBufferD3D12.cpp new file mode 100644 index 0000000000..f0d5b984fd --- /dev/null +++ b/src/backend/d3d12/CommandBufferD3D12.cpp @@ -0,0 +1,185 @@ +// 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 "CommandBufferD3D12.h" + +#include "common/Commands.h" +#include "D3D12Backend.h" +#include "PipelineD3D12.h" +#include "PipelineLayoutD3D12.h" + +namespace backend { +namespace d3d12 { + + CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder) + : CommandBufferBase(builder), device(device), commands(builder->AcquireCommands()) { + } + + CommandBuffer::~CommandBuffer() { + FreeCommands(&commands); + } + + void CommandBuffer::FillCommands(ComPtr commandList) { + Command type; + Pipeline* lastPipeline = nullptr; + + RenderPass* currentRenderPass = nullptr; + Framebuffer* currentFramebuffer = nullptr; + + while(commands.NextCommandId(&type)) { + switch (type) { + case Command::AdvanceSubpass: + { + commands.NextCommand(); + } + break; + + case Command::BeginRenderPass: + { + BeginRenderPassCmd* beginRenderPassCmd = commands.NextCommand(); + currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get()); + currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get()); + + float width = (float) currentFramebuffer->GetWidth(); + float height = (float) currentFramebuffer->GetHeight(); + D3D12_VIEWPORT viewport = { 0.f, 0.f, width, height, 0.f, 1.f }; + D3D12_RECT scissorRect = { 0.f, 0.f, width, height }; + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + // TODO(enga@google.com): Set the back buffer as the render target only when a new render target is set + D3D12_RESOURCE_BARRIER resourceBarrier; + resourceBarrier.Transition.pResource = device->GetNextRenderTarget().Get(); + resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + resourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + commandList->ResourceBarrier(1, &resourceBarrier); + commandList->OMSetRenderTargets(1, &device->GetNextRenderTargetDescriptor(), FALSE, nullptr); + } + break; + + case Command::CopyBufferToTexture: + { + CopyBufferToTextureCmd* copy = commands.NextCommand(); + } + break; + + case Command::Dispatch: + { + DispatchCmd* dispatch = commands.NextCommand(); + + ASSERT(lastPipeline->IsCompute()); + commandList->Dispatch(dispatch->x, dispatch->y, dispatch->z); + } + break; + + case Command::DrawArrays: + { + DrawArraysCmd* draw = commands.NextCommand(); + + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + commandList->DrawInstanced( + draw->vertexCount, + draw->instanceCount, + draw->firstVertex, + draw->firstInstance + ); + } + break; + + case Command::DrawElements: + { + DrawElementsCmd* draw = commands.NextCommand(); + } + break; + + case Command::EndRenderPass: + { + EndRenderPassCmd* cmd = commands.NextCommand(); + + // TODO(enga@google.com): Present the back buffer only before swap + D3D12_RESOURCE_BARRIER resourceBarrier; + resourceBarrier.Transition.pResource = device->GetNextRenderTarget().Get(); + resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + resourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + commandList->ResourceBarrier(1, &resourceBarrier); + } + break; + + case Command::SetPipeline: + { + SetPipelineCmd* cmd = commands.NextCommand(); + lastPipeline = ToBackend(cmd->pipeline).Get(); + PipelineLayout* pipelineLayout = ToBackend(lastPipeline->GetLayout()); + + // TODO + if (lastPipeline->IsCompute()) { + } else { + commandList->SetGraphicsRootSignature(pipelineLayout->GetRootSignature().Get()); + commandList->SetPipelineState(lastPipeline->GetRenderPipelineState().Get()); + } + } + break; + + case Command::SetPushConstants: + { + SetPushConstantsCmd* cmd = commands.NextCommand(); + } + break; + + case Command::SetStencilReference: + { + SetStencilReferenceCmd* cmd = commands.NextCommand(); + } + break; + + case Command::SetBindGroup: + { + SetBindGroupCmd* cmd = commands.NextCommand(); + } + break; + + case Command::SetIndexBuffer: + { + SetIndexBufferCmd* cmd = commands.NextCommand(); + } + break; + + case Command::SetVertexBuffers: + { + SetVertexBuffersCmd* cmd = commands.NextCommand(); + } + break; + + case Command::TransitionBufferUsage: + { + TransitionBufferUsageCmd* cmd = commands.NextCommand(); + } + break; + + case Command::TransitionTextureUsage: + { + TransitionTextureUsageCmd* cmd = commands.NextCommand(); + } + break; + } + } + } +} +} diff --git a/src/backend/d3d12/CommandBufferD3D12.h b/src/backend/d3d12/CommandBufferD3D12.h new file mode 100644 index 0000000000..c9e434de76 --- /dev/null +++ b/src/backend/d3d12/CommandBufferD3D12.h @@ -0,0 +1,42 @@ +// 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_COMMANDBUFFERD3D12_H_ +#define BACKEND_D3D12_COMMANDBUFFERD3D12_H_ + +#include "common/CommandAllocator.h" +#include "common/CommandBuffer.h" + +#include "d3d12_platform.h" + +namespace backend { +namespace d3d12 { + + class Device; + + class CommandBuffer : public CommandBufferBase { + public: + CommandBuffer(Device* device, CommandBufferBuilder* builder); + ~CommandBuffer(); + + void FillCommands(ComPtr commandList); + + private: + Device* device; + CommandIterator commands; + }; +} +} + +#endif // BACKEND_D3D12_COMMANDBUFFERD3D12_H_ diff --git a/src/backend/d3d12/D3D12Backend.cpp b/src/backend/d3d12/D3D12Backend.cpp index b82a0fa841..039230b0dc 100644 --- a/src/backend/d3d12/D3D12Backend.cpp +++ b/src/backend/d3d12/D3D12Backend.cpp @@ -14,6 +14,12 @@ #include "D3D12Backend.h" +#include "CommandBufferD3D12.h" +#include "PipelineD3D12.h" +#include "PipelineLayoutD3D12.h" +#include "QueueD3D12.h" +#include "ShaderModuleD3D12.h" + namespace backend { namespace d3d12 { @@ -45,19 +51,6 @@ namespace d3d12 { queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ASSERT_SUCCESS(d3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue))); - - // Create an empty root signature. - D3D12_ROOT_SIGNATURE_DESC rootSignatureDescriptor; - rootSignatureDescriptor.NumParameters = 0; - rootSignatureDescriptor.pParameters = nullptr; - rootSignatureDescriptor.NumStaticSamplers = 0; - rootSignatureDescriptor.pStaticSamplers = nullptr; - rootSignatureDescriptor.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - - ComPtr signature; - ComPtr error; - ASSERT_SUCCESS(D3D12SerializeRootSignature(&rootSignatureDescriptor, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); - ASSERT_SUCCESS(d3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature))); } Device::~Device() { @@ -67,15 +60,11 @@ namespace d3d12 { return d3d12Device; } - ComPtr Device::GetRootSignature() { - return rootSignature; - } - ComPtr Device::GetCommandQueue() { return commandQueue; } - Microsoft::WRL::ComPtr Device::GetNextRenderTarget() { + ComPtr Device::GetNextRenderTarget() { return renderTargetResource; } @@ -170,12 +159,6 @@ namespace d3d12 { : BufferViewBase(builder), device(device) { } - // CommandBuffer - - CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder) - : CommandBufferBase(builder), device(device) { - } - // DepthStencilState DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder) @@ -194,28 +177,6 @@ namespace d3d12 { : 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) @@ -228,12 +189,6 @@ namespace d3d12 { : SamplerBase(builder), device(device) { } - // ShaderModule - - ShaderModule::ShaderModule(Device* device, ShaderModuleBuilder* builder) - : ShaderModuleBase(builder), device(device) { - } - // Texture Texture::Texture(Device* device, TextureBuilder* builder) diff --git a/src/backend/d3d12/D3D12Backend.h b/src/backend/d3d12/D3D12Backend.h index 85b4fac312..f319921d22 100644 --- a/src/backend/d3d12/D3D12Backend.h +++ b/src/backend/d3d12/D3D12Backend.h @@ -20,17 +20,14 @@ #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" @@ -85,7 +82,7 @@ namespace d3d12 { // Definition of backend types class Device : public DeviceBase { public: - Device(Microsoft::WRL::ComPtr d3d12Device); + Device(ComPtr d3d12Device); ~Device(); BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override; @@ -105,23 +102,21 @@ namespace d3d12 { TextureBase* CreateTexture(TextureBuilder* builder) override; TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override; - Microsoft::WRL::ComPtr GetD3D12Device(); - Microsoft::WRL::ComPtr GetRootSignature(); - Microsoft::WRL::ComPtr GetCommandQueue(); - Microsoft::WRL::ComPtr GetNextRenderTarget(); + ComPtr GetD3D12Device(); + ComPtr GetCommandQueue(); + ComPtr GetNextRenderTarget(); D3D12_CPU_DESCRIPTOR_HANDLE GetNextRenderTargetDescriptor(); - void SetNextRenderTarget(Microsoft::WRL::ComPtr renderTargetResource, D3D12_CPU_DESCRIPTOR_HANDLE renderTargetDescriptor); + void SetNextRenderTarget(ComPtr renderTargetResource, D3D12_CPU_DESCRIPTOR_HANDLE renderTargetDescriptor); // NXT API void Reference(); void Release(); private: - Microsoft::WRL::ComPtr d3d12Device; - Microsoft::WRL::ComPtr commandQueue; - Microsoft::WRL::ComPtr rootSignature; - Microsoft::WRL::ComPtr renderTargetResource; + ComPtr d3d12Device; + ComPtr commandQueue; + ComPtr renderTargetResource; D3D12_CPU_DESCRIPTOR_HANDLE renderTargetDescriptor; }; @@ -160,14 +155,6 @@ namespace d3d12 { 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); @@ -192,33 +179,6 @@ namespace d3d12 { 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); @@ -235,14 +195,6 @@ namespace d3d12 { 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); diff --git a/src/backend/d3d12/GeneratedCodeIncludes.h b/src/backend/d3d12/GeneratedCodeIncludes.h index 1f553548ed..f2e322f3d4 100644 --- a/src/backend/d3d12/GeneratedCodeIncludes.h +++ b/src/backend/d3d12/GeneratedCodeIncludes.h @@ -13,3 +13,8 @@ // limitations under the License. #include "D3D12Backend.h" +#include "CommandBufferD3D12.h" +#include "PipelineD3D12.h" +#include "PipelineLayoutD3D12.h" +#include "QueueD3D12.h" +#include "ShaderModuleD3D12.h" diff --git a/src/backend/d3d12/PipelineD3D12.cpp b/src/backend/d3d12/PipelineD3D12.cpp new file mode 100644 index 0000000000..be9562a9cc --- /dev/null +++ b/src/backend/d3d12/PipelineD3D12.cpp @@ -0,0 +1,162 @@ +// 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 "PipelineD3D12.h" + +#include "D3D12Backend.h" +#include "ShaderModuleD3D12.h" +#include "PipelineLayoutD3D12.h" + +#include + +using Microsoft::WRL::ComPtr; + +namespace backend { +namespace d3d12 { + + Pipeline::Pipeline(Device* device, PipelineBuilder* builder) : PipelineBase(builder), device(device) { + uint32_t compileFlags = 0; +#if defined(_DEBUG) + // Enable better shader debugging with the graphics debugging tools. + compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + if (IsCompute()) { + const auto& module = ToBackend(builder->GetStageInfo(nxt::ShaderStage::Compute).module); + const auto& entryPoint = builder->GetStageInfo(nxt::ShaderStage::Compute).entryPoint; + const auto& hlslSource = module->GetHLSLSource(); + + ComPtr compiledShader; + ComPtr errors; + + if(FAILED(D3DCompile( + hlslSource.c_str(), + hlslSource.length(), + nullptr, + { nullptr }, + nullptr, + entryPoint.c_str(), + "cs_5_0", + compileFlags, + 0, + &compiledShader, + &errors + ))) { + printf("%s\n", errors->GetBufferPointer()); + ASSERT(false); + } + + D3D12_COMPUTE_PIPELINE_STATE_DESC descriptor = {}; + descriptor.pRootSignature = ToBackend(GetLayout())->GetRootSignature().Get(); + descriptor.CS.pShaderBytecode = compiledShader->GetBufferPointer(); + descriptor.CS.BytecodeLength = compiledShader->GetBufferSize(); + + device->GetD3D12Device()->CreateComputePipelineState(&descriptor, IID_PPV_ARGS(&computePipelineState)); + + } else { + D3D12_GRAPHICS_PIPELINE_STATE_DESC descriptor = {}; + + PerStage> compiledShader; + ComPtr errors; + + for (auto stage : IterateStages(GetStageMask())) { + const auto& module = ToBackend(builder->GetStageInfo(stage).module); + const auto& entryPoint = builder->GetStageInfo(stage).entryPoint; + const auto& hlslSource = module->GetHLSLSource(); + + const char* compileTarget = nullptr; + + D3D12_SHADER_BYTECODE* shader = nullptr; + switch (stage) { + case nxt::ShaderStage::Vertex: + shader = &descriptor.VS; + compileTarget = "vs_5_0"; + break; + case nxt::ShaderStage::Fragment: + shader = &descriptor.PS; + compileTarget = "ps_5_0"; + break; + case nxt::ShaderStage::Compute: + ASSERT(false); + break; + } + + if(FAILED(D3DCompile( + hlslSource.c_str(), + hlslSource.length(), + nullptr, + nullptr, + nullptr, + entryPoint.c_str(), + compileTarget, + compileFlags, + 0, + &compiledShader[stage], + &errors + ))) { + printf("%s\n", errors->GetBufferPointer()); + ASSERT(false); + } + + if (shader != nullptr) { + shader->pShaderBytecode = compiledShader[stage]->GetBufferPointer(); + shader->BytecodeLength = compiledShader[stage]->GetBufferSize(); + } + } + + descriptor.pRootSignature = ToBackend(GetLayout())->GetRootSignature().Get(); + + descriptor.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; + descriptor.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; + descriptor.RasterizerState.FrontCounterClockwise = FALSE; + descriptor.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + descriptor.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + descriptor.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + descriptor.RasterizerState.DepthClipEnable = TRUE; + descriptor.RasterizerState.MultisampleEnable = FALSE; + descriptor.RasterizerState.AntialiasedLineEnable = FALSE; + descriptor.RasterizerState.ForcedSampleCount = 0; + descriptor.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + + descriptor.BlendState.AlphaToCoverageEnable = FALSE; + descriptor.BlendState.IndependentBlendEnable = FALSE; + descriptor.BlendState.RenderTarget[0].BlendEnable = FALSE; + descriptor.BlendState.RenderTarget[0].LogicOpEnable = FALSE; + descriptor.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; + descriptor.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO; + descriptor.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; + descriptor.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; + descriptor.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; + descriptor.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; + descriptor.BlendState.RenderTarget[0].LogicOp = D3D12_LOGIC_OP_NOOP; + descriptor.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + + descriptor.DepthStencilState.DepthEnable = false; + descriptor.DepthStencilState.StencilEnable = false; + descriptor.SampleMask = UINT_MAX; + descriptor.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + descriptor.NumRenderTargets = 1; + descriptor.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + descriptor.SampleDesc.Count = 1; + + ASSERT_SUCCESS(device->GetD3D12Device()->CreateGraphicsPipelineState(&descriptor, IID_PPV_ARGS(&renderPipelineState))); + } + } + + ComPtr Pipeline::GetRenderPipelineState() { + return renderPipelineState; + } + +} +} diff --git a/src/backend/d3d12/PipelineD3D12.h b/src/backend/d3d12/PipelineD3D12.h new file mode 100644 index 0000000000..ec88b46084 --- /dev/null +++ b/src/backend/d3d12/PipelineD3D12.h @@ -0,0 +1,44 @@ +// 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_PIPELINED3D12_H_ +#define BACKEND_D3D12_PIPELINED3D12_H_ + +#include "common/Pipeline.h" + +#include "d3d12_platform.h" + +namespace backend { +namespace d3d12 { + + class Device; + class ShaderModule; + + class Pipeline : public PipelineBase { + public: + Pipeline(Device* device, PipelineBuilder* builder); + + ComPtr GetRenderPipelineState(); + + private: + Device* device; + + ComPtr renderPipelineState; + ComPtr computePipelineState; + }; + +} +} + +#endif // BACKEND_D3D12_PIPELINED3D12_H_ diff --git a/src/backend/d3d12/PipelineLayoutD3D12.cpp b/src/backend/d3d12/PipelineLayoutD3D12.cpp new file mode 100644 index 0000000000..f5ba6c7531 --- /dev/null +++ b/src/backend/d3d12/PipelineLayoutD3D12.cpp @@ -0,0 +1,46 @@ +// 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 "PipelineLayoutD3D12.h" + +#include "D3D12Backend.h" + +using Microsoft::WRL::ComPtr; + +namespace backend { +namespace d3d12 { + + PipelineLayout::PipelineLayout(Device* device, PipelineLayoutBuilder* builder) + : PipelineLayoutBase(builder), device(device) { + + // Create an empty root signature. + D3D12_ROOT_SIGNATURE_DESC rootSignatureDescriptor; + rootSignatureDescriptor.NumParameters = 0; + rootSignatureDescriptor.pParameters = nullptr; + rootSignatureDescriptor.NumStaticSamplers = 0; + rootSignatureDescriptor.pStaticSamplers = nullptr; + rootSignatureDescriptor.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + + ComPtr signature; + ComPtr error; + ASSERT_SUCCESS(D3D12SerializeRootSignature(&rootSignatureDescriptor, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); + ASSERT_SUCCESS(device->GetD3D12Device()->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature))); + } + + ComPtr PipelineLayout::GetRootSignature() { + return rootSignature; + } + +} +} diff --git a/src/backend/d3d12/PipelineLayoutD3D12.h b/src/backend/d3d12/PipelineLayoutD3D12.h new file mode 100644 index 0000000000..57dd4ef36e --- /dev/null +++ b/src/backend/d3d12/PipelineLayoutD3D12.h @@ -0,0 +1,42 @@ +// 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_PIPELINELAYOUTD3D12_H_ +#define BACKEND_D3D12_PIPELINELAYOUTD3D12_H_ + +#include "common/PipelineLayout.h" + +#include "d3d12_platform.h" + +namespace backend { +namespace d3d12 { + + class Device; + + class PipelineLayout : public PipelineLayoutBase { + public: + PipelineLayout(Device* device, PipelineLayoutBuilder* builder); + + ComPtr GetRootSignature(); + + private: + Device* device; + + ComPtr rootSignature; + }; + +} +} + +#endif // BACKEND_D3D12_PIPELINELAYOUTD3D12_H_ diff --git a/src/backend/d3d12/QueueD3D12.cpp b/src/backend/d3d12/QueueD3D12.cpp new file mode 100644 index 0000000000..aaa1c3cf79 --- /dev/null +++ b/src/backend/d3d12/QueueD3D12.cpp @@ -0,0 +1,52 @@ +// 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 "QueueD3D12.h" + +#include "D3D12Backend.h" +#include "CommandBufferD3D12.h" + +namespace backend { +namespace d3d12 { + + Queue::Queue(Device* device, QueueBuilder* builder) + : QueueBase(builder), device(device) { + + ASSERT_SUCCESS(device->GetD3D12Device()->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocator))); + ASSERT_SUCCESS(device->GetD3D12Device()->CreateCommandList( + 0, + D3D12_COMMAND_LIST_TYPE_DIRECT, + commandAllocator.Get(), + nullptr, + IID_PPV_ARGS(&commandList) + )); + ASSERT_SUCCESS(commandList->Close()); + } + + void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) { + ASSERT_SUCCESS(commandAllocator->Reset()); + ASSERT_SUCCESS(commandList->Reset(commandAllocator.Get(), NULL)); + + for (uint32_t i = 0; i < numCommands; ++i) { + commands[i]->FillCommands(commandList); + } + + ASSERT_SUCCESS(commandList->Close()); + + ID3D12CommandList* commandLists[] = { commandList.Get() }; + device->GetCommandQueue()->ExecuteCommandLists(_countof(commandLists), commandLists); + } + +} +} diff --git a/src/backend/d3d12/QueueD3D12.h b/src/backend/d3d12/QueueD3D12.h new file mode 100644 index 0000000000..4c36230259 --- /dev/null +++ b/src/backend/d3d12/QueueD3D12.h @@ -0,0 +1,45 @@ +// 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_QUEUED3D12_H_ +#define BACKEND_D3D12_QUEUED3D12_H_ + +#include "common/Queue.h" + +#include "d3d12_platform.h" + +namespace backend { +namespace d3d12 { + + class Device; + class CommandBuffer; + + class Queue : public QueueBase { + public: + Queue(Device* device, QueueBuilder* builder); + + // NXT API + void Submit(uint32_t numCommands, CommandBuffer* const * commands); + + private: + Device* device; + + ComPtr commandAllocator; + ComPtr commandList; + }; + +} +} + +#endif // BACKEND_D3D12_QUEUED3D12_H_ diff --git a/src/backend/d3d12/ShaderModuleD3D12.cpp b/src/backend/d3d12/ShaderModuleD3D12.cpp new file mode 100644 index 0000000000..44784989b7 --- /dev/null +++ b/src/backend/d3d12/ShaderModuleD3D12.cpp @@ -0,0 +1,43 @@ +// 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 "ShaderModuleD3D12.h" + +#include + +namespace backend { +namespace d3d12 { + + ShaderModule::ShaderModule(Device* device, ShaderModuleBuilder* builder) + : ShaderModuleBase(builder), device(device) { + spirv_cross::CompilerHLSL compiler(builder->AcquireSpirv()); + + spirv_cross::CompilerHLSL::Options options; + options.shader_model = 40; + options.flip_vert_y = false; + options.fixup_clipspace = true; + + compiler.set_options(options); + + ExtractSpirvInfo(compiler); + + hlslSource = compiler.compile(); + } + + const std::string& ShaderModule::GetHLSLSource() const { + return hlslSource; + } + +} +} diff --git a/src/backend/d3d12/ShaderModuleD3D12.h b/src/backend/d3d12/ShaderModuleD3D12.h new file mode 100644 index 0000000000..d703cd8b80 --- /dev/null +++ b/src/backend/d3d12/ShaderModuleD3D12.h @@ -0,0 +1,40 @@ +// 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_SHADERMODULED3D12_H_ +#define BACKEND_D3D12_SHADERMODULED3D12_H_ + +#include "common/ShaderModule.h" + +namespace backend { +namespace d3d12 { + + class Device; + + class ShaderModule : public ShaderModuleBase { + public: + ShaderModule(Device* device, ShaderModuleBuilder* builder); + + const std::string& GetHLSLSource() const; + + private: + Device* device; + + std::string hlslSource; + }; + +} +} + +#endif // BACKEND_D3D12_SHADERMODULED3D12_H_ diff --git a/src/backend/metal/MetalBackend.mm b/src/backend/metal/MetalBackend.mm index 80aacf6eb5..4922dcc106 100644 --- a/src/backend/metal/MetalBackend.mm +++ b/src/backend/metal/MetalBackend.mm @@ -259,7 +259,8 @@ namespace metal { id compute = nil; id render = nil; - BeginRenderPassCmd* currentRenderPass = nullptr; + RenderPass* currentRenderPass = nullptr; + Framebuffer* currentFramebuffer = nullptr; void FinishEncoders() { ASSERT(render == nil); @@ -293,8 +294,7 @@ namespace metal { render = nil; } - const auto& info = currentRenderPass->renderPass->GetSubpassInfo(subpass); - auto& framebuffer = currentRenderPass->framebuffer; + const auto& info = currentRenderPass->GetSubpassInfo(subpass); MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor]; bool usingBackbuffer = false; // HACK(kainino@chromium.org): workaround for not having depth attachments @@ -305,7 +305,7 @@ namespace metal { // falls back to the 'back buffer' but this should go away // when we have WSI. id texture = nil; - if (auto textureView = framebuffer->GetTextureView(attachment)) { + if (auto textureView = currentFramebuffer->GetTextureView(attachment)) { texture = ToBackend(textureView->GetTexture())->GetMTLTexture(); } else { texture = device->GetCurrentTexture(); @@ -359,7 +359,9 @@ namespace metal { case Command::BeginRenderPass: { - encoders.currentRenderPass = commands.NextCommand(); + BeginRenderPassCmd* beginRenderPassCmd = commands.NextCommand(); + encoders.currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get()); + encoders.currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get()); encoders.FinishEncoders(); currentSubpass = 0; encoders.BeginSubpass(commandBuffer, currentSubpass);