D3D12 vertex and index buffers with resource transitions

This commit is contained in:
Austin Eng 2017-06-09 12:50:51 -04:00 committed by Austin Eng
parent 459537491b
commit d251356783
11 changed files with 561 additions and 177 deletions

View File

@ -216,10 +216,14 @@ if (WIN32)
SetPIC(d3d12_autogen)
list(APPEND BACKEND_SOURCES
${D3D12_DIR}/BufferD3D12.cpp
${D3D12_DIR}/BufferD3D12.h
${D3D12_DIR}/CommandBufferD3D12.cpp
${D3D12_DIR}/CommandBufferD3D12.h
${D3D12_DIR}/D3D12Backend.cpp
${D3D12_DIR}/D3D12Backend.h
${D3D12_DIR}/InputStateD3D12.cpp
${D3D12_DIR}/InputStateD3D12.h
${D3D12_DIR}/PipelineD3D12.cpp
${D3D12_DIR}/PipelineD3D12.h
${D3D12_DIR}/PipelineLayoutD3D12.cpp

View File

@ -0,0 +1,163 @@
// 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 "BufferD3D12.h"
#include "D3D12Backend.h"
namespace backend {
namespace d3d12 {
namespace {
D3D12_RESOURCE_STATES D3D12BufferUsage(nxt::BufferUsageBit usage) {
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON;
if (usage & nxt::BufferUsageBit::TransferSrc) {
resourceState |= D3D12_RESOURCE_STATE_COPY_SOURCE;
}
if (usage & nxt::BufferUsageBit::TransferDst) {
resourceState |= D3D12_RESOURCE_STATE_COPY_DEST;
}
if (usage & (nxt::BufferUsageBit::Vertex | nxt::BufferUsageBit::Uniform)) {
resourceState |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
}
if (usage & nxt::BufferUsageBit::Index) {
resourceState |= D3D12_RESOURCE_STATE_INDEX_BUFFER;
}
if (usage & nxt::BufferUsageBit::Storage) {
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
}
return resourceState;
}
}
Buffer::Buffer(Device* device, BufferBuilder* builder)
: BufferBase(builder), device(device) {
D3D12_RESOURCE_DESC resourceDescriptor;
resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
resourceDescriptor.Alignment = 0;
resourceDescriptor.Width = GetSize();
resourceDescriptor.Height = 1;
resourceDescriptor.DepthOrArraySize = 1;
resourceDescriptor.MipLevels = 1;
resourceDescriptor.Format = DXGI_FORMAT_UNKNOWN;
resourceDescriptor.SampleDesc.Count = 1;
resourceDescriptor.SampleDesc.Quality = 0;
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
resourceDescriptor.Flags = D3D12_RESOURCE_FLAG_NONE;
{
D3D12_HEAP_PROPERTIES heapProperties;
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProperties.CreationNodeMask = 0;
heapProperties.VisibleNodeMask = 0;
ASSERT_SUCCESS(device->GetD3D12Device()->CreateCommittedResource(
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&resourceDescriptor,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&uploadResource)
));
}
{
D3D12_HEAP_PROPERTIES heapProperties;
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProperties.CreationNodeMask = 0;
heapProperties.VisibleNodeMask = 0;
ASSERT_SUCCESS(device->GetD3D12Device()->CreateCommittedResource(
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&resourceDescriptor,
D3D12BufferUsage(GetUsage()),
nullptr,
IID_PPV_ARGS(&resource)
));
}
}
ComPtr<ID3D12Resource> Buffer::GetD3D12Resource() {
return resource;
}
bool Buffer::GetResourceTransitionBarrier(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier) {
D3D12_RESOURCE_STATES stateBefore = D3D12BufferUsage(currentUsage);
D3D12_RESOURCE_STATES stateAfter = D3D12BufferUsage(targetUsage);
if (stateBefore == stateAfter) {
return false;
}
barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier->Transition.pResource = resource.Get();
barrier->Transition.StateBefore = stateBefore;
barrier->Transition.StateAfter = stateAfter;
barrier->Transition.Subresource = 0;
return true;
}
D3D12_GPU_VIRTUAL_ADDRESS Buffer::GetVA() const {
return resource->GetGPUVirtualAddress();
}
void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) {
uint32_t begin = start * sizeof(uint32_t);
uint32_t end = (start + count) * sizeof(uint32_t);
uint8_t* mappedResource = nullptr;
D3D12_RANGE readRange;
readRange.Begin = 0;
readRange.End = 0;
ASSERT_SUCCESS(uploadResource->Map(0, &readRange, reinterpret_cast<void**>(&mappedResource)));
memcpy(&mappedResource[begin], data, end - begin);
D3D12_RANGE writeRange;
writeRange.Begin = begin;
writeRange.End = end;
uploadResource->Unmap(0, &writeRange);
device->GetPendingCommandList()->CopyBufferRegion(resource.Get(), begin, uploadResource.Get(), begin, end - begin);
}
void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) {
// TODO(cwallez@chromium.org): Implement Map Read for the null backend
}
void Buffer::UnmapImpl() {
// TODO(cwallez@chromium.org): Implement Map Read for the null backend
}
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) {
D3D12_RESOURCE_BARRIER barrier;
if (GetResourceTransitionBarrier(currentUsage, targetUsage, &barrier)) {
device->GetPendingCommandList()->ResourceBarrier(1, &barrier);
}
}
}
}

View File

@ -0,0 +1,51 @@
// 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_BUFFERD3D12_H_
#define BACKEND_D3D12_BUFFERD3D12_H_
#include "common/Buffer.h"
#include "d3d12_platform.h"
namespace backend {
namespace d3d12 {
class Device;
class Buffer : public BufferBase {
public:
Buffer(Device* device, BufferBuilder* builder);
ComPtr<ID3D12Resource> GetD3D12Resource();
D3D12_GPU_VIRTUAL_ADDRESS GetVA() const;
bool GetResourceTransitionBarrier(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier);
private:
Device* device;
ComPtr<ID3D12Resource> uploadResource;
ComPtr<ID3D12Resource> resource;
// NXT API
void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override;
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
void UnmapImpl() override;
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) override;
};
}
}
#endif // BACKEND_D3D12_BUFFERD3D12_H_

View File

@ -16,156 +16,212 @@
#include "common/Commands.h"
#include "D3D12Backend.h"
#include "BufferD3D12.h"
#include "InputStateD3D12.h"
#include "PipelineD3D12.h"
#include "PipelineLayoutD3D12.h"
namespace backend {
namespace d3d12 {
CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder)
: CommandBufferBase(builder), device(device), commands(builder->AcquireCommands()) {
}
namespace {
DXGI_FORMAT DXGIIndexFormat(nxt::IndexFormat format) {
switch (format) {
case nxt::IndexFormat::Uint16:
return DXGI_FORMAT_R16_UINT;
case nxt::IndexFormat::Uint32:
return DXGI_FORMAT_R32_UINT;
}
}
}
CommandBuffer::~CommandBuffer() {
FreeCommands(&commands);
}
CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder)
: CommandBufferBase(builder), device(device), commands(builder->AcquireCommands()) {
}
void CommandBuffer::FillCommands(ComPtr<ID3D12GraphicsCommandList> commandList) {
Command type;
Pipeline* lastPipeline = nullptr;
CommandBuffer::~CommandBuffer() {
FreeCommands(&commands);
}
RenderPass* currentRenderPass = nullptr;
Framebuffer* currentFramebuffer = nullptr;
void CommandBuffer::FillCommands(ComPtr<ID3D12GraphicsCommandList> commandList) {
Command type;
Pipeline* lastPipeline = nullptr;
while(commands.NextCommandId(&type)) {
switch (type) {
case Command::AdvanceSubpass:
{
commands.NextCommand<AdvanceSubpassCmd>();
}
break;
RenderPass* currentRenderPass = nullptr;
Framebuffer* currentFramebuffer = nullptr;
case Command::BeginRenderPass:
{
BeginRenderPassCmd* beginRenderPassCmd = commands.NextCommand<BeginRenderPassCmd>();
currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get());
currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get());
while(commands.NextCommandId(&type)) {
switch (type) {
case Command::AdvanceSubpass:
{
commands.NextCommand<AdvanceSubpassCmd>();
}
break;
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);
commandList->OMSetRenderTargets(1, &device->GetCurrentRenderTargetDescriptor(), FALSE, nullptr);
}
break;
case Command::BeginRenderPass:
{
BeginRenderPassCmd* beginRenderPassCmd = commands.NextCommand<BeginRenderPassCmd>();
currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get());
currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get());
case Command::CopyBufferToBuffer:
{
CopyBufferToBufferCmd* copy = commands.NextCommand<CopyBufferToBufferCmd>();
}
break;
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);
commandList->OMSetRenderTargets(1, &device->GetCurrentRenderTargetDescriptor(), FALSE, nullptr);
}
break;
case Command::CopyBufferToBuffer:
{
CopyBufferToBufferCmd* copy = commands.NextCommand<CopyBufferToBufferCmd>();
}
break;
case Command::CopyBufferToTexture:
{
CopyBufferToTextureCmd* copy = commands.NextCommand<CopyBufferToTextureCmd>();
}
break;
case Command::CopyBufferToTexture:
{
CopyBufferToTextureCmd* copy = commands.NextCommand<CopyBufferToTextureCmd>();
}
break;
case Command::Dispatch:
{
DispatchCmd* dispatch = commands.NextCommand<DispatchCmd>();
case Command::Dispatch:
{
DispatchCmd* dispatch = commands.NextCommand<DispatchCmd>();
ASSERT(lastPipeline->IsCompute());
commandList->Dispatch(dispatch->x, dispatch->y, dispatch->z);
}
break;
ASSERT(lastPipeline->IsCompute());
commandList->Dispatch(dispatch->x, dispatch->y, dispatch->z);
}
break;
case Command::DrawArrays:
{
DrawArraysCmd* draw = commands.NextCommand<DrawArraysCmd>();
case Command::DrawArrays:
{
DrawArraysCmd* draw = commands.NextCommand<DrawArraysCmd>();
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
commandList->DrawInstanced(
draw->vertexCount,
draw->instanceCount,
draw->firstVertex,
draw->firstInstance
);
}
break;
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
commandList->DrawInstanced(
draw->vertexCount,
draw->instanceCount,
draw->firstVertex,
draw->firstInstance
);
}
break;
case Command::DrawElements:
{
DrawElementsCmd* draw = commands.NextCommand<DrawElementsCmd>();
}
break;
case Command::DrawElements:
{
DrawElementsCmd* draw = commands.NextCommand<DrawElementsCmd>();
case Command::EndRenderPass:
{
EndRenderPassCmd* cmd = commands.NextCommand<EndRenderPassCmd>();
}
break;
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
commandList->DrawIndexedInstanced(
draw->indexCount,
draw->instanceCount,
draw->firstIndex,
0,
draw->firstInstance
);
}
break;
case Command::SetPipeline:
{
SetPipelineCmd* cmd = commands.NextCommand<SetPipelineCmd>();
lastPipeline = ToBackend(cmd->pipeline).Get();
PipelineLayout* pipelineLayout = ToBackend(lastPipeline->GetLayout());
case Command::EndRenderPass:
{
EndRenderPassCmd* cmd = commands.NextCommand<EndRenderPassCmd>();
}
break;
// TODO
if (lastPipeline->IsCompute()) {
} else {
commandList->SetGraphicsRootSignature(pipelineLayout->GetRootSignature().Get());
commandList->SetPipelineState(lastPipeline->GetRenderPipelineState().Get());
}
}
break;
case Command::SetPipeline:
{
SetPipelineCmd* cmd = commands.NextCommand<SetPipelineCmd>();
lastPipeline = ToBackend(cmd->pipeline).Get();
PipelineLayout* pipelineLayout = ToBackend(lastPipeline->GetLayout());
case Command::SetPushConstants:
{
SetPushConstantsCmd* cmd = commands.NextCommand<SetPushConstantsCmd>();
}
break;
// TODO
if (lastPipeline->IsCompute()) {
} else {
commandList->SetGraphicsRootSignature(pipelineLayout->GetRootSignature().Get());
commandList->SetPipelineState(lastPipeline->GetRenderPipelineState().Get());
}
}
break;
case Command::SetStencilReference:
case Command::SetPushConstants:
{
SetPushConstantsCmd* cmd = commands.NextCommand<SetPushConstantsCmd>();
}
break;
case Command::SetStencilReference:
{
SetStencilReferenceCmd* cmd = commands.NextCommand<SetStencilReferenceCmd>();
}
break;
case Command::SetBindGroup:
{
SetBindGroupCmd* cmd = commands.NextCommand<SetBindGroupCmd>();
}
break;
case Command::SetBindGroup:
{
SetBindGroupCmd* cmd = commands.NextCommand<SetBindGroupCmd>();
}
break;
case Command::SetIndexBuffer:
{
SetIndexBufferCmd* cmd = commands.NextCommand<SetIndexBufferCmd>();
}
break;
case Command::SetIndexBuffer:
{
SetIndexBufferCmd* cmd = commands.NextCommand<SetIndexBufferCmd>();
case Command::SetVertexBuffers:
{
SetVertexBuffersCmd* cmd = commands.NextCommand<SetVertexBuffersCmd>();
}
break;
Buffer* buffer = ToBackend(cmd->buffer.Get());
D3D12_INDEX_BUFFER_VIEW bufferView;
bufferView.BufferLocation = buffer->GetVA() + cmd->offset;
bufferView.SizeInBytes = buffer->GetSize() - cmd->offset;
bufferView.Format = DXGIIndexFormat(cmd->format);
case Command::TransitionBufferUsage:
{
TransitionBufferUsageCmd* cmd = commands.NextCommand<TransitionBufferUsageCmd>();
}
break;
commandList->IASetIndexBuffer(&bufferView);
}
break;
case Command::TransitionTextureUsage:
{
TransitionTextureUsageCmd* cmd = commands.NextCommand<TransitionTextureUsageCmd>();
}
break;
}
}
}
case Command::SetVertexBuffers:
{
SetVertexBuffersCmd* cmd = commands.NextCommand<SetVertexBuffersCmd>();
auto buffers = commands.NextData<Ref<BufferBase>>(cmd->count);
auto offsets = commands.NextData<uint32_t>(cmd->count);
auto inputState = ToBackend(lastPipeline->GetInputState());
std::array<D3D12_VERTEX_BUFFER_VIEW, kMaxVertexInputs> d3d12BufferViews;
for (uint32_t i = 0; i < cmd->count; ++i) {
auto input = inputState->GetInput(cmd->startSlot + i);
Buffer* buffer = ToBackend(buffers[i].Get());
d3d12BufferViews[i].BufferLocation = buffer->GetVA() + offsets[i];
d3d12BufferViews[i].StrideInBytes = input.stride;
d3d12BufferViews[i].SizeInBytes = buffer->GetSize() - offsets[i];
}
commandList->IASetVertexBuffers(cmd->startSlot, cmd->count, d3d12BufferViews.data());
}
break;
case Command::TransitionBufferUsage:
{
TransitionBufferUsageCmd* cmd = commands.NextCommand<TransitionBufferUsageCmd>();
Buffer* buffer = ToBackend(cmd->buffer.Get());
D3D12_RESOURCE_BARRIER barrier;
if (buffer->GetResourceTransitionBarrier(buffer->GetUsage(), cmd->usage, &barrier)) {
commandList->ResourceBarrier(1, &barrier);
}
buffer->UpdateUsageInternal(cmd->usage);
}
break;
case Command::TransitionTextureUsage:
{
TransitionTextureUsageCmd* cmd = commands.NextCommand<TransitionTextureUsageCmd>();
Texture* texture = ToBackend(cmd->texture.Get());
texture->UpdateUsageInternal(cmd->usage);
}
break;
}
}
}
}
}

View File

@ -14,7 +14,9 @@
#include "D3D12Backend.h"
#include "BufferD3D12.h"
#include "CommandBufferD3D12.h"
#include "InputStateD3D12.h"
#include "PipelineD3D12.h"
#include "PipelineLayoutD3D12.h"
#include "QueueD3D12.h"
@ -51,6 +53,15 @@ 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)));
ASSERT_SUCCESS(d3d12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&pendingCommandAllocator)));
ASSERT_SUCCESS(d3d12Device->CreateCommandList(
0,
D3D12_COMMAND_LIST_TYPE_DIRECT,
pendingCommandAllocator.Get(),
nullptr,
IID_PPV_ARGS(&pendingCommandList)
));
}
Device::~Device() {
@ -64,6 +75,14 @@ namespace d3d12 {
return commandQueue;
}
ComPtr<ID3D12CommandAllocator> Device::GetPendingCommandAllocator() {
return pendingCommandAllocator;
}
ComPtr<ID3D12GraphicsCommandList> Device::GetPendingCommandList() {
return pendingCommandList;
}
D3D12_CPU_DESCRIPTOR_HANDLE Device::GetCurrentRenderTargetDescriptor() {
return renderTargetDescriptor;
}
@ -139,26 +158,6 @@ namespace d3d12 {
: 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) {
}
void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) {
// TODO(cwallez@chromium.org): Implement Map Read for the null backend
}
void Buffer::UnmapImpl() {
// TODO(cwallez@chromium.org): Implement Map Read for the null backend
}
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) {
}
// BufferView
BufferView::BufferView(Device* device, BufferViewBuilder* builder)
@ -177,12 +176,6 @@ namespace d3d12 {
: FramebufferBase(builder), device(device) {
}
// InputState
InputState::InputState(Device* device, InputStateBuilder * builder)
: InputStateBase(builder), device(device) {
}
// RenderPass
RenderPass::RenderPass(Device* device, RenderPassBuilder* builder)

View File

@ -106,6 +106,8 @@ namespace d3d12 {
ComPtr<ID3D12Device> GetD3D12Device();
ComPtr<ID3D12CommandQueue> GetCommandQueue();
ComPtr<ID3D12CommandAllocator> GetPendingCommandAllocator();
ComPtr<ID3D12GraphicsCommandList> GetPendingCommandList();
D3D12_CPU_DESCRIPTOR_HANDLE GetCurrentRenderTargetDescriptor();
void SetNextRenderTargetDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE renderTargetDescriptor);
@ -117,6 +119,8 @@ namespace d3d12 {
private:
ComPtr<ID3D12Device> d3d12Device;
ComPtr<ID3D12CommandQueue> commandQueue;
ComPtr<ID3D12CommandAllocator> pendingCommandAllocator;
ComPtr<ID3D12GraphicsCommandList> pendingCommandList;
D3D12_CPU_DESCRIPTOR_HANDLE renderTargetDescriptor;
};
@ -137,19 +141,6 @@ namespace d3d12 {
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;
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
void UnmapImpl() override;
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) override;
Device* device;
};
class BufferView : public BufferViewBase {
public:
BufferView(Device* device, BufferViewBuilder* builder);
@ -174,14 +165,6 @@ namespace d3d12 {
Device* device;
};
class InputState : public InputStateBase {
public:
InputState(Device* device, InputStateBuilder* builder);
private:
Device* device;
};
class RenderPass : public RenderPassBase {
public:
RenderPass(Device* device, RenderPassBuilder* builder);

View File

@ -13,7 +13,9 @@
// limitations under the License.
#include "D3D12Backend.h"
#include "BufferD3D12.h"
#include "CommandBufferD3D12.h"
#include "InputStateD3D12.h"
#include "PipelineD3D12.h"
#include "PipelineLayoutD3D12.h"
#include "QueueD3D12.h"

View File

@ -0,0 +1,82 @@
// 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 "InputStateD3D12.h"
namespace backend {
namespace d3d12 {
static DXGI_FORMAT VertexFormatType(nxt::VertexFormat format) {
switch (format) {
case nxt::VertexFormat::FloatR32G32B32A32:
return DXGI_FORMAT_R32G32B32A32_FLOAT;
case nxt::VertexFormat::FloatR32G32B32:
return DXGI_FORMAT_R32G32B32_FLOAT;
case nxt::VertexFormat::FloatR32G32:
return DXGI_FORMAT_R32G32_FLOAT;
}
}
static D3D12_INPUT_CLASSIFICATION InputStepModeFunction(nxt::InputStepMode mode) {
switch (mode) {
case nxt::InputStepMode::Vertex:
return D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
case nxt::InputStepMode::Instance:
return D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
}
}
InputState::InputState(Device* device, InputStateBuilder* builder)
: InputStateBase(builder), device(device) {
const auto& attributesSetMask = GetAttributesSetMask();
size_t count = 0;
for (size_t i = 0; i < attributesSetMask.size(); ++i) {
if (!attributesSetMask[i]) {
continue;
}
D3D12_INPUT_ELEMENT_DESC& inputElementDescriptor = inputElementDescriptors[count++];
const AttributeInfo& attribute = GetAttribute(i);
// If the HLSL semantic is TEXCOORDN the SemanticName should be "TEXCOORD" and the SemanticIndex N
inputElementDescriptor.SemanticName = "TEXCOORD";
inputElementDescriptor.SemanticIndex = i;
inputElementDescriptor.Format = VertexFormatType(attribute.format);
inputElementDescriptor.InputSlot = attribute.bindingSlot;
const InputInfo& input = GetInput(attribute.bindingSlot);
inputElementDescriptor.AlignedByteOffset = attribute.offset;
inputElementDescriptor.InputSlotClass = InputStepModeFunction(input.stepMode);
if (inputElementDescriptor.InputSlotClass == D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA) {
inputElementDescriptor.InstanceDataStepRate = 0;
} else {
inputElementDescriptor.InstanceDataStepRate = 1;
}
}
inputLayoutDescriptor.pInputElementDescs = inputElementDescriptors;
inputLayoutDescriptor.NumElements = count;
}
const D3D12_INPUT_LAYOUT_DESC& InputState::GetD3D12InputLayoutDescriptor() const {
return inputLayoutDescriptor;
}
}
}

View File

@ -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_INPUTSTATED3D12_H_
#define BACKEND_D3D12_INPUTSTATED3D12_H_
#include "common/InputState.h"
#include "d3d12_platform.h"
namespace backend {
namespace d3d12 {
class Device;
class InputState : public InputStateBase {
public:
InputState(Device* device, InputStateBuilder* builder);
const D3D12_INPUT_LAYOUT_DESC& GetD3D12InputLayoutDescriptor() const;
private:
Device* device;
D3D12_INPUT_LAYOUT_DESC inputLayoutDescriptor;
D3D12_INPUT_ELEMENT_DESC inputElementDescriptors[kMaxVertexAttributes];
};
}
}
#endif // BACKEND_D3D12_INPUTSTATED3D12_H_

View File

@ -15,6 +15,7 @@
#include "PipelineD3D12.h"
#include "D3D12Backend.h"
#include "InputStateD3D12.h"
#include "ShaderModuleD3D12.h"
#include "PipelineLayoutD3D12.h"
@ -115,6 +116,9 @@ namespace d3d12 {
}
}
InputState* inputState = ToBackend(GetInputState());
descriptor.InputLayout = inputState->GetD3D12InputLayoutDescriptor();
descriptor.pRootSignature = ToBackend(GetLayout())->GetRootSignature().Get();
descriptor.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;

View File

@ -31,7 +31,6 @@ namespace d3d12 {
nullptr,
IID_PPV_ARGS(&commandList)
));
ASSERT_SUCCESS(commandList->Close());
ASSERT_SUCCESS(device->GetD3D12Device()->CreateFence(fenceValue, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)));
fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
@ -39,10 +38,22 @@ namespace d3d12 {
}
void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) {
// TODO(enga@google.com): This will stall on the previous submit because
ComPtr<ID3D12CommandAllocator> pendingCommandAllocator = device->GetPendingCommandAllocator();
ComPtr<ID3D12GraphicsCommandList> pendingCommandList = device->GetPendingCommandList();
ASSERT_SUCCESS(pendingCommandList->Close());
for (uint32_t i = 0; i < numCommands; ++i) {
commands[i]->FillCommands(commandList);
}
ASSERT_SUCCESS(commandList->Close());
ID3D12CommandList* commandLists[] = { pendingCommandList.Get(), commandList.Get() };
device->GetCommandQueue()->ExecuteCommandLists(_countof(commandLists), commandLists);
// TODO(enga@google.com): This will stall on the submit because
// the commands must finish exeuting before the ID3D12CommandAllocator is reset.
// This should be fixed / optimized by using multiple command allocators.
const uint64_t currentFence = fenceValue++;
const uint64_t currentFence = ++fenceValue;
ASSERT_SUCCESS(device->GetCommandQueue()->Signal(fence.Get(), fenceValue));
if (fence->GetCompletedValue() < currentFence) {
@ -51,16 +62,9 @@ namespace d3d12 {
}
ASSERT_SUCCESS(commandAllocator->Reset());
ASSERT_SUCCESS(pendingCommandAllocator->Reset());
ASSERT_SUCCESS(pendingCommandList->Reset(pendingCommandAllocator.Get(), NULL));
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);
}
}