Add D3D12 buffer, texture, and sampler binding
This commit is contained in:
parent
29477375a6
commit
aecf0b130e
|
@ -243,6 +243,8 @@ if (WIN32)
|
||||||
${D3D12_DIR}/CommandAllocatorManager.h
|
${D3D12_DIR}/CommandAllocatorManager.h
|
||||||
${D3D12_DIR}/CommandBufferD3D12.cpp
|
${D3D12_DIR}/CommandBufferD3D12.cpp
|
||||||
${D3D12_DIR}/CommandBufferD3D12.h
|
${D3D12_DIR}/CommandBufferD3D12.h
|
||||||
|
${D3D12_DIR}/DescriptorHeapAllocator.cpp
|
||||||
|
${D3D12_DIR}/DescriptorHeapAllocator.h
|
||||||
${D3D12_DIR}/D3D12Backend.cpp
|
${D3D12_DIR}/D3D12Backend.cpp
|
||||||
${D3D12_DIR}/D3D12Backend.h
|
${D3D12_DIR}/D3D12Backend.h
|
||||||
${D3D12_DIR}/InputStateD3D12.cpp
|
${D3D12_DIR}/InputStateD3D12.cpp
|
||||||
|
@ -257,8 +259,12 @@ if (WIN32)
|
||||||
${D3D12_DIR}/ResourceAllocator.h
|
${D3D12_DIR}/ResourceAllocator.h
|
||||||
${D3D12_DIR}/ResourceUploader.cpp
|
${D3D12_DIR}/ResourceUploader.cpp
|
||||||
${D3D12_DIR}/ResourceUploader.h
|
${D3D12_DIR}/ResourceUploader.h
|
||||||
|
${D3D12_DIR}/SamplerD3D12.cpp
|
||||||
|
${D3D12_DIR}/SamplerD3D12.h
|
||||||
${D3D12_DIR}/ShaderModuleD3D12.cpp
|
${D3D12_DIR}/ShaderModuleD3D12.cpp
|
||||||
${D3D12_DIR}/ShaderModuleD3D12.h
|
${D3D12_DIR}/ShaderModuleD3D12.h
|
||||||
|
${D3D12_DIR}/TextureD3D12.cpp
|
||||||
|
${D3D12_DIR}/TextureD3D12.h
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,85 @@ namespace backend {
|
||||||
commands->DataWasDestroyed();
|
commands->DataWasDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkipCommand(CommandIterator* commands, Command type) {
|
||||||
|
switch (type) {
|
||||||
|
case Command::AdvanceSubpass:
|
||||||
|
commands->NextCommand<AdvanceSubpassCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::BeginRenderPass:
|
||||||
|
commands->NextCommand<BeginRenderPassCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::CopyBufferToBuffer:
|
||||||
|
commands->NextCommand<CopyBufferToBufferCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::CopyBufferToTexture:
|
||||||
|
commands->NextCommand<CopyBufferToTextureCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::CopyTextureToBuffer:
|
||||||
|
commands->NextCommand<CopyTextureToBufferCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::Dispatch:
|
||||||
|
commands->NextCommand<DispatchCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::DrawArrays:
|
||||||
|
commands->NextCommand<DrawArraysCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::DrawElements:
|
||||||
|
commands->NextCommand<DrawElementsCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::EndRenderPass:
|
||||||
|
commands->NextCommand<EndRenderPassCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::SetPipeline:
|
||||||
|
commands->NextCommand<SetPipelineCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::SetPushConstants:
|
||||||
|
{
|
||||||
|
auto* cmd = commands->NextCommand<SetPushConstantsCmd>();
|
||||||
|
commands->NextData<uint32_t>(cmd->count);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::SetStencilReference:
|
||||||
|
commands->NextCommand<SetStencilReferenceCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::SetBindGroup:
|
||||||
|
commands->NextCommand<SetBindGroupCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::SetIndexBuffer:
|
||||||
|
commands->NextCommand<SetIndexBufferCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::SetVertexBuffers:
|
||||||
|
{
|
||||||
|
auto* cmd = commands->NextCommand<SetVertexBuffersCmd>();
|
||||||
|
commands->NextData<Ref<BufferBase>>(cmd->count);
|
||||||
|
commands->NextData<uint32_t>(cmd->count);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::TransitionBufferUsage:
|
||||||
|
commands->NextCommand<TransitionBufferUsageCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::TransitionTextureUsage:
|
||||||
|
commands->NextCommand<TransitionTextureUsageCmd>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CommandBufferBuilder::CommandBufferBuilder(DeviceBase* device) : Builder(device), state(std::make_unique<CommandBufferStateTracker>(this)) {
|
CommandBufferBuilder::CommandBufferBuilder(DeviceBase* device) : Builder(device), state(std::make_unique<CommandBufferStateTracker>(this)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,7 @@ namespace backend {
|
||||||
// This needs to be called before the CommandIterator is freed so that the Ref<> present in
|
// This needs to be called before the CommandIterator is freed so that the Ref<> present in
|
||||||
// the commands have a chance to run their destructor and remove internal references.
|
// the commands have a chance to run their destructor and remove internal references.
|
||||||
void FreeCommands(CommandIterator* commands);
|
void FreeCommands(CommandIterator* commands);
|
||||||
|
void SkipCommand(CommandIterator* commands, Command type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace d3d12 {
|
||||||
D3D12_RESOURCE_DESC resourceDescriptor;
|
D3D12_RESOURCE_DESC resourceDescriptor;
|
||||||
resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||||
resourceDescriptor.Alignment = 0;
|
resourceDescriptor.Alignment = 0;
|
||||||
resourceDescriptor.Width = GetSize();
|
resourceDescriptor.Width = GetD3D12Size();
|
||||||
resourceDescriptor.Height = 1;
|
resourceDescriptor.Height = 1;
|
||||||
resourceDescriptor.DepthOrArraySize = 1;
|
resourceDescriptor.DepthOrArraySize = 1;
|
||||||
resourceDescriptor.MipLevels = 1;
|
resourceDescriptor.MipLevels = 1;
|
||||||
|
@ -68,6 +68,11 @@ namespace d3d12 {
|
||||||
device->GetResourceAllocator()->Release(resource);
|
device->GetResourceAllocator()->Release(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Buffer::GetD3D12Size() const {
|
||||||
|
// TODO(enga@google.com): TODO investigate if this needs to be a constraint at the API level
|
||||||
|
return ((GetSize() + 256 - 1) / 256) * 256; // size is required to be 256-byte aligned.
|
||||||
|
}
|
||||||
|
|
||||||
ComPtr<ID3D12Resource> Buffer::GetD3D12Resource() {
|
ComPtr<ID3D12Resource> Buffer::GetD3D12Resource() {
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
@ -113,5 +118,34 @@ namespace d3d12 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BufferView::BufferView(Device* device, BufferViewBuilder* builder)
|
||||||
|
: BufferViewBase(builder), device(device) {
|
||||||
|
|
||||||
|
cbvDesc.BufferLocation = ToBackend(GetBuffer())->GetVA() + GetOffset();
|
||||||
|
cbvDesc.SizeInBytes = GetD3D12Size();
|
||||||
|
|
||||||
|
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
|
||||||
|
uavDesc.Buffer.FirstElement = GetOffset();
|
||||||
|
uavDesc.Buffer.NumElements = GetD3D12Size();
|
||||||
|
uavDesc.Buffer.StructureByteStride = 1;
|
||||||
|
uavDesc.Buffer.CounterOffsetInBytes = 0;
|
||||||
|
uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t BufferView::GetD3D12Size() const {
|
||||||
|
// TODO(enga@google.com): TODO investigate if this needs to be a constraint at the API level
|
||||||
|
return ((GetSize() + 256 - 1) / 256) * 256; // size is required to be 256-byte aligned.
|
||||||
|
}
|
||||||
|
|
||||||
|
const D3D12_CONSTANT_BUFFER_VIEW_DESC& BufferView::GetCBVDescriptor() const {
|
||||||
|
return cbvDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const D3D12_UNORDERED_ACCESS_VIEW_DESC& BufferView::GetUAVDescriptor() const {
|
||||||
|
return uavDesc;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace d3d12 {
|
||||||
Buffer(Device* device, BufferBuilder* builder);
|
Buffer(Device* device, BufferBuilder* builder);
|
||||||
~Buffer();
|
~Buffer();
|
||||||
|
|
||||||
|
uint32_t GetD3D12Size() const;
|
||||||
ComPtr<ID3D12Resource> GetD3D12Resource();
|
ComPtr<ID3D12Resource> GetD3D12Resource();
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS GetVA() const;
|
D3D12_GPU_VIRTUAL_ADDRESS GetVA() const;
|
||||||
bool GetResourceTransitionBarrier(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier);
|
bool GetResourceTransitionBarrier(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier);
|
||||||
|
@ -45,6 +46,20 @@ namespace d3d12 {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BufferView : public BufferViewBase {
|
||||||
|
public:
|
||||||
|
BufferView(Device* device, BufferViewBuilder* builder);
|
||||||
|
|
||||||
|
uint32_t GetD3D12Size() const;
|
||||||
|
const D3D12_CONSTANT_BUFFER_VIEW_DESC& GetCBVDescriptor() const;
|
||||||
|
const D3D12_UNORDERED_ACCESS_VIEW_DESC& GetUAVDescriptor() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Device* device;
|
||||||
|
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc;
|
||||||
|
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,13 @@
|
||||||
|
|
||||||
#include "common/Commands.h"
|
#include "common/Commands.h"
|
||||||
#include "D3D12Backend.h"
|
#include "D3D12Backend.h"
|
||||||
|
#include "DescriptorHeapAllocator.h"
|
||||||
#include "BufferD3D12.h"
|
#include "BufferD3D12.h"
|
||||||
#include "InputStateD3D12.h"
|
#include "InputStateD3D12.h"
|
||||||
#include "PipelineD3D12.h"
|
#include "PipelineD3D12.h"
|
||||||
#include "PipelineLayoutD3D12.h"
|
#include "PipelineLayoutD3D12.h"
|
||||||
|
#include "SamplerD3D12.h"
|
||||||
|
#include "TextureD3D12.h"
|
||||||
|
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
@ -33,6 +36,146 @@ namespace d3d12 {
|
||||||
return DXGI_FORMAT_R32_UINT;
|
return DXGI_FORMAT_R32_UINT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct BindGroupStateTracker {
|
||||||
|
uint32_t cbvSrvUavDescriptorIndex = 0;
|
||||||
|
uint32_t samplerDescriptorIndex = 0;
|
||||||
|
DescriptorHeapHandle cbvSrvUavDescriptorHeap;
|
||||||
|
DescriptorHeapHandle samplerDescriptorHeap;
|
||||||
|
std::array<BindGroup*, kMaxBindGroups> bindGroups = {};
|
||||||
|
Device* device;
|
||||||
|
|
||||||
|
BindGroupStateTracker(Device* device) : device(device) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackSetBindGroup(const BindGroupLayoutBase* bindGroupLayout) {
|
||||||
|
const auto& layout = bindGroupLayout->GetBindingInfo();
|
||||||
|
|
||||||
|
for (size_t binding = 0; binding < layout.mask.size(); ++binding) {
|
||||||
|
if (!layout.mask[binding]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (layout.types[binding]) {
|
||||||
|
case nxt::BindingType::UniformBuffer:
|
||||||
|
case nxt::BindingType::StorageBuffer:
|
||||||
|
case nxt::BindingType::SampledTexture:
|
||||||
|
cbvSrvUavDescriptorIndex++;
|
||||||
|
case nxt::BindingType::Sampler:
|
||||||
|
samplerDescriptorIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetBindGroup(Pipeline* pipeline, BindGroup* group, uint32_t index, ComPtr<ID3D12GraphicsCommandList> commandList) {
|
||||||
|
const auto& layout = group->GetLayout()->GetBindingInfo();
|
||||||
|
|
||||||
|
// these indices are the beginning of the descriptor table
|
||||||
|
uint32_t cbvSrvUavDescriptorStart = cbvSrvUavDescriptorIndex;
|
||||||
|
uint32_t samplerDescriptorStart = samplerDescriptorIndex;
|
||||||
|
|
||||||
|
bindGroups[index] = group;
|
||||||
|
|
||||||
|
PipelineLayout* pipelineLayout = ToBackend(pipeline->GetLayout());
|
||||||
|
|
||||||
|
// these indices are the offsets from the start of the descriptor table
|
||||||
|
uint32_t cbvIndex = pipelineLayout->GetDescriptorStartingIndex(index, PipelineLayout::Descriptor::Type::CBV);
|
||||||
|
uint32_t uavIndex = pipelineLayout->GetDescriptorStartingIndex(index, PipelineLayout::Descriptor::Type::UAV);
|
||||||
|
uint32_t srvIndex = pipelineLayout->GetDescriptorStartingIndex(index, PipelineLayout::Descriptor::Type::SRV);
|
||||||
|
uint32_t samplerIndex = pipelineLayout->GetDescriptorStartingIndex(index, PipelineLayout::Descriptor::Type::Sampler);
|
||||||
|
|
||||||
|
for (size_t binding = 0; binding < layout.mask.size(); ++binding) {
|
||||||
|
if (!layout.mask[binding]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (layout.types[binding]) {
|
||||||
|
case nxt::BindingType::UniformBuffer:
|
||||||
|
{
|
||||||
|
auto* view = ToBackend(group->GetBindingAsBufferView(binding));
|
||||||
|
auto* buffer = ToBackend(view->GetBuffer());
|
||||||
|
auto& cbvDesc = view->GetCBVDescriptor();
|
||||||
|
device->GetD3D12Device()->CreateConstantBufferView(&cbvDesc, cbvSrvUavDescriptorHeap.GetCPUHandle(cbvSrvUavDescriptorStart + cbvIndex++));
|
||||||
|
cbvSrvUavDescriptorIndex++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case nxt::BindingType::StorageBuffer:
|
||||||
|
{
|
||||||
|
auto* view = ToBackend(group->GetBindingAsBufferView(binding));
|
||||||
|
auto* buffer = ToBackend(view->GetBuffer());
|
||||||
|
auto& uavDesc = view->GetUAVDescriptor();
|
||||||
|
device->GetD3D12Device()->CreateUnorderedAccessView(buffer->GetD3D12Resource().Get(), nullptr, &uavDesc, cbvSrvUavDescriptorHeap.GetCPUHandle(cbvSrvUavDescriptorStart + uavIndex++));
|
||||||
|
cbvSrvUavDescriptorIndex++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case nxt::BindingType::SampledTexture:
|
||||||
|
{
|
||||||
|
auto* texture = ToBackend(group->GetBindingAsTextureView(binding)->GetTexture());
|
||||||
|
auto& srvDesc = texture->GetSRVDescriptor();
|
||||||
|
device->GetD3D12Device()->CreateShaderResourceView(texture->GetD3D12Resource().Get(), &srvDesc, cbvSrvUavDescriptorHeap.GetCPUHandle(cbvSrvUavDescriptorStart + srvIndex++));
|
||||||
|
cbvSrvUavDescriptorIndex++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case nxt::BindingType::Sampler:
|
||||||
|
{
|
||||||
|
auto* sampler = ToBackend(group->GetBindingAsSampler(binding));
|
||||||
|
auto& samplerDesc = sampler->GetSamplerDescriptor();
|
||||||
|
device->GetD3D12Device()->CreateSampler(&samplerDesc, samplerDescriptorHeap.GetCPUHandle(samplerDescriptorStart + samplerIndex++));
|
||||||
|
samplerDescriptorIndex++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cbvSrvUavDescriptorStart != cbvSrvUavDescriptorIndex) {
|
||||||
|
uint32_t parameterIndex = pipelineLayout->GetCBVSRVUAVRootParameterIndex(index);
|
||||||
|
|
||||||
|
if (pipeline->IsCompute()) {
|
||||||
|
commandList->SetComputeRootDescriptorTable(parameterIndex, cbvSrvUavDescriptorHeap.GetGPUHandle(cbvSrvUavDescriptorStart));
|
||||||
|
} else {
|
||||||
|
commandList->SetGraphicsRootDescriptorTable(parameterIndex, cbvSrvUavDescriptorHeap.GetGPUHandle(cbvSrvUavDescriptorStart));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (samplerDescriptorStart != samplerDescriptorIndex) {
|
||||||
|
uint32_t parameterIndex = pipelineLayout->GetSamplerRootParameterIndex(index);
|
||||||
|
|
||||||
|
if (pipeline->IsCompute()) {
|
||||||
|
commandList->SetComputeRootDescriptorTable(parameterIndex, samplerDescriptorHeap.GetGPUHandle(samplerDescriptorStart));
|
||||||
|
} else {
|
||||||
|
commandList->SetGraphicsRootDescriptorTable(parameterIndex, samplerDescriptorHeap.GetGPUHandle(samplerDescriptorStart));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetInheritedBindGroup(Pipeline* pipeline, uint32_t index, ComPtr<ID3D12GraphicsCommandList> commandList) {
|
||||||
|
BindGroup* group = bindGroups[index];
|
||||||
|
ASSERT(group != nullptr);
|
||||||
|
SetBindGroup(pipeline, group, index, commandList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocateAndSetDescriptorHeaps(Device* device, ComPtr<ID3D12GraphicsCommandList> commandList) {
|
||||||
|
cbvSrvUavDescriptorHeap = device->GetDescriptorHeapAllocator()->Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, cbvSrvUavDescriptorIndex);
|
||||||
|
samplerDescriptorHeap = device->GetDescriptorHeapAllocator()->Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, samplerDescriptorIndex);
|
||||||
|
|
||||||
|
ID3D12DescriptorHeap* descriptorHeaps[2] = { cbvSrvUavDescriptorHeap.Get(), samplerDescriptorHeap.Get() };
|
||||||
|
if (descriptorHeaps[0] && descriptorHeaps[1]) {
|
||||||
|
commandList->SetDescriptorHeaps(2, descriptorHeaps);
|
||||||
|
} else if (descriptorHeaps[0]) {
|
||||||
|
commandList->SetDescriptorHeaps(1, descriptorHeaps);
|
||||||
|
} else if (descriptorHeaps[1]) {
|
||||||
|
commandList->SetDescriptorHeaps(2, &descriptorHeaps[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset() {
|
||||||
|
cbvSrvUavDescriptorIndex = 0;
|
||||||
|
samplerDescriptorIndex = 0;
|
||||||
|
for (uint32_t i = 0; i < kMaxBindGroups; ++i) {
|
||||||
|
bindGroups[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder)
|
CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder)
|
||||||
|
@ -44,8 +187,59 @@ namespace d3d12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::FillCommands(ComPtr<ID3D12GraphicsCommandList> commandList) {
|
void CommandBuffer::FillCommands(ComPtr<ID3D12GraphicsCommandList> commandList) {
|
||||||
|
BindGroupStateTracker bindingTracker(device);
|
||||||
|
|
||||||
|
{
|
||||||
Command type;
|
Command type;
|
||||||
Pipeline* lastPipeline = nullptr;
|
Pipeline* lastPipeline = nullptr;
|
||||||
|
PipelineLayout* lastLayout = nullptr;
|
||||||
|
|
||||||
|
while(commands.NextCommandId(&type)) {
|
||||||
|
switch (type) {
|
||||||
|
case Command::SetPipeline:
|
||||||
|
{
|
||||||
|
SetPipelineCmd* cmd = commands.NextCommand<SetPipelineCmd>();
|
||||||
|
Pipeline* pipeline = ToBackend(cmd->pipeline).Get();
|
||||||
|
PipelineLayout* layout = ToBackend(pipeline->GetLayout());
|
||||||
|
|
||||||
|
if (lastLayout) {
|
||||||
|
auto mask = layout->GetBindGroupsLayoutMask();
|
||||||
|
for (uint32_t i = 0; i < kMaxBindGroups; ++i) {
|
||||||
|
// matching bind groups are inherited until they differ
|
||||||
|
if (mask[i] && lastLayout->GetBindGroupLayout(i) == layout->GetBindGroupLayout(i)) {
|
||||||
|
bindingTracker.TrackSetBindGroup(layout->GetBindGroupLayout(i));
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPipeline = pipeline;
|
||||||
|
lastLayout = layout;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Command::SetBindGroup:
|
||||||
|
{
|
||||||
|
SetBindGroupCmd* cmd = commands.NextCommand<SetBindGroupCmd>();
|
||||||
|
BindGroup* group = ToBackend(cmd->group.Get());
|
||||||
|
bindingTracker.TrackSetBindGroup(group->GetLayout());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SkipCommand(&commands, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bindingTracker.AllocateAndSetDescriptorHeaps(device, commandList);
|
||||||
|
bindingTracker.Reset();
|
||||||
|
|
||||||
|
Command type;
|
||||||
|
Pipeline* lastPipeline = nullptr;
|
||||||
|
PipelineLayout* lastLayout = nullptr;
|
||||||
|
|
||||||
RenderPass* currentRenderPass = nullptr;
|
RenderPass* currentRenderPass = nullptr;
|
||||||
Framebuffer* currentFramebuffer = nullptr;
|
Framebuffer* currentFramebuffer = nullptr;
|
||||||
|
@ -64,10 +258,10 @@ namespace d3d12 {
|
||||||
currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get());
|
currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get());
|
||||||
currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get());
|
currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get());
|
||||||
|
|
||||||
float width = (float) currentFramebuffer->GetWidth();
|
uint32_t width = currentFramebuffer->GetWidth();
|
||||||
float height = (float) currentFramebuffer->GetHeight();
|
uint32_t height = currentFramebuffer->GetHeight();
|
||||||
D3D12_VIEWPORT viewport = { 0.f, 0.f, width, height, 0.f, 1.f };
|
D3D12_VIEWPORT viewport = { 0.f, 0.f, static_cast<float>(width), static_cast<float>(height), 0.f, 1.f };
|
||||||
D3D12_RECT scissorRect = { 0.f, 0.f, width, height };
|
D3D12_RECT scissorRect = { 0, 0, static_cast<long>(width), static_cast<long>(height) };
|
||||||
commandList->RSSetViewports(1, &viewport);
|
commandList->RSSetViewports(1, &viewport);
|
||||||
commandList->RSSetScissorRects(1, &scissorRect);
|
commandList->RSSetScissorRects(1, &scissorRect);
|
||||||
commandList->OMSetRenderTargets(1, &device->GetCurrentRenderTargetDescriptor(), FALSE, nullptr);
|
commandList->OMSetRenderTargets(1, &device->GetCurrentRenderTargetDescriptor(), FALSE, nullptr);
|
||||||
|
@ -139,15 +333,33 @@ namespace d3d12 {
|
||||||
case Command::SetPipeline:
|
case Command::SetPipeline:
|
||||||
{
|
{
|
||||||
SetPipelineCmd* cmd = commands.NextCommand<SetPipelineCmd>();
|
SetPipelineCmd* cmd = commands.NextCommand<SetPipelineCmd>();
|
||||||
lastPipeline = ToBackend(cmd->pipeline).Get();
|
|
||||||
PipelineLayout* pipelineLayout = ToBackend(lastPipeline->GetLayout());
|
Pipeline* pipeline = ToBackend(cmd->pipeline).Get();
|
||||||
|
PipelineLayout* layout = ToBackend(pipeline->GetLayout());
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
if (lastPipeline->IsCompute()) {
|
if (pipeline->IsCompute()) {
|
||||||
} else {
|
|
||||||
commandList->SetGraphicsRootSignature(pipelineLayout->GetRootSignature().Get());
|
|
||||||
commandList->SetPipelineState(lastPipeline->GetRenderPipelineState().Get());
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
commandList->SetGraphicsRootSignature(layout->GetRootSignature().Get());
|
||||||
|
commandList->SetPipelineState(pipeline->GetRenderPipelineState().Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastLayout) {
|
||||||
|
auto mask = layout->GetBindGroupsLayoutMask();
|
||||||
|
for (uint32_t i = 0; i < kMaxBindGroups; ++i) {
|
||||||
|
// matching bind groups are inherited until they differ
|
||||||
|
if (mask[i] && lastLayout->GetBindGroupLayout(i) == layout->GetBindGroupLayout(i)) {
|
||||||
|
bindingTracker.SetInheritedBindGroup(pipeline, i, commandList);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lastPipeline = pipeline;
|
||||||
|
lastLayout = layout;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -166,6 +378,8 @@ namespace d3d12 {
|
||||||
case Command::SetBindGroup:
|
case Command::SetBindGroup:
|
||||||
{
|
{
|
||||||
SetBindGroupCmd* cmd = commands.NextCommand<SetBindGroupCmd>();
|
SetBindGroupCmd* cmd = commands.NextCommand<SetBindGroupCmd>();
|
||||||
|
BindGroup* group = ToBackend(cmd->group.Get());
|
||||||
|
bindingTracker.SetBindGroup(lastPipeline, group, cmd->index, commandList);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -224,6 +438,12 @@ namespace d3d12 {
|
||||||
TransitionTextureUsageCmd* cmd = commands.NextCommand<TransitionTextureUsageCmd>();
|
TransitionTextureUsageCmd* cmd = commands.NextCommand<TransitionTextureUsageCmd>();
|
||||||
|
|
||||||
Texture* texture = ToBackend(cmd->texture.Get());
|
Texture* texture = ToBackend(cmd->texture.Get());
|
||||||
|
|
||||||
|
D3D12_RESOURCE_BARRIER barrier;
|
||||||
|
if (texture->GetResourceTransitionBarrier(texture->GetUsage(), cmd->usage, &barrier)) {
|
||||||
|
commandList->ResourceBarrier(1, &barrier);
|
||||||
|
}
|
||||||
|
|
||||||
texture->UpdateUsageInternal(cmd->usage);
|
texture->UpdateUsageInternal(cmd->usage);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -20,9 +20,12 @@
|
||||||
#include "PipelineD3D12.h"
|
#include "PipelineD3D12.h"
|
||||||
#include "PipelineLayoutD3D12.h"
|
#include "PipelineLayoutD3D12.h"
|
||||||
#include "QueueD3D12.h"
|
#include "QueueD3D12.h"
|
||||||
|
#include "SamplerD3D12.h"
|
||||||
#include "ShaderModuleD3D12.h"
|
#include "ShaderModuleD3D12.h"
|
||||||
|
#include "TextureD3D12.h"
|
||||||
|
|
||||||
#include "CommandAllocatorManager.h"
|
#include "CommandAllocatorManager.h"
|
||||||
|
#include "DescriptorHeapAllocator.h"
|
||||||
#include "ResourceAllocator.h"
|
#include "ResourceAllocator.h"
|
||||||
#include "ResourceUploader.h"
|
#include "ResourceUploader.h"
|
||||||
|
|
||||||
|
@ -80,6 +83,7 @@ namespace d3d12 {
|
||||||
Device::Device(ComPtr<ID3D12Device> d3d12Device)
|
Device::Device(ComPtr<ID3D12Device> d3d12Device)
|
||||||
: d3d12Device(d3d12Device),
|
: d3d12Device(d3d12Device),
|
||||||
commandAllocatorManager(new CommandAllocatorManager(this)),
|
commandAllocatorManager(new CommandAllocatorManager(this)),
|
||||||
|
descriptorHeapAllocator(new DescriptorHeapAllocator(this)),
|
||||||
resourceAllocator(new ResourceAllocator(this)),
|
resourceAllocator(new ResourceAllocator(this)),
|
||||||
resourceUploader(new ResourceUploader(this)) {
|
resourceUploader(new ResourceUploader(this)) {
|
||||||
|
|
||||||
|
@ -104,6 +108,10 @@ namespace d3d12 {
|
||||||
return commandQueue;
|
return commandQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DescriptorHeapAllocator* Device::GetDescriptorHeapAllocator() {
|
||||||
|
return descriptorHeapAllocator;
|
||||||
|
}
|
||||||
|
|
||||||
ResourceAllocator* Device::GetResourceAllocator() {
|
ResourceAllocator* Device::GetResourceAllocator() {
|
||||||
return resourceAllocator;
|
return resourceAllocator;
|
||||||
}
|
}
|
||||||
|
@ -142,6 +150,8 @@ namespace d3d12 {
|
||||||
|
|
||||||
void Device::SetNextRenderTargetDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE renderTargetDescriptor) {
|
void Device::SetNextRenderTargetDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE renderTargetDescriptor) {
|
||||||
this->renderTargetDescriptor = renderTargetDescriptor;
|
this->renderTargetDescriptor = renderTargetDescriptor;
|
||||||
|
static const float clearColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
GetPendingCommandList()->ClearRenderTargetView(renderTargetDescriptor, clearColor, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::TickImpl() {
|
void Device::TickImpl() {
|
||||||
|
@ -149,6 +159,7 @@ namespace d3d12 {
|
||||||
const uint64_t lastCompletedSerial = fence->GetCompletedValue();
|
const uint64_t lastCompletedSerial = fence->GetCompletedValue();
|
||||||
resourceAllocator->FreeUnusedResources(lastCompletedSerial);
|
resourceAllocator->FreeUnusedResources(lastCompletedSerial);
|
||||||
commandAllocatorManager->ResetCompletedAllocators(lastCompletedSerial);
|
commandAllocatorManager->ResetCompletedAllocators(lastCompletedSerial);
|
||||||
|
descriptorHeapAllocator->FreeDescriptorHeaps(lastCompletedSerial);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Device::GetSerial() const {
|
uint64_t Device::GetSerial() const {
|
||||||
|
@ -219,7 +230,7 @@ namespace d3d12 {
|
||||||
return new RenderPass(this, builder);
|
return new RenderPass(this, builder);
|
||||||
}
|
}
|
||||||
SamplerBase* Device::CreateSampler(SamplerBuilder* builder) {
|
SamplerBase* Device::CreateSampler(SamplerBuilder* builder) {
|
||||||
return new Sampler(this, builder);
|
return new Sampler(builder);
|
||||||
}
|
}
|
||||||
ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) {
|
ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) {
|
||||||
return new ShaderModule(this, builder);
|
return new ShaderModule(this, builder);
|
||||||
|
@ -249,12 +260,6 @@ namespace d3d12 {
|
||||||
: BindGroupLayoutBase(builder), device(device) {
|
: BindGroupLayoutBase(builder), device(device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BufferView
|
|
||||||
|
|
||||||
BufferView::BufferView(Device* device, BufferViewBuilder* builder)
|
|
||||||
: BufferViewBase(builder), device(device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// DepthStencilState
|
// DepthStencilState
|
||||||
|
|
||||||
DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder)
|
DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder)
|
||||||
|
@ -273,26 +278,5 @@ namespace d3d12 {
|
||||||
: RenderPassBase(builder), device(device) {
|
: RenderPassBase(builder), device(device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sampler
|
|
||||||
|
|
||||||
Sampler::Sampler(Device* device, SamplerBuilder* builder)
|
|
||||||
: SamplerBase(builder), device(device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Texture
|
|
||||||
|
|
||||||
Texture::Texture(Device* device, TextureBuilder* builder)
|
|
||||||
: TextureBase(builder), device(device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Texture::TransitionUsageImpl(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextureView
|
|
||||||
|
|
||||||
TextureView::TextureView(Device* device, TextureViewBuilder* builder)
|
|
||||||
: TextureViewBase(builder), device(device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ namespace d3d12 {
|
||||||
class RenderPass;
|
class RenderPass;
|
||||||
|
|
||||||
class CommandAllocatorManager;
|
class CommandAllocatorManager;
|
||||||
|
class DescriptorHeapAllocator;
|
||||||
class ResourceAllocator;
|
class ResourceAllocator;
|
||||||
class ResourceUploader;
|
class ResourceUploader;
|
||||||
|
|
||||||
|
@ -113,6 +114,7 @@ namespace d3d12 {
|
||||||
ComPtr<ID3D12Device> GetD3D12Device();
|
ComPtr<ID3D12Device> GetD3D12Device();
|
||||||
ComPtr<ID3D12CommandQueue> GetCommandQueue();
|
ComPtr<ID3D12CommandQueue> GetCommandQueue();
|
||||||
|
|
||||||
|
DescriptorHeapAllocator* GetDescriptorHeapAllocator();
|
||||||
ResourceAllocator* GetResourceAllocator();
|
ResourceAllocator* GetResourceAllocator();
|
||||||
ResourceUploader* GetResourceUploader();
|
ResourceUploader* GetResourceUploader();
|
||||||
|
|
||||||
|
@ -141,6 +143,7 @@ namespace d3d12 {
|
||||||
ComPtr<ID3D12CommandQueue> commandQueue;
|
ComPtr<ID3D12CommandQueue> commandQueue;
|
||||||
|
|
||||||
CommandAllocatorManager* commandAllocatorManager;
|
CommandAllocatorManager* commandAllocatorManager;
|
||||||
|
DescriptorHeapAllocator* descriptorHeapAllocator;
|
||||||
ResourceAllocator* resourceAllocator;
|
ResourceAllocator* resourceAllocator;
|
||||||
ResourceUploader* resourceUploader;
|
ResourceUploader* resourceUploader;
|
||||||
|
|
||||||
|
@ -169,14 +172,6 @@ namespace d3d12 {
|
||||||
Device* device;
|
Device* device;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferView : public BufferViewBase {
|
|
||||||
public:
|
|
||||||
BufferView(Device* device, BufferViewBuilder* builder);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Device* device;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Framebuffer : public FramebufferBase {
|
class Framebuffer : public FramebufferBase {
|
||||||
public:
|
public:
|
||||||
Framebuffer(Device* device, FramebufferBuilder* builder);
|
Framebuffer(Device* device, FramebufferBuilder* builder);
|
||||||
|
@ -201,32 +196,6 @@ namespace d3d12 {
|
||||||
Device* device;
|
Device* device;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Sampler : public SamplerBase {
|
|
||||||
public:
|
|
||||||
Sampler(Device* device, SamplerBuilder* builder);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Device* device;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Texture : public TextureBase {
|
|
||||||
public:
|
|
||||||
Texture(Device* device, TextureBuilder* builder);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage) override;
|
|
||||||
|
|
||||||
Device* device;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TextureView : public TextureViewBase {
|
|
||||||
public:
|
|
||||||
TextureView(Device* device, TextureViewBuilder* builder);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Device* device;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
// 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 "DescriptorHeapAllocator.h"
|
||||||
|
|
||||||
|
#include "D3D12Backend.h"
|
||||||
|
|
||||||
|
namespace backend {
|
||||||
|
namespace d3d12 {
|
||||||
|
|
||||||
|
DescriptorHeapHandle::DescriptorHeapHandle() {
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorHeapHandle::DescriptorHeapHandle(ComPtr<ID3D12DescriptorHeap> descriptorHeap, uint32_t sizeIncrement, uint32_t offset)
|
||||||
|
: device(device), descriptorHeap(descriptorHeap), sizeIncrement(sizeIncrement), offset(offset) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D12DescriptorHeap* DescriptorHeapHandle::Get() const {
|
||||||
|
return descriptorHeap.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorHeapHandle::GetCPUHandle(uint32_t index) const {
|
||||||
|
ASSERT(descriptorHeap);
|
||||||
|
auto handle = descriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
||||||
|
handle.ptr += sizeIncrement * (index + offset);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeapHandle::GetGPUHandle(uint32_t index) const {
|
||||||
|
ASSERT(descriptorHeap);
|
||||||
|
auto handle = descriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
||||||
|
handle.ptr += sizeIncrement * (index + offset);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DescriptorHeapAllocator::DescriptorHeapAllocator(Device* device)
|
||||||
|
: device(device),
|
||||||
|
sizeIncrements {
|
||||||
|
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),
|
||||||
|
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER),
|
||||||
|
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV),
|
||||||
|
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV),
|
||||||
|
} {
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorHeapHandle DescriptorHeapAllocator::Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count) {
|
||||||
|
if (count == 0) {
|
||||||
|
return DescriptorHeapHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& pools = descriptorHeapPools[type];
|
||||||
|
for (auto it : pools) {
|
||||||
|
auto& allocationInfo = it.second;
|
||||||
|
if (allocationInfo.remaining >= count) {
|
||||||
|
DescriptorHeapHandle handle(it.first, sizeIncrements[type], allocationInfo.size - allocationInfo.remaining);
|
||||||
|
allocationInfo.remaining -= count;
|
||||||
|
Release(handle);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(count <= 2048); // TODO(enga@google.com): Have a very large CPU heap that's copied to GPU-visible heaps
|
||||||
|
uint32_t descriptorHeapSize = 2048; // TODO(enga@google.com): Allocate much more and use this as a pool
|
||||||
|
|
||||||
|
D3D12_DESCRIPTOR_HEAP_DESC heapDescriptor;
|
||||||
|
heapDescriptor.Type = type;
|
||||||
|
heapDescriptor.NumDescriptors = descriptorHeapSize;
|
||||||
|
heapDescriptor.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||||
|
heapDescriptor.NodeMask = 0;
|
||||||
|
ComPtr<ID3D12DescriptorHeap> heap;
|
||||||
|
ASSERT_SUCCESS(device->GetD3D12Device()->CreateDescriptorHeap(&heapDescriptor, IID_PPV_ARGS(&heap)));
|
||||||
|
AllocationInfo allocationInfo = { descriptorHeapSize, descriptorHeapSize - count };
|
||||||
|
pools.emplace_back(std::make_pair(heap, allocationInfo));
|
||||||
|
|
||||||
|
DescriptorHeapHandle handle(heap, sizeIncrements[type], 0);
|
||||||
|
Release(handle);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptorHeapAllocator::FreeDescriptorHeaps(uint64_t lastCompletedSerial) {
|
||||||
|
releasedHandles.ClearUpTo(lastCompletedSerial);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptorHeapAllocator::Release(DescriptorHeapHandle handle) {
|
||||||
|
releasedHandles.Enqueue(handle, device->GetSerial());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
// 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_DESCRIPTORHEAPALLOCATOR_H_
|
||||||
|
#define BACKEND_D3D12_DESCRIPTORHEAPALLOCATOR_H_
|
||||||
|
|
||||||
|
#include "d3d12_platform.h"
|
||||||
|
|
||||||
|
#include "common/SerialQueue.h"
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace backend {
|
||||||
|
namespace d3d12 {
|
||||||
|
|
||||||
|
class Device;
|
||||||
|
|
||||||
|
class DescriptorHeapHandle {
|
||||||
|
public:
|
||||||
|
DescriptorHeapHandle();
|
||||||
|
DescriptorHeapHandle(ComPtr<ID3D12DescriptorHeap> descriptorHeap, uint32_t sizeIncrement, uint32_t offset);
|
||||||
|
|
||||||
|
ID3D12DescriptorHeap* Get() const;
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHandle(uint32_t index) const;
|
||||||
|
D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandle(uint32_t index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Device* device;
|
||||||
|
ComPtr<ID3D12DescriptorHeap> descriptorHeap;
|
||||||
|
uint32_t sizeIncrement;
|
||||||
|
uint32_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DescriptorHeapAllocator {
|
||||||
|
public:
|
||||||
|
DescriptorHeapAllocator(Device* device);
|
||||||
|
|
||||||
|
DescriptorHeapHandle Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count);
|
||||||
|
void FreeDescriptorHeaps(uint64_t lastCompletedSerial);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Release(DescriptorHeapHandle handle);
|
||||||
|
|
||||||
|
Device* device;
|
||||||
|
|
||||||
|
static constexpr unsigned int kDescriptorHeapTypes = D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
|
||||||
|
|
||||||
|
struct AllocationInfo {
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
using DescriptorHeapPool = std::pair<ComPtr<ID3D12DescriptorHeap>, AllocationInfo>;
|
||||||
|
|
||||||
|
using DescriptorHeapPoolList = std::vector<DescriptorHeapPool>;
|
||||||
|
|
||||||
|
std::array<uint32_t, kDescriptorHeapTypes> sizeIncrements;
|
||||||
|
std::array<DescriptorHeapPoolList, kDescriptorHeapTypes> descriptorHeapPools;
|
||||||
|
SerialQueue<DescriptorHeapHandle> releasedHandles;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BACKEND_D3D12_DESCRIPTORHEAPALLOCATOR_H_
|
|
@ -19,4 +19,6 @@
|
||||||
#include "PipelineD3D12.h"
|
#include "PipelineD3D12.h"
|
||||||
#include "PipelineLayoutD3D12.h"
|
#include "PipelineLayoutD3D12.h"
|
||||||
#include "QueueD3D12.h"
|
#include "QueueD3D12.h"
|
||||||
|
#include "SamplerD3D12.h"
|
||||||
#include "ShaderModuleD3D12.h"
|
#include "ShaderModuleD3D12.h"
|
||||||
|
#include "TextureD3D12.h"
|
||||||
|
|
|
@ -32,6 +32,8 @@ namespace d3d12 {
|
||||||
// Enable better shader debugging with the graphics debugging tools.
|
// Enable better shader debugging with the graphics debugging tools.
|
||||||
compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||||
#endif
|
#endif
|
||||||
|
// SPRIV-cross does matrix multiplication expecting row major matrices
|
||||||
|
compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
|
||||||
|
|
||||||
if (IsCompute()) {
|
if (IsCompute()) {
|
||||||
const auto& module = ToBackend(builder->GetStageInfo(nxt::ShaderStage::Compute).module);
|
const auto& module = ToBackend(builder->GetStageInfo(nxt::ShaderStage::Compute).module);
|
||||||
|
@ -54,7 +56,7 @@ namespace d3d12 {
|
||||||
&compiledShader,
|
&compiledShader,
|
||||||
&errors
|
&errors
|
||||||
))) {
|
))) {
|
||||||
printf("%s\n", errors->GetBufferPointer());
|
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +84,11 @@ namespace d3d12 {
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case nxt::ShaderStage::Vertex:
|
case nxt::ShaderStage::Vertex:
|
||||||
shader = &descriptor.VS;
|
shader = &descriptor.VS;
|
||||||
compileTarget = "vs_5_0";
|
compileTarget = "vs_5_1";
|
||||||
break;
|
break;
|
||||||
case nxt::ShaderStage::Fragment:
|
case nxt::ShaderStage::Fragment:
|
||||||
shader = &descriptor.PS;
|
shader = &descriptor.PS;
|
||||||
compileTarget = "ps_5_0";
|
compileTarget = "ps_5_1";
|
||||||
break;
|
break;
|
||||||
case nxt::ShaderStage::Compute:
|
case nxt::ShaderStage::Compute:
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
@ -106,7 +108,7 @@ namespace d3d12 {
|
||||||
&compiledShader[stage],
|
&compiledShader[stage],
|
||||||
&errors
|
&errors
|
||||||
))) {
|
))) {
|
||||||
printf("%s\n", errors->GetBufferPointer());
|
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,10 +118,15 @@ namespace d3d12 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InputState* inputState = ToBackend(GetInputState());
|
PipelineLayout* layout = ToBackend(GetLayout());
|
||||||
descriptor.InputLayout = inputState->GetD3D12InputLayoutDescriptor();
|
|
||||||
|
|
||||||
descriptor.pRootSignature = ToBackend(GetLayout())->GetRootSignature().Get();
|
descriptor.pRootSignature = layout->GetRootSignature().Get();
|
||||||
|
|
||||||
|
// D3D12 logs warnings if any empty input state is used
|
||||||
|
InputState* inputState = ToBackend(GetInputState());
|
||||||
|
if (inputState->GetAttributesSetMask().any()) {
|
||||||
|
descriptor.InputLayout = inputState->GetD3D12InputLayoutDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
descriptor.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
descriptor.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||||
descriptor.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
descriptor.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "PipelineLayoutD3D12.h"
|
#include "PipelineLayoutD3D12.h"
|
||||||
|
|
||||||
#include "D3D12Backend.h"
|
#include "D3D12Backend.h"
|
||||||
|
#include "BindGroupLayoutD3D12.h"
|
||||||
|
|
||||||
using Microsoft::WRL::ComPtr;
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
|
@ -24,10 +25,59 @@ namespace d3d12 {
|
||||||
PipelineLayout::PipelineLayout(Device* device, PipelineLayoutBuilder* builder)
|
PipelineLayout::PipelineLayout(Device* device, PipelineLayoutBuilder* builder)
|
||||||
: PipelineLayoutBase(builder), device(device) {
|
: PipelineLayoutBase(builder), device(device) {
|
||||||
|
|
||||||
// Create an empty root signature.
|
D3D12_ROOT_PARAMETER rootParameters[kMaxBindGroups * 2];
|
||||||
|
|
||||||
|
// A root parameter is one of these types
|
||||||
|
union {
|
||||||
|
D3D12_ROOT_DESCRIPTOR_TABLE DescriptorTable;
|
||||||
|
D3D12_ROOT_CONSTANTS Constants;
|
||||||
|
D3D12_ROOT_DESCRIPTOR Descriptor;
|
||||||
|
} rootParameterValues[kMaxBindGroups * 2];
|
||||||
|
// samplers must be in a separate descriptor table so we need at most twice as many tables as bind groups
|
||||||
|
|
||||||
|
// Ranges are D3D12_DESCRIPTOR_RANGE_TYPE_(SRV|UAV|CBV|SAMPLER)
|
||||||
|
// They are grouped together so each bind group has at most 4 ranges
|
||||||
|
D3D12_DESCRIPTOR_RANGE ranges[kMaxBindGroups * 4];
|
||||||
|
|
||||||
|
uint32_t parameterIndex = 0;
|
||||||
|
uint32_t rangeIndex = 0;
|
||||||
|
|
||||||
|
for (uint32_t group = 0; group < kMaxBindGroups; ++group) {
|
||||||
|
const BindGroupLayout* bindGroupLayout = ToBackend(GetBindGroupLayout(group));
|
||||||
|
|
||||||
|
// Set the root descriptor table parameter and copy ranges. Ranges are offset by the bind group index
|
||||||
|
// Returns whether or not the parameter was set. A root parameter is not set if the number of ranges is 0
|
||||||
|
auto SetRootDescriptorTable = [&](uint32_t rangeCount, const D3D12_DESCRIPTOR_RANGE* descriptorRanges) -> bool {
|
||||||
|
if (rangeCount > 0) {
|
||||||
|
auto& rootParameter = rootParameters[parameterIndex];
|
||||||
|
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||||
|
rootParameter.DescriptorTable = rootParameterValues[parameterIndex].DescriptorTable;
|
||||||
|
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||||
|
rootParameter.DescriptorTable.NumDescriptorRanges = rangeCount;
|
||||||
|
rootParameter.DescriptorTable.pDescriptorRanges = &ranges[rangeIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < rangeCount; ++i) {
|
||||||
|
ranges[rangeIndex] = descriptorRanges[i];
|
||||||
|
ranges[rangeIndex].BaseShaderRegister = group * kMaxBindingsPerGroup;
|
||||||
|
rangeIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (rangeCount > 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (SetRootDescriptorTable(bindGroupLayout->GetCbvUavSrvDescriptorTableSize(), bindGroupLayout->GetCbvUavSrvDescriptorRanges())) {
|
||||||
|
cbvUavSrvRootParameterInfo[group] = parameterIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SetRootDescriptorTable(bindGroupLayout->GetSamplerDescriptorTableSize(), bindGroupLayout->GetSamplerDescriptorRanges())) {
|
||||||
|
samplerRootParameterInfo[group] = parameterIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
D3D12_ROOT_SIGNATURE_DESC rootSignatureDescriptor;
|
D3D12_ROOT_SIGNATURE_DESC rootSignatureDescriptor;
|
||||||
rootSignatureDescriptor.NumParameters = 0;
|
rootSignatureDescriptor.NumParameters = parameterIndex;
|
||||||
rootSignatureDescriptor.pParameters = nullptr;
|
rootSignatureDescriptor.pParameters = rootParameters;
|
||||||
rootSignatureDescriptor.NumStaticSamplers = 0;
|
rootSignatureDescriptor.NumStaticSamplers = 0;
|
||||||
rootSignatureDescriptor.pStaticSamplers = nullptr;
|
rootSignatureDescriptor.pStaticSamplers = nullptr;
|
||||||
rootSignatureDescriptor.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
rootSignatureDescriptor.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||||
|
@ -38,9 +88,19 @@ namespace d3d12 {
|
||||||
ASSERT_SUCCESS(device->GetD3D12Device()->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature)));
|
ASSERT_SUCCESS(device->GetD3D12Device()->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t PipelineLayout::GetCbvUavSrvRootParameterIndex(uint32_t group) const {
|
||||||
|
ASSERT(group < kMaxBindGroups);
|
||||||
|
return cbvUavSrvRootParameterInfo[group];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PipelineLayout::GetSamplerRootParameterIndex(uint32_t group) const {
|
||||||
|
ASSERT(group < kMaxBindGroups);
|
||||||
|
return samplerRootParameterInfo[group];
|
||||||
|
}
|
||||||
|
|
||||||
ComPtr<ID3D12RootSignature> PipelineLayout::GetRootSignature() {
|
ComPtr<ID3D12RootSignature> PipelineLayout::GetRootSignature() {
|
||||||
return rootSignature;
|
return rootSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,35 @@ namespace d3d12 {
|
||||||
public:
|
public:
|
||||||
PipelineLayout(Device* device, PipelineLayoutBuilder* builder);
|
PipelineLayout(Device* device, PipelineLayoutBuilder* builder);
|
||||||
|
|
||||||
|
class Descriptor {
|
||||||
|
public:
|
||||||
|
enum class Type {
|
||||||
|
CBV,
|
||||||
|
UAV,
|
||||||
|
SRV,
|
||||||
|
Sampler,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
static constexpr unsigned int TypeCount = static_cast<typename std::underlying_type<Type>::type>(Type::Count);
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t GetCbvUavSrvRootParameterIndex(uint32_t group) const;
|
||||||
|
uint32_t GetSamplerRootParameterIndex(uint32_t group) const;
|
||||||
|
|
||||||
ComPtr<ID3D12RootSignature> GetRootSignature();
|
ComPtr<ID3D12RootSignature> GetRootSignature();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
static constexpr unsigned int ToIndex(Descriptor::Type type) {
|
||||||
|
return static_cast<typename std::underlying_type<Descriptor::Type>::type>(type);
|
||||||
|
}
|
||||||
|
|
||||||
Device* device;
|
Device* device;
|
||||||
|
|
||||||
|
std::array<uint32_t, kMaxBindGroups> cbvUavSrvRootParameterInfo;
|
||||||
|
std::array<uint32_t, kMaxBindGroups> samplerRootParameterInfo;
|
||||||
|
std::array<std::array<uint32_t, Descriptor::TypeCount>, kMaxBindGroups> descriptorCountInfo;
|
||||||
|
|
||||||
ComPtr<ID3D12RootSignature> rootSignature;
|
ComPtr<ID3D12RootSignature> rootSignature;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
// 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 "SamplerD3D12.h"
|
||||||
|
|
||||||
|
#include "D3D12Backend.h"
|
||||||
|
|
||||||
|
namespace backend {
|
||||||
|
namespace d3d12 {
|
||||||
|
|
||||||
|
Sampler::Sampler(SamplerBuilder* builder)
|
||||||
|
: SamplerBase(builder) {
|
||||||
|
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn770367(v=vs.85).aspx
|
||||||
|
// D3D12_FILTER_MIN_MAG_MIP_POINT = 0 0 0 0 0 // hex value, decimal value, min linear, mag linear, mip linear
|
||||||
|
// D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR = 0x1 1 0 0 1
|
||||||
|
// D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x4 4 0 1 0
|
||||||
|
// D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR = 0x5 5 0 1 1
|
||||||
|
// D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT = 0x10 16 1 0 0
|
||||||
|
// D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x11 17 1 0 1
|
||||||
|
// D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x14 20 1 1 0
|
||||||
|
// D3D12_FILTER_MIN_MAG_MIP_LINEAR = 0x15 21 1 1 1
|
||||||
|
|
||||||
|
// if mip mode is linear, add 1
|
||||||
|
// if mag mode is linear, add 4
|
||||||
|
// if min mode is linear, add 16
|
||||||
|
|
||||||
|
uint8_t mode = 0;
|
||||||
|
|
||||||
|
switch (builder->GetMinFilter()) {
|
||||||
|
case nxt::FilterMode::Nearest:
|
||||||
|
break;
|
||||||
|
case nxt::FilterMode::Linear:
|
||||||
|
mode += 16;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (builder->GetMagFilter()) {
|
||||||
|
case nxt::FilterMode::Nearest:
|
||||||
|
break;
|
||||||
|
case nxt::FilterMode::Linear:
|
||||||
|
mode += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (builder->GetMipMapFilter()) {
|
||||||
|
case nxt::FilterMode::Nearest:
|
||||||
|
break;
|
||||||
|
case nxt::FilterMode::Linear:
|
||||||
|
mode += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
samplerDesc.Filter = static_cast<D3D12_FILTER>(mode);
|
||||||
|
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
|
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
|
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
|
samplerDesc.MipLODBias = 0.f;
|
||||||
|
samplerDesc.MaxAnisotropy = 1;
|
||||||
|
samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||||
|
samplerDesc.BorderColor[0] = samplerDesc.BorderColor[1] = samplerDesc.BorderColor[2] = samplerDesc.BorderColor[3] = 0;
|
||||||
|
samplerDesc.MinLOD = 0;
|
||||||
|
samplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const D3D12_SAMPLER_DESC& Sampler::GetSamplerDescriptor() const {
|
||||||
|
return samplerDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
// 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_SAMPLERD3D12_H_
|
||||||
|
#define BACKEND_D3D12_SAMPLERD3D12_H_
|
||||||
|
|
||||||
|
#include "common/Sampler.h"
|
||||||
|
|
||||||
|
#include "d3d12_platform.h"
|
||||||
|
|
||||||
|
namespace backend {
|
||||||
|
namespace d3d12 {
|
||||||
|
|
||||||
|
class Sampler : public SamplerBase {
|
||||||
|
public:
|
||||||
|
Sampler(SamplerBuilder* builder);
|
||||||
|
|
||||||
|
const D3D12_SAMPLER_DESC& GetSamplerDescriptor() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
D3D12_SAMPLER_DESC samplerDesc;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BACKEND_D3D12_SAMPLERD3D12_H_
|
|
@ -24,7 +24,7 @@ namespace d3d12 {
|
||||||
spirv_cross::CompilerHLSL compiler(builder->AcquireSpirv());
|
spirv_cross::CompilerHLSL compiler(builder->AcquireSpirv());
|
||||||
|
|
||||||
spirv_cross::CompilerHLSL::Options options;
|
spirv_cross::CompilerHLSL::Options options;
|
||||||
options.shader_model = 40;
|
options.shader_model = 51;
|
||||||
options.flip_vert_y = false;
|
options.flip_vert_y = false;
|
||||||
options.fixup_clipspace = true;
|
options.fixup_clipspace = true;
|
||||||
|
|
||||||
|
@ -32,7 +32,46 @@ namespace d3d12 {
|
||||||
|
|
||||||
ExtractSpirvInfo(compiler);
|
ExtractSpirvInfo(compiler);
|
||||||
|
|
||||||
|
enum RegisterType {
|
||||||
|
Buffer,
|
||||||
|
UnorderedAccess,
|
||||||
|
Texture,
|
||||||
|
Sampler,
|
||||||
|
Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<uint32_t, RegisterType::Count * kMaxBindGroups> baseRegisters = {};
|
||||||
|
|
||||||
|
const auto& resources = compiler.get_shader_resources();
|
||||||
|
|
||||||
|
// rename bindings so that each register type b/u/t/s starts at 0 and then offset by kMaxBindingsPerGroup * bindGroupIndex
|
||||||
|
auto RenumberBindings = [&](std::vector<spirv_cross::Resource> resources, uint32_t offset) {
|
||||||
|
for (const auto& resource : resources) {
|
||||||
|
auto bindGroupIndex = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);
|
||||||
|
auto& baseRegister = baseRegisters[RegisterType::Count * bindGroupIndex + offset];
|
||||||
|
auto bindGroupOffset = bindGroupIndex * kMaxBindingsPerGroup;
|
||||||
|
compiler.set_decoration(resource.id, spv::DecorationBinding, bindGroupOffset + baseRegister++);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RenumberBindings(resources.uniform_buffers, RegisterType::Buffer);
|
||||||
|
RenumberBindings(resources.storage_buffers, RegisterType::UnorderedAccess);
|
||||||
|
RenumberBindings(resources.separate_images, RegisterType::Texture);
|
||||||
|
RenumberBindings(resources.separate_samplers, RegisterType::Sampler);
|
||||||
|
|
||||||
hlslSource = compiler.compile();
|
hlslSource = compiler.compile();
|
||||||
|
|
||||||
|
{
|
||||||
|
// pending https://github.com/KhronosGroup/SPIRV-Cross/issues/216
|
||||||
|
// rename ": register(cN)" to ": register(bN)"
|
||||||
|
std::string::size_type pos = 0;
|
||||||
|
const std::string search = ": register(c";
|
||||||
|
const std::string replace = ": register(b";
|
||||||
|
while ((pos = hlslSource.find(search, pos)) != std::string::npos) {
|
||||||
|
hlslSource.replace(pos, search.length(), replace);
|
||||||
|
pos += replace.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ShaderModule::GetHLSLSource() const {
|
const std::string& ShaderModule::GetHLSLSource() const {
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
// 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 "TextureD3D12.h"
|
||||||
|
|
||||||
|
#include "D3D12Backend.h"
|
||||||
|
#include "ResourceAllocator.h"
|
||||||
|
|
||||||
|
namespace backend {
|
||||||
|
namespace d3d12 {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
D3D12_RESOURCE_STATES D3D12TextureUsage(nxt::TextureUsageBit usage) {
|
||||||
|
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON;
|
||||||
|
|
||||||
|
if (usage & nxt::TextureUsageBit::TransferSrc) {
|
||||||
|
resourceState |= D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||||
|
}
|
||||||
|
if (usage & nxt::TextureUsageBit::TransferDst) {
|
||||||
|
resourceState |= D3D12_RESOURCE_STATE_COPY_DEST;
|
||||||
|
}
|
||||||
|
if (usage & nxt::TextureUsageBit::Sampled) {
|
||||||
|
resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||||
|
}
|
||||||
|
if (usage & nxt::TextureUsageBit::Storage) {
|
||||||
|
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||||
|
}
|
||||||
|
if (usage & nxt::TextureUsageBit::ColorAttachment) {
|
||||||
|
resourceState |= D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||||
|
}
|
||||||
|
if (usage & nxt::TextureUsageBit::DepthStencilAttachment) {
|
||||||
|
resourceState |= D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceState;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_RESOURCE_FLAGS D3D12ResourceFlags(nxt::TextureUsageBit usage) {
|
||||||
|
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
|
if (usage & nxt::TextureUsageBit::Storage) {
|
||||||
|
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||||
|
}
|
||||||
|
if (usage & nxt::TextureUsageBit::ColorAttachment) {
|
||||||
|
flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||||
|
}
|
||||||
|
if (usage & nxt::TextureUsageBit::DepthStencilAttachment) {
|
||||||
|
flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_RESOURCE_DIMENSION D3D12TextureDimension(nxt::TextureDimension dimension) {
|
||||||
|
switch (dimension) {
|
||||||
|
case nxt::TextureDimension::e2D:
|
||||||
|
return D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_FORMAT D3D12TextureFormat(nxt::TextureFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case nxt::TextureFormat::R8G8B8A8Unorm:
|
||||||
|
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::Texture(Device* device, TextureBuilder* builder)
|
||||||
|
: TextureBase(builder), device(device) {
|
||||||
|
|
||||||
|
D3D12_RESOURCE_DESC resourceDescriptor;
|
||||||
|
resourceDescriptor.Dimension = D3D12TextureDimension(GetDimension());
|
||||||
|
resourceDescriptor.Alignment = 0;
|
||||||
|
resourceDescriptor.Width = GetWidth();
|
||||||
|
resourceDescriptor.Height = GetHeight();
|
||||||
|
resourceDescriptor.DepthOrArraySize = GetDepth();
|
||||||
|
resourceDescriptor.MipLevels = GetNumMipLevels();
|
||||||
|
resourceDescriptor.Format = D3D12TextureFormat(GetFormat());
|
||||||
|
resourceDescriptor.SampleDesc.Count = 1;
|
||||||
|
resourceDescriptor.SampleDesc.Quality = 0;
|
||||||
|
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||||
|
resourceDescriptor.Flags = D3D12ResourceFlags(GetUsage());
|
||||||
|
|
||||||
|
resource = device->GetResourceAllocator()->Allocate(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor, D3D12TextureUsage(GetUsage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::~Texture() {
|
||||||
|
device->GetResourceAllocator()->Release(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<ID3D12Resource> Texture::GetD3D12Resource() {
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Texture::GetResourceTransitionBarrier(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier) {
|
||||||
|
D3D12_RESOURCE_STATES stateBefore = D3D12TextureUsage(currentUsage);
|
||||||
|
D3D12_RESOURCE_STATES stateAfter = D3D12TextureUsage(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::TransitionUsageImpl(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage) {
|
||||||
|
D3D12_RESOURCE_BARRIER barrier;
|
||||||
|
if (GetResourceTransitionBarrier(currentUsage, targetUsage, &barrier)) {
|
||||||
|
device->GetPendingCommandList()->ResourceBarrier(1, &barrier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureView::TextureView(Device* device, TextureViewBuilder* builder)
|
||||||
|
: TextureViewBase(builder) {
|
||||||
|
|
||||||
|
srvDesc.Format = D3D12TextureFormat(GetTexture()->GetFormat());
|
||||||
|
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||||
|
switch (GetTexture()->GetDimension()) {
|
||||||
|
case nxt::TextureDimension::e2D:
|
||||||
|
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||||
|
srvDesc.Texture2D.MipLevels = GetTexture()->GetNumMipLevels();
|
||||||
|
srvDesc.Texture2D.PlaneSlice = 0;
|
||||||
|
srvDesc.Texture2D.ResourceMinLODClamp = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const D3D12_SHADER_RESOURCE_VIEW_DESC& TextureView::GetSRVDescriptor() const {
|
||||||
|
return srvDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
// 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_TEXTURED3D12_H_
|
||||||
|
#define BACKEND_D3D12_TEXTURED3D12_H_
|
||||||
|
|
||||||
|
#include "common/Texture.h"
|
||||||
|
|
||||||
|
#include "d3d12_platform.h"
|
||||||
|
|
||||||
|
namespace backend {
|
||||||
|
namespace d3d12 {
|
||||||
|
|
||||||
|
class Device;
|
||||||
|
|
||||||
|
class Texture : public TextureBase {
|
||||||
|
public:
|
||||||
|
Texture(Device* device, TextureBuilder* builder);
|
||||||
|
~Texture();
|
||||||
|
|
||||||
|
ComPtr<ID3D12Resource> GetD3D12Resource();
|
||||||
|
bool GetResourceTransitionBarrier(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Device* device;
|
||||||
|
ComPtr<ID3D12Resource> resource;
|
||||||
|
|
||||||
|
// NXT API
|
||||||
|
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextureView : public TextureViewBase {
|
||||||
|
public:
|
||||||
|
TextureView(Device* device, TextureViewBuilder* builder);
|
||||||
|
|
||||||
|
const D3D12_SHADER_RESOURCE_VIEW_DESC& GetSRVDescriptor() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BACKEND_D3D12_TEXTURED3D12_H_
|
Loading…
Reference in New Issue