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}/CommandBufferD3D12.cpp
|
||||
${D3D12_DIR}/CommandBufferD3D12.h
|
||||
${D3D12_DIR}/DescriptorHeapAllocator.cpp
|
||||
${D3D12_DIR}/DescriptorHeapAllocator.h
|
||||
${D3D12_DIR}/D3D12Backend.cpp
|
||||
${D3D12_DIR}/D3D12Backend.h
|
||||
${D3D12_DIR}/InputStateD3D12.cpp
|
||||
|
@ -257,8 +259,12 @@ if (WIN32)
|
|||
${D3D12_DIR}/ResourceAllocator.h
|
||||
${D3D12_DIR}/ResourceUploader.cpp
|
||||
${D3D12_DIR}/ResourceUploader.h
|
||||
${D3D12_DIR}/SamplerD3D12.cpp
|
||||
${D3D12_DIR}/SamplerD3D12.h
|
||||
${D3D12_DIR}/ShaderModuleD3D12.cpp
|
||||
${D3D12_DIR}/ShaderModuleD3D12.h
|
||||
${D3D12_DIR}/TextureD3D12.cpp
|
||||
${D3D12_DIR}/TextureD3D12.h
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -218,6 +218,85 @@ namespace backend {
|
|||
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)) {
|
||||
}
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ namespace backend {
|
|||
// 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.
|
||||
void FreeCommands(CommandIterator* commands);
|
||||
void SkipCommand(CommandIterator* commands, Command type);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace d3d12 {
|
|||
D3D12_RESOURCE_DESC resourceDescriptor;
|
||||
resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resourceDescriptor.Alignment = 0;
|
||||
resourceDescriptor.Width = GetSize();
|
||||
resourceDescriptor.Width = GetD3D12Size();
|
||||
resourceDescriptor.Height = 1;
|
||||
resourceDescriptor.DepthOrArraySize = 1;
|
||||
resourceDescriptor.MipLevels = 1;
|
||||
|
@ -68,6 +68,11 @@ namespace d3d12 {
|
|||
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() {
|
||||
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();
|
||||
|
||||
uint32_t GetD3D12Size() const;
|
||||
ComPtr<ID3D12Resource> GetD3D12Resource();
|
||||
D3D12_GPU_VIRTUAL_ADDRESS GetVA() const;
|
||||
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 "D3D12Backend.h"
|
||||
#include "DescriptorHeapAllocator.h"
|
||||
#include "BufferD3D12.h"
|
||||
#include "InputStateD3D12.h"
|
||||
#include "PipelineD3D12.h"
|
||||
#include "PipelineLayoutD3D12.h"
|
||||
#include "SamplerD3D12.h"
|
||||
#include "TextureD3D12.h"
|
||||
|
||||
namespace backend {
|
||||
namespace d3d12 {
|
||||
|
@ -33,6 +36,146 @@ namespace d3d12 {
|
|||
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)
|
||||
|
@ -44,8 +187,59 @@ namespace d3d12 {
|
|||
}
|
||||
|
||||
void CommandBuffer::FillCommands(ComPtr<ID3D12GraphicsCommandList> commandList) {
|
||||
BindGroupStateTracker bindingTracker(device);
|
||||
|
||||
{
|
||||
Command type;
|
||||
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;
|
||||
Framebuffer* currentFramebuffer = nullptr;
|
||||
|
@ -64,10 +258,10 @@ namespace d3d12 {
|
|||
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 };
|
||||
uint32_t width = currentFramebuffer->GetWidth();
|
||||
uint32_t height = currentFramebuffer->GetHeight();
|
||||
D3D12_VIEWPORT viewport = { 0.f, 0.f, static_cast<float>(width), static_cast<float>(height), 0.f, 1.f };
|
||||
D3D12_RECT scissorRect = { 0, 0, static_cast<long>(width), static_cast<long>(height) };
|
||||
commandList->RSSetViewports(1, &viewport);
|
||||
commandList->RSSetScissorRects(1, &scissorRect);
|
||||
commandList->OMSetRenderTargets(1, &device->GetCurrentRenderTargetDescriptor(), FALSE, nullptr);
|
||||
|
@ -139,15 +333,33 @@ namespace d3d12 {
|
|||
case Command::SetPipeline:
|
||||
{
|
||||
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
|
||||
if (lastPipeline->IsCompute()) {
|
||||
} else {
|
||||
commandList->SetGraphicsRootSignature(pipelineLayout->GetRootSignature().Get());
|
||||
commandList->SetPipelineState(lastPipeline->GetRenderPipelineState().Get());
|
||||
if (pipeline->IsCompute()) {
|
||||
}
|
||||
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;
|
||||
|
||||
|
@ -166,6 +378,8 @@ namespace d3d12 {
|
|||
case Command::SetBindGroup:
|
||||
{
|
||||
SetBindGroupCmd* cmd = commands.NextCommand<SetBindGroupCmd>();
|
||||
BindGroup* group = ToBackend(cmd->group.Get());
|
||||
bindingTracker.SetBindGroup(lastPipeline, group, cmd->index, commandList);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -224,6 +438,12 @@ namespace d3d12 {
|
|||
TransitionTextureUsageCmd* cmd = commands.NextCommand<TransitionTextureUsageCmd>();
|
||||
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -20,9 +20,12 @@
|
|||
#include "PipelineD3D12.h"
|
||||
#include "PipelineLayoutD3D12.h"
|
||||
#include "QueueD3D12.h"
|
||||
#include "SamplerD3D12.h"
|
||||
#include "ShaderModuleD3D12.h"
|
||||
#include "TextureD3D12.h"
|
||||
|
||||
#include "CommandAllocatorManager.h"
|
||||
#include "DescriptorHeapAllocator.h"
|
||||
#include "ResourceAllocator.h"
|
||||
#include "ResourceUploader.h"
|
||||
|
||||
|
@ -80,6 +83,7 @@ namespace d3d12 {
|
|||
Device::Device(ComPtr<ID3D12Device> d3d12Device)
|
||||
: d3d12Device(d3d12Device),
|
||||
commandAllocatorManager(new CommandAllocatorManager(this)),
|
||||
descriptorHeapAllocator(new DescriptorHeapAllocator(this)),
|
||||
resourceAllocator(new ResourceAllocator(this)),
|
||||
resourceUploader(new ResourceUploader(this)) {
|
||||
|
||||
|
@ -104,6 +108,10 @@ namespace d3d12 {
|
|||
return commandQueue;
|
||||
}
|
||||
|
||||
DescriptorHeapAllocator* Device::GetDescriptorHeapAllocator() {
|
||||
return descriptorHeapAllocator;
|
||||
}
|
||||
|
||||
ResourceAllocator* Device::GetResourceAllocator() {
|
||||
return resourceAllocator;
|
||||
}
|
||||
|
@ -142,6 +150,8 @@ namespace d3d12 {
|
|||
|
||||
void Device::SetNextRenderTargetDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE 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() {
|
||||
|
@ -149,6 +159,7 @@ namespace d3d12 {
|
|||
const uint64_t lastCompletedSerial = fence->GetCompletedValue();
|
||||
resourceAllocator->FreeUnusedResources(lastCompletedSerial);
|
||||
commandAllocatorManager->ResetCompletedAllocators(lastCompletedSerial);
|
||||
descriptorHeapAllocator->FreeDescriptorHeaps(lastCompletedSerial);
|
||||
}
|
||||
|
||||
uint64_t Device::GetSerial() const {
|
||||
|
@ -219,7 +230,7 @@ namespace d3d12 {
|
|||
return new RenderPass(this, builder);
|
||||
}
|
||||
SamplerBase* Device::CreateSampler(SamplerBuilder* builder) {
|
||||
return new Sampler(this, builder);
|
||||
return new Sampler(builder);
|
||||
}
|
||||
ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) {
|
||||
return new ShaderModule(this, builder);
|
||||
|
@ -249,12 +260,6 @@ namespace d3d12 {
|
|||
: BindGroupLayoutBase(builder), device(device) {
|
||||
}
|
||||
|
||||
// BufferView
|
||||
|
||||
BufferView::BufferView(Device* device, BufferViewBuilder* builder)
|
||||
: BufferViewBase(builder), device(device) {
|
||||
}
|
||||
|
||||
// DepthStencilState
|
||||
|
||||
DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder)
|
||||
|
@ -273,26 +278,5 @@ namespace d3d12 {
|
|||
: 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 CommandAllocatorManager;
|
||||
class DescriptorHeapAllocator;
|
||||
class ResourceAllocator;
|
||||
class ResourceUploader;
|
||||
|
||||
|
@ -113,6 +114,7 @@ namespace d3d12 {
|
|||
ComPtr<ID3D12Device> GetD3D12Device();
|
||||
ComPtr<ID3D12CommandQueue> GetCommandQueue();
|
||||
|
||||
DescriptorHeapAllocator* GetDescriptorHeapAllocator();
|
||||
ResourceAllocator* GetResourceAllocator();
|
||||
ResourceUploader* GetResourceUploader();
|
||||
|
||||
|
@ -141,6 +143,7 @@ namespace d3d12 {
|
|||
ComPtr<ID3D12CommandQueue> commandQueue;
|
||||
|
||||
CommandAllocatorManager* commandAllocatorManager;
|
||||
DescriptorHeapAllocator* descriptorHeapAllocator;
|
||||
ResourceAllocator* resourceAllocator;
|
||||
ResourceUploader* resourceUploader;
|
||||
|
||||
|
@ -169,14 +172,6 @@ namespace d3d12 {
|
|||
Device* device;
|
||||
};
|
||||
|
||||
class BufferView : public BufferViewBase {
|
||||
public:
|
||||
BufferView(Device* device, BufferViewBuilder* builder);
|
||||
|
||||
private:
|
||||
Device* device;
|
||||
};
|
||||
|
||||
class Framebuffer : public FramebufferBase {
|
||||
public:
|
||||
Framebuffer(Device* device, FramebufferBuilder* builder);
|
||||
|
@ -201,32 +196,6 @@ namespace d3d12 {
|
|||
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 "PipelineLayoutD3D12.h"
|
||||
#include "QueueD3D12.h"
|
||||
#include "SamplerD3D12.h"
|
||||
#include "ShaderModuleD3D12.h"
|
||||
#include "TextureD3D12.h"
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace d3d12 {
|
|||
// Enable better shader debugging with the graphics debugging tools.
|
||||
compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
#endif
|
||||
// SPRIV-cross does matrix multiplication expecting row major matrices
|
||||
compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
|
||||
|
||||
if (IsCompute()) {
|
||||
const auto& module = ToBackend(builder->GetStageInfo(nxt::ShaderStage::Compute).module);
|
||||
|
@ -54,7 +56,7 @@ namespace d3d12 {
|
|||
&compiledShader,
|
||||
&errors
|
||||
))) {
|
||||
printf("%s\n", errors->GetBufferPointer());
|
||||
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
|
@ -82,11 +84,11 @@ namespace d3d12 {
|
|||
switch (stage) {
|
||||
case nxt::ShaderStage::Vertex:
|
||||
shader = &descriptor.VS;
|
||||
compileTarget = "vs_5_0";
|
||||
compileTarget = "vs_5_1";
|
||||
break;
|
||||
case nxt::ShaderStage::Fragment:
|
||||
shader = &descriptor.PS;
|
||||
compileTarget = "ps_5_0";
|
||||
compileTarget = "ps_5_1";
|
||||
break;
|
||||
case nxt::ShaderStage::Compute:
|
||||
ASSERT(false);
|
||||
|
@ -106,7 +108,7 @@ namespace d3d12 {
|
|||
&compiledShader[stage],
|
||||
&errors
|
||||
))) {
|
||||
printf("%s\n", errors->GetBufferPointer());
|
||||
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
|
@ -116,10 +118,15 @@ namespace d3d12 {
|
|||
}
|
||||
}
|
||||
|
||||
InputState* inputState = ToBackend(GetInputState());
|
||||
descriptor.InputLayout = inputState->GetD3D12InputLayoutDescriptor();
|
||||
PipelineLayout* layout = ToBackend(GetLayout());
|
||||
|
||||
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.CullMode = D3D12_CULL_MODE_NONE;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "PipelineLayoutD3D12.h"
|
||||
|
||||
#include "D3D12Backend.h"
|
||||
#include "BindGroupLayoutD3D12.h"
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
|
@ -24,10 +25,59 @@ namespace d3d12 {
|
|||
PipelineLayout::PipelineLayout(Device* device, PipelineLayoutBuilder* builder)
|
||||
: 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;
|
||||
rootSignatureDescriptor.NumParameters = 0;
|
||||
rootSignatureDescriptor.pParameters = nullptr;
|
||||
rootSignatureDescriptor.NumParameters = parameterIndex;
|
||||
rootSignatureDescriptor.pParameters = rootParameters;
|
||||
rootSignatureDescriptor.NumStaticSamplers = 0;
|
||||
rootSignatureDescriptor.pStaticSamplers = nullptr;
|
||||
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)));
|
||||
}
|
||||
|
||||
|
||||
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() {
|
||||
return rootSignature;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,11 +28,35 @@ namespace d3d12 {
|
|||
public:
|
||||
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();
|
||||
|
||||
private:
|
||||
|
||||
static constexpr unsigned int ToIndex(Descriptor::Type type) {
|
||||
return static_cast<typename std::underlying_type<Descriptor::Type>::type>(type);
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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::Options options;
|
||||
options.shader_model = 40;
|
||||
options.shader_model = 51;
|
||||
options.flip_vert_y = false;
|
||||
options.fixup_clipspace = true;
|
||||
|
||||
|
@ -32,7 +32,46 @@ namespace d3d12 {
|
|||
|
||||
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();
|
||||
|
||||
{
|
||||
// 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 {
|
||||
|
|
|
@ -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