Format: src/backend/d3d12

This commit is contained in:
Corentin Wallez 2017-11-24 14:04:22 -05:00 committed by Corentin Wallez
parent c1400f0d14
commit 2d62a371ee
46 changed files with 1141 additions and 1161 deletions

View File

@ -12,23 +12,26 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "common/BitSetIterator.h"
#include "backend/d3d12/BindGroupD3D12.h" #include "backend/d3d12/BindGroupD3D12.h"
#include "backend/d3d12/BindGroupLayoutD3D12.h" #include "backend/d3d12/BindGroupLayoutD3D12.h"
#include "backend/d3d12/BufferD3D12.h" #include "backend/d3d12/BufferD3D12.h"
#include "backend/d3d12/SamplerD3D12.h" #include "backend/d3d12/SamplerD3D12.h"
#include "backend/d3d12/TextureD3D12.h" #include "backend/d3d12/TextureD3D12.h"
#include "common/BitSetIterator.h"
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
BindGroup::BindGroup(Device* device, BindGroupBuilder* builder) BindGroup::BindGroup(Device* device, BindGroupBuilder* builder)
: BindGroupBase(builder), mDevice(device) { : BindGroupBase(builder), mDevice(device) {
} }
void BindGroup::RecordDescriptors(const DescriptorHeapHandle &cbvUavSrvHeapStart, uint32_t* cbvUavSrvHeapOffset, const DescriptorHeapHandle &samplerHeapStart, uint32_t* samplerHeapOffset, uint64_t serial) { void BindGroup::RecordDescriptors(const DescriptorHeapHandle& cbvUavSrvHeapStart,
uint32_t* cbvUavSrvHeapOffset,
const DescriptorHeapHandle& samplerHeapStart,
uint32_t* samplerHeapOffset,
uint64_t serial) {
mHeapSerial = serial; mHeapSerial = serial;
const auto* bgl = ToBackend(GetLayout()); const auto* bgl = ToBackend(GetLayout());
@ -43,34 +46,36 @@ namespace d3d12 {
auto d3d12Device = mDevice->GetD3D12Device(); auto d3d12Device = mDevice->GetD3D12Device();
for (uint32_t binding : IterateBitSet(layout.mask)) { for (uint32_t binding : IterateBitSet(layout.mask)) {
switch (layout.types[binding]) { switch (layout.types[binding]) {
case nxt::BindingType::UniformBuffer: case nxt::BindingType::UniformBuffer: {
{ auto* view = ToBackend(GetBindingAsBufferView(binding));
auto* view = ToBackend(GetBindingAsBufferView(binding)); auto& cbv = view->GetCBVDescriptor();
auto& cbv = view->GetCBVDescriptor(); d3d12Device->CreateConstantBufferView(
d3d12Device->CreateConstantBufferView(&cbv, cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset + bindingOffsets[binding])); &cbv, cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset +
} bindingOffsets[binding]));
break; } break;
case nxt::BindingType::StorageBuffer: case nxt::BindingType::StorageBuffer: {
{ auto* view = ToBackend(GetBindingAsBufferView(binding));
auto* view = ToBackend(GetBindingAsBufferView(binding)); auto& uav = view->GetUAVDescriptor();
auto& uav = view->GetUAVDescriptor(); d3d12Device->CreateUnorderedAccessView(
d3d12Device->CreateUnorderedAccessView(ToBackend(view->GetBuffer())->GetD3D12Resource().Get(), nullptr, &uav, cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset + bindingOffsets[binding])); ToBackend(view->GetBuffer())->GetD3D12Resource().Get(), nullptr, &uav,
} cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset +
break; bindingOffsets[binding]));
case nxt::BindingType::SampledTexture: } break;
{ case nxt::BindingType::SampledTexture: {
auto* view = ToBackend(GetBindingAsTextureView(binding)); auto* view = ToBackend(GetBindingAsTextureView(binding));
auto& srv = view->GetSRVDescriptor(); auto& srv = view->GetSRVDescriptor();
d3d12Device->CreateShaderResourceView(ToBackend(view->GetTexture())->GetD3D12Resource(), &srv, cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset + bindingOffsets[binding])); d3d12Device->CreateShaderResourceView(
} ToBackend(view->GetTexture())->GetD3D12Resource(), &srv,
break; cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset +
case nxt::BindingType::Sampler: bindingOffsets[binding]));
{ } break;
auto* sampler = ToBackend(GetBindingAsSampler(binding)); case nxt::BindingType::Sampler: {
auto& samplerDesc = sampler->GetSamplerDescriptor(); auto* sampler = ToBackend(GetBindingAsSampler(binding));
d3d12Device->CreateSampler(&samplerDesc, samplerHeapStart.GetCPUHandle(*samplerHeapOffset + bindingOffsets[binding])); auto& samplerDesc = sampler->GetSamplerDescriptor();
} d3d12Device->CreateSampler(
break; &samplerDesc, samplerHeapStart.GetCPUHandle(*samplerHeapOffset +
bindingOffsets[binding]));
} break;
} }
} }
@ -91,5 +96,4 @@ namespace d3d12 {
return mHeapSerial; return mHeapSerial;
} }
} }} // namespace backend::d3d12
}

View File

@ -21,30 +21,32 @@
#include "backend/d3d12/DescriptorHeapAllocator.h" #include "backend/d3d12/DescriptorHeapAllocator.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class BindGroup : public BindGroupBase { class BindGroup : public BindGroupBase {
public: public:
BindGroup(Device* device, BindGroupBuilder* builder); BindGroup(Device* device, BindGroupBuilder* builder);
void RecordDescriptors(const DescriptorHeapHandle &cbvSrvUavHeapStart, uint32_t* cbvUavSrvHeapOffset, const DescriptorHeapHandle &samplerHeapStart, uint32_t* samplerHeapOffset, uint64_t serial); void RecordDescriptors(const DescriptorHeapHandle& cbvSrvUavHeapStart,
uint32_t GetCbvUavSrvHeapOffset() const; uint32_t* cbvUavSrvHeapOffset,
uint32_t GetSamplerHeapOffset() const; const DescriptorHeapHandle& samplerHeapStart,
uint64_t GetHeapSerial() const; uint32_t* samplerHeapOffset,
uint64_t serial);
uint32_t GetCbvUavSrvHeapOffset() const;
uint32_t GetSamplerHeapOffset() const;
uint64_t GetHeapSerial() const;
private: private:
Device* mDevice; Device* mDevice;
uint32_t mCbvUavSrvHeapOffset; uint32_t mCbvUavSrvHeapOffset;
uint32_t mSamplerHeapOffset; uint32_t mSamplerHeapOffset;
uint32_t mCbvUavSrvCount = 0; uint32_t mCbvUavSrvCount = 0;
uint32_t mSamplerCount = 0; uint32_t mSamplerCount = 0;
uint64_t mHeapSerial = 0; uint64_t mHeapSerial = 0;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_BINDGROUPD3D12_H_ #endif // BACKEND_D3D12_BINDGROUPD3D12_H_

View File

@ -14,15 +14,13 @@
#include "backend/d3d12/BindGroupLayoutD3D12.h" #include "backend/d3d12/BindGroupLayoutD3D12.h"
#include "common/BitSetIterator.h"
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
#include "common/BitSetIterator.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
BindGroupLayout::BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder) BindGroupLayout::BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder)
: BindGroupLayoutBase(builder), mDevice(device), mDescriptorCounts {} { : BindGroupLayoutBase(builder), mDevice(device), mDescriptorCounts{} {
const auto& groupInfo = GetBindingInfo(); const auto& groupInfo = GetBindingInfo();
for (uint32_t binding : IterateBitSet(groupInfo.mask)) { for (uint32_t binding : IterateBitSet(groupInfo.mask)) {
@ -42,7 +40,8 @@ namespace d3d12 {
} }
} }
auto SetDescriptorRange = [&](uint32_t index, uint32_t count, D3D12_DESCRIPTOR_RANGE_TYPE type) -> bool { auto SetDescriptorRange = [&](uint32_t index, uint32_t count,
D3D12_DESCRIPTOR_RANGE_TYPE type) -> bool {
if (count == 0) { if (count == 0) {
return false; return false;
} }
@ -52,7 +51,8 @@ namespace d3d12 {
range.NumDescriptors = count; range.NumDescriptors = count;
range.RegisterSpace = 0; range.RegisterSpace = 0;
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
// These ranges will be copied and range.BaseShaderRegister will be set in d3d12::PipelineLayout to account for bind group register offsets // These ranges will be copied and range.BaseShaderRegister will be set in
// d3d12::PipelineLayout to account for bind group register offsets
return true; return true;
}; };
@ -60,23 +60,27 @@ namespace d3d12 {
// Ranges 0-2 contain the CBV, UAV, and SRV ranges, if they exist, tightly packed // Ranges 0-2 contain the CBV, UAV, and SRV ranges, if they exist, tightly packed
// Range 3 contains the Sampler range, if there is one // Range 3 contains the Sampler range, if there is one
if (SetDescriptorRange(rangeIndex, mDescriptorCounts[CBV], D3D12_DESCRIPTOR_RANGE_TYPE_CBV)) { if (SetDescriptorRange(rangeIndex, mDescriptorCounts[CBV],
D3D12_DESCRIPTOR_RANGE_TYPE_CBV)) {
rangeIndex++; rangeIndex++;
} }
if (SetDescriptorRange(rangeIndex, mDescriptorCounts[UAV], D3D12_DESCRIPTOR_RANGE_TYPE_UAV)) { if (SetDescriptorRange(rangeIndex, mDescriptorCounts[UAV],
D3D12_DESCRIPTOR_RANGE_TYPE_UAV)) {
rangeIndex++; rangeIndex++;
} }
if (SetDescriptorRange(rangeIndex, mDescriptorCounts[SRV], D3D12_DESCRIPTOR_RANGE_TYPE_SRV)) { if (SetDescriptorRange(rangeIndex, mDescriptorCounts[SRV],
D3D12_DESCRIPTOR_RANGE_TYPE_SRV)) {
rangeIndex++; rangeIndex++;
} }
SetDescriptorRange(Sampler, mDescriptorCounts[Sampler], D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER); SetDescriptorRange(Sampler, mDescriptorCounts[Sampler],
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER);
// descriptors ranges are offset by the offset + size of the previous range // descriptors ranges are offset by the offset + size of the previous range
std::array<uint32_t, DescriptorType::Count> descriptorOffsets; std::array<uint32_t, DescriptorType::Count> descriptorOffsets;
descriptorOffsets[CBV] = 0; descriptorOffsets[CBV] = 0;
descriptorOffsets[UAV] = descriptorOffsets[CBV] + mDescriptorCounts[CBV]; descriptorOffsets[UAV] = descriptorOffsets[CBV] + mDescriptorCounts[CBV];
descriptorOffsets[SRV] = descriptorOffsets[UAV] + mDescriptorCounts[UAV]; descriptorOffsets[SRV] = descriptorOffsets[UAV] + mDescriptorCounts[UAV];
descriptorOffsets[Sampler] = 0; // samplers are in a different heap descriptorOffsets[Sampler] = 0; // samplers are in a different heap
for (uint32_t binding : IterateBitSet(groupInfo.mask)) { for (uint32_t binding : IterateBitSet(groupInfo.mask)) {
switch (groupInfo.types[binding]) { switch (groupInfo.types[binding]) {
@ -101,11 +105,9 @@ namespace d3d12 {
} }
uint32_t BindGroupLayout::GetCbvUavSrvDescriptorTableSize() const { uint32_t BindGroupLayout::GetCbvUavSrvDescriptorTableSize() const {
return ( return (static_cast<uint32_t>(mDescriptorCounts[CBV] > 0) +
static_cast<uint32_t>(mDescriptorCounts[CBV] > 0) + static_cast<uint32_t>(mDescriptorCounts[UAV] > 0) +
static_cast<uint32_t>(mDescriptorCounts[UAV] > 0) + static_cast<uint32_t>(mDescriptorCounts[SRV] > 0));
static_cast<uint32_t>(mDescriptorCounts[SRV] > 0)
);
} }
uint32_t BindGroupLayout::GetSamplerDescriptorTableSize() const { uint32_t BindGroupLayout::GetSamplerDescriptorTableSize() const {
@ -128,5 +130,4 @@ namespace d3d12 {
return &mRanges[Sampler]; return &mRanges[Sampler];
} }
} }} // namespace backend::d3d12
}

View File

@ -19,39 +19,37 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class BindGroupLayout : public BindGroupLayoutBase { class BindGroupLayout : public BindGroupLayoutBase {
public: public:
BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder); BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder);
enum DescriptorType { enum DescriptorType {
CBV, CBV,
UAV, UAV,
SRV, SRV,
Sampler, Sampler,
Count, Count,
}; };
const std::array<uint32_t, kMaxBindingsPerGroup>& GetBindingOffsets() const; const std::array<uint32_t, kMaxBindingsPerGroup>& GetBindingOffsets() const;
uint32_t GetCbvUavSrvDescriptorTableSize() const; uint32_t GetCbvUavSrvDescriptorTableSize() const;
uint32_t GetSamplerDescriptorTableSize() const; uint32_t GetSamplerDescriptorTableSize() const;
uint32_t GetCbvUavSrvDescriptorCount() const; uint32_t GetCbvUavSrvDescriptorCount() const;
uint32_t GetSamplerDescriptorCount() const; uint32_t GetSamplerDescriptorCount() const;
const D3D12_DESCRIPTOR_RANGE* GetCbvUavSrvDescriptorRanges() const; const D3D12_DESCRIPTOR_RANGE* GetCbvUavSrvDescriptorRanges() const;
const D3D12_DESCRIPTOR_RANGE* GetSamplerDescriptorRanges() const; const D3D12_DESCRIPTOR_RANGE* GetSamplerDescriptorRanges() const;
private: private:
Device* mDevice; Device* mDevice;
std::array<uint32_t, kMaxBindingsPerGroup> mBindingOffsets; std::array<uint32_t, kMaxBindingsPerGroup> mBindingOffsets;
std::array<uint32_t, DescriptorType::Count> mDescriptorCounts; std::array<uint32_t, DescriptorType::Count> mDescriptorCounts;
D3D12_DESCRIPTOR_RANGE mRanges[DescriptorType::Count]; D3D12_DESCRIPTOR_RANGE mRanges[DescriptorType::Count];
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_BINDGROUPLAYOUTD3D12_H_ #endif // BACKEND_D3D12_BINDGROUPLAYOUTD3D12_H_

View File

@ -17,12 +17,11 @@
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
#include "common/Assert.h" #include "common/Assert.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
namespace { namespace {
D3D12_BLEND D3D12Blend(nxt::BlendFactor factor) { D3D12_BLEND D3D12Blend(nxt::BlendFactor factor) {
switch(factor) { switch (factor) {
case nxt::BlendFactor::Zero: case nxt::BlendFactor::Zero:
return D3D12_BLEND_ZERO; return D3D12_BLEND_ZERO;
case nxt::BlendFactor::One: case nxt::BlendFactor::One:
@ -55,7 +54,7 @@ namespace d3d12 {
} }
D3D12_BLEND_OP D3D12BlendOperation(nxt::BlendOperation operation) { D3D12_BLEND_OP D3D12BlendOperation(nxt::BlendOperation operation) {
switch(operation) { switch (operation) {
case nxt::BlendOperation::Add: case nxt::BlendOperation::Add:
return D3D12_BLEND_OP_ADD; return D3D12_BLEND_OP_ADD;
case nxt::BlendOperation::Subtract: case nxt::BlendOperation::Subtract:
@ -72,13 +71,21 @@ namespace d3d12 {
} }
uint8_t D3D12RenderTargetWriteMask(nxt::ColorWriteMask colorWriteMask) { uint8_t D3D12RenderTargetWriteMask(nxt::ColorWriteMask colorWriteMask) {
static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(nxt::ColorWriteMask::Red) == D3D12_COLOR_WRITE_ENABLE_RED, "ColorWriteMask values must match"); static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(nxt::ColorWriteMask::Red) ==
static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(nxt::ColorWriteMask::Green) == D3D12_COLOR_WRITE_ENABLE_GREEN, "ColorWriteMask values must match"); D3D12_COLOR_WRITE_ENABLE_RED,
static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(nxt::ColorWriteMask::Blue) == D3D12_COLOR_WRITE_ENABLE_BLUE, "ColorWriteMask values must match"); "ColorWriteMask values must match");
static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(nxt::ColorWriteMask::Alpha) == D3D12_COLOR_WRITE_ENABLE_ALPHA, "ColorWriteMask values must match"); static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(nxt::ColorWriteMask::Green) ==
D3D12_COLOR_WRITE_ENABLE_GREEN,
"ColorWriteMask values must match");
static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(nxt::ColorWriteMask::Blue) ==
D3D12_COLOR_WRITE_ENABLE_BLUE,
"ColorWriteMask values must match");
static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(nxt::ColorWriteMask::Alpha) ==
D3D12_COLOR_WRITE_ENABLE_ALPHA,
"ColorWriteMask values must match");
return static_cast<uint8_t>(colorWriteMask); return static_cast<uint8_t>(colorWriteMask);
} }
} } // namespace
BlendState::BlendState(BlendStateBuilder* builder) : BlendStateBase(builder) { BlendState::BlendState(BlendStateBuilder* builder) : BlendStateBase(builder) {
auto& info = GetBlendInfo(); auto& info = GetBlendInfo();
@ -98,5 +105,4 @@ namespace d3d12 {
return mBlendDesc; return mBlendDesc;
} }
} }} // namespace backend::d3d12
}

View File

@ -19,20 +19,18 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class BlendState : public BlendStateBase { class BlendState : public BlendStateBase {
public: public:
BlendState(BlendStateBuilder* builder); BlendState(BlendStateBuilder* builder);
const D3D12_RENDER_TARGET_BLEND_DESC& GetD3D12BlendDesc() const; const D3D12_RENDER_TARGET_BLEND_DESC& GetD3D12BlendDesc() const;
private: private:
D3D12_RENDER_TARGET_BLEND_DESC mBlendDesc; D3D12_RENDER_TARGET_BLEND_DESC mBlendDesc;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_BLENDSTATED3D12_H_ #endif // BACKEND_D3D12_BLENDSTATED3D12_H_

View File

@ -21,8 +21,7 @@
#include "common/Constants.h" #include "common/Constants.h"
#include "common/Math.h" #include "common/Math.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
namespace { namespace {
D3D12_RESOURCE_FLAGS D3D12ResourceFlags(nxt::BufferUsageBit usage) { D3D12_RESOURCE_FLAGS D3D12ResourceFlags(nxt::BufferUsageBit usage) {
@ -66,11 +65,9 @@ namespace d3d12 {
return D3D12_HEAP_TYPE_DEFAULT; return D3D12_HEAP_TYPE_DEFAULT;
} }
} }
} } // namespace
Buffer::Buffer(Device* device, BufferBuilder* builder)
: BufferBase(builder), mDevice(device) {
Buffer::Buffer(Device* device, BufferBuilder* builder) : BufferBase(builder), mDevice(device) {
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;
@ -87,17 +84,20 @@ namespace d3d12 {
auto heapType = D3D12HeapType(GetAllowedUsage()); auto heapType = D3D12HeapType(GetAllowedUsage());
auto bufferUsage = D3D12BufferUsage(GetUsage()); auto bufferUsage = D3D12BufferUsage(GetUsage());
// D3D12 requires buffers on the READBACK heap to have the D3D12_RESOURCE_STATE_COPY_DEST state // D3D12 requires buffers on the READBACK heap to have the D3D12_RESOURCE_STATE_COPY_DEST
// state
if (heapType == D3D12_HEAP_TYPE_READBACK) { if (heapType == D3D12_HEAP_TYPE_READBACK) {
bufferUsage |= D3D12_RESOURCE_STATE_COPY_DEST; bufferUsage |= D3D12_RESOURCE_STATE_COPY_DEST;
} }
// D3D12 requires buffers on the UPLOAD heap to have the D3D12_RESOURCE_STATE_GENERIC_READ state // D3D12 requires buffers on the UPLOAD heap to have the D3D12_RESOURCE_STATE_GENERIC_READ
// state
if (heapType == D3D12_HEAP_TYPE_UPLOAD) { if (heapType == D3D12_HEAP_TYPE_UPLOAD) {
bufferUsage |= D3D12_RESOURCE_STATE_GENERIC_READ; bufferUsage |= D3D12_RESOURCE_STATE_GENERIC_READ;
} }
mResource = device->GetResourceAllocator()->Allocate(heapType, resourceDescriptor, bufferUsage); mResource =
device->GetResourceAllocator()->Allocate(heapType, resourceDescriptor, bufferUsage);
} }
Buffer::~Buffer() { Buffer::~Buffer() {
@ -113,10 +113,13 @@ namespace d3d12 {
return mResource; return mResource;
} }
bool Buffer::GetResourceTransitionBarrier(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier) { bool Buffer::GetResourceTransitionBarrier(nxt::BufferUsageBit currentUsage,
nxt::BufferUsageBit targetUsage,
D3D12_RESOURCE_BARRIER* barrier) {
if (GetAllowedUsage() & (nxt::BufferUsageBit::MapRead | nxt::BufferUsageBit::MapWrite)) { if (GetAllowedUsage() & (nxt::BufferUsageBit::MapRead | nxt::BufferUsageBit::MapWrite)) {
// Transitions are never needed for mapped buffers because they are created with and always need the Transfer(Dst|Src) state. // Transitions are never needed for mapped buffers because they are created with and
// Mapped buffers cannot have states outside of (MapRead|TransferDst) and (MapWrite|TransferSrc) // always need the Transfer(Dst|Src) state. Mapped buffers cannot have states outside of
// (MapRead|TransferDst) and (MapWrite|TransferSrc)
return false; return false;
} }
@ -146,11 +149,12 @@ namespace d3d12 {
} }
void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) { void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) {
mDevice->GetResourceUploader()->BufferSubData(mResource, start * sizeof(uint32_t), count * sizeof(uint32_t), data); mDevice->GetResourceUploader()->BufferSubData(mResource, start * sizeof(uint32_t),
count * sizeof(uint32_t), data);
} }
void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) { void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) {
D3D12_RANGE readRange = { start, start + count }; D3D12_RANGE readRange = {start, start + count};
char* data = nullptr; char* data = nullptr;
ASSERT_SUCCESS(mResource->Map(0, &readRange, reinterpret_cast<void**>(&data))); ASSERT_SUCCESS(mResource->Map(0, &readRange, reinterpret_cast<void**>(&data)));
@ -159,22 +163,22 @@ namespace d3d12 {
} }
void Buffer::UnmapImpl() { void Buffer::UnmapImpl() {
// TODO(enga@google.com): When MapWrite is implemented, this should state the range that was modified // TODO(enga@google.com): When MapWrite is implemented, this should state the range that was
// modified
D3D12_RANGE writeRange = {}; D3D12_RANGE writeRange = {};
mResource->Unmap(0, &writeRange); mResource->Unmap(0, &writeRange);
mDevice->GetResourceAllocator()->Release(mResource); mDevice->GetResourceAllocator()->Release(mResource);
} }
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) { void Buffer::TransitionUsageImpl(nxt::BufferUsageBit currentUsage,
nxt::BufferUsageBit targetUsage) {
D3D12_RESOURCE_BARRIER barrier; D3D12_RESOURCE_BARRIER barrier;
if (GetResourceTransitionBarrier(currentUsage, targetUsage, &barrier)) { if (GetResourceTransitionBarrier(currentUsage, targetUsage, &barrier)) {
mDevice->GetPendingCommandList()->ResourceBarrier(1, &barrier); mDevice->GetPendingCommandList()->ResourceBarrier(1, &barrier);
} }
} }
BufferView::BufferView(BufferViewBuilder* builder) BufferView::BufferView(BufferViewBuilder* builder) : BufferViewBase(builder) {
: BufferViewBase(builder) {
mCbvDesc.BufferLocation = ToBackend(GetBuffer())->GetVA() + GetOffset(); mCbvDesc.BufferLocation = ToBackend(GetBuffer())->GetVA() + GetOffset();
mCbvDesc.SizeInBytes = GetD3D12Size(); mCbvDesc.SizeInBytes = GetD3D12Size();
@ -200,8 +204,7 @@ namespace d3d12 {
return mUavDesc; return mUavDesc;
} }
MapReadRequestTracker::MapReadRequestTracker(Device* device) MapReadRequestTracker::MapReadRequestTracker(Device* device) : mDevice(device) {
: mDevice(device) {
} }
MapReadRequestTracker::~MapReadRequestTracker() { MapReadRequestTracker::~MapReadRequestTracker() {
@ -224,5 +227,4 @@ namespace d3d12 {
mInflightRequests.ClearUpTo(finishedSerial); mInflightRequests.ClearUpTo(finishedSerial);
} }
} }} // namespace backend::d3d12
}

View File

@ -20,67 +20,67 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class Buffer : public BufferBase { class Buffer : public BufferBase {
public: public:
Buffer(Device* device, BufferBuilder* builder); Buffer(Device* device, BufferBuilder* builder);
~Buffer(); ~Buffer();
uint32_t GetD3D12Size() const; 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,
void OnMapReadCommandSerialFinished(uint32_t mapSerial, const void* data); nxt::BufferUsageBit targetUsage,
D3D12_RESOURCE_BARRIER* barrier);
void OnMapReadCommandSerialFinished(uint32_t mapSerial, const void* data);
private: private:
Device* mDevice; Device* mDevice;
ComPtr<ID3D12Resource> mResource; ComPtr<ID3D12Resource> mResource;
// NXT API
void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override;
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
void UnmapImpl() override;
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) override;
// NXT API
void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override;
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
void UnmapImpl() override;
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage,
nxt::BufferUsageBit targetUsage) override;
}; };
class BufferView : public BufferViewBase { class BufferView : public BufferViewBase {
public: public:
BufferView(BufferViewBuilder* builder); BufferView(BufferViewBuilder* builder);
uint32_t GetD3D12Size() const; uint32_t GetD3D12Size() const;
const D3D12_CONSTANT_BUFFER_VIEW_DESC& GetCBVDescriptor() const; const D3D12_CONSTANT_BUFFER_VIEW_DESC& GetCBVDescriptor() const;
const D3D12_UNORDERED_ACCESS_VIEW_DESC& GetUAVDescriptor() const; const D3D12_UNORDERED_ACCESS_VIEW_DESC& GetUAVDescriptor() const;
private: private:
D3D12_CONSTANT_BUFFER_VIEW_DESC mCbvDesc; D3D12_CONSTANT_BUFFER_VIEW_DESC mCbvDesc;
D3D12_UNORDERED_ACCESS_VIEW_DESC mUavDesc; D3D12_UNORDERED_ACCESS_VIEW_DESC mUavDesc;
}; };
class MapReadRequestTracker { class MapReadRequestTracker {
public: public:
MapReadRequestTracker(Device* device); MapReadRequestTracker(Device* device);
~MapReadRequestTracker(); ~MapReadRequestTracker();
void Track(Buffer* buffer, uint32_t mapSerial, const void* data); void Track(Buffer* buffer, uint32_t mapSerial, const void* data);
void Tick(Serial finishedSerial); void Tick(Serial finishedSerial);
private: private:
Device* mDevice; Device* mDevice;
struct Request { struct Request {
Ref<Buffer> buffer; Ref<Buffer> buffer;
uint32_t mapSerial; uint32_t mapSerial;
const void* data; const void* data;
}; };
SerialQueue<Request> mInflightRequests; SerialQueue<Request> mInflightRequests;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_BUFFERD3D12_H_ #endif // BACKEND_D3D12_BUFFERD3D12_H_

View File

@ -19,10 +19,10 @@
#include "common/Assert.h" #include "common/Assert.h"
#include "common/BitSetIterator.h" #include "common/BitSetIterator.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
CommandAllocatorManager::CommandAllocatorManager(Device* device) : device(device), mAllocatorCount(0) { CommandAllocatorManager::CommandAllocatorManager(Device* device)
: device(device), mAllocatorCount(0) {
mFreeAllocators.set(); mFreeAllocators.set();
} }
@ -42,14 +42,17 @@ namespace d3d12 {
if (firstFreeIndex >= mAllocatorCount) { if (firstFreeIndex >= mAllocatorCount) {
ASSERT(firstFreeIndex == mAllocatorCount); ASSERT(firstFreeIndex == mAllocatorCount);
mAllocatorCount++; mAllocatorCount++;
ASSERT_SUCCESS(device->GetD3D12Device()->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCommandAllocators[firstFreeIndex]))); ASSERT_SUCCESS(device->GetD3D12Device()->CreateCommandAllocator(
D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCommandAllocators[firstFreeIndex])));
} }
// Mark the command allocator as used // Mark the command allocator as used
mFreeAllocators.reset(firstFreeIndex); mFreeAllocators.reset(firstFreeIndex);
// Enqueue the command allocator. It will be scheduled for reset after the next ExecuteCommandLists // Enqueue the command allocator. It will be scheduled for reset after the next
mInFlightCommandAllocators.Enqueue({mCommandAllocators[firstFreeIndex], firstFreeIndex}, device->GetSerial()); // ExecuteCommandLists
mInFlightCommandAllocators.Enqueue({mCommandAllocators[firstFreeIndex], firstFreeIndex},
device->GetSerial());
return mCommandAllocators[firstFreeIndex]; return mCommandAllocators[firstFreeIndex];
} }
@ -63,5 +66,4 @@ namespace d3d12 {
mInFlightCommandAllocators.ClearUpTo(lastCompletedSerial); mInFlightCommandAllocators.ClearUpTo(lastCompletedSerial);
} }
} }} // namespace backend::d3d12
}

View File

@ -21,38 +21,36 @@
#include <bitset> #include <bitset>
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class CommandAllocatorManager { class CommandAllocatorManager {
public: public:
CommandAllocatorManager(Device* device); CommandAllocatorManager(Device* device);
// A CommandAllocator that is reserved must be used on the next ExecuteCommandLists // A CommandAllocator that is reserved must be used on the next ExecuteCommandLists
// otherwise its commands may be reset before execution has completed on the GPU // otherwise its commands may be reset before execution has completed on the GPU
ComPtr<ID3D12CommandAllocator> ReserveCommandAllocator(); ComPtr<ID3D12CommandAllocator> ReserveCommandAllocator();
void Tick(uint64_t lastCompletedSerial); void Tick(uint64_t lastCompletedSerial);
private: private:
Device* device; Device* device;
// This must be at least 2 because the Device and Queue use separate command allocators // This must be at least 2 because the Device and Queue use separate command allocators
static constexpr unsigned int kMaxCommandAllocators = 32; static constexpr unsigned int kMaxCommandAllocators = 32;
unsigned int mAllocatorCount; unsigned int mAllocatorCount;
struct IndexedCommandAllocator { struct IndexedCommandAllocator {
ComPtr<ID3D12CommandAllocator> commandAllocator; ComPtr<ID3D12CommandAllocator> commandAllocator;
unsigned int index; unsigned int index;
}; };
ComPtr<ID3D12CommandAllocator> mCommandAllocators[kMaxCommandAllocators]; ComPtr<ID3D12CommandAllocator> mCommandAllocators[kMaxCommandAllocators];
std::bitset<kMaxCommandAllocators> mFreeAllocators; std::bitset<kMaxCommandAllocators> mFreeAllocators;
SerialQueue<IndexedCommandAllocator> mInFlightCommandAllocators; SerialQueue<IndexedCommandAllocator> mInFlightCommandAllocators;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_COMMANDALLOCATORMANAGER_H_ #endif // BACKEND_D3D12_COMMANDALLOCATORMANAGER_H_

View File

@ -15,11 +15,11 @@
#include "backend/d3d12/CommandBufferD3D12.h" #include "backend/d3d12/CommandBufferD3D12.h"
#include "backend/Commands.h" #include "backend/Commands.h"
#include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/BindGroupD3D12.h" #include "backend/d3d12/BindGroupD3D12.h"
#include "backend/d3d12/BindGroupLayoutD3D12.h" #include "backend/d3d12/BindGroupLayoutD3D12.h"
#include "backend/d3d12/BufferD3D12.h" #include "backend/d3d12/BufferD3D12.h"
#include "backend/d3d12/ComputePipelineD3D12.h" #include "backend/d3d12/ComputePipelineD3D12.h"
#include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/DescriptorHeapAllocator.h" #include "backend/d3d12/DescriptorHeapAllocator.h"
#include "backend/d3d12/FramebufferD3D12.h" #include "backend/d3d12/FramebufferD3D12.h"
#include "backend/d3d12/InputStateD3D12.h" #include "backend/d3d12/InputStateD3D12.h"
@ -31,8 +31,7 @@
#include "backend/d3d12/TextureD3D12.h" #include "backend/d3d12/TextureD3D12.h"
#include "common/Assert.h" #include "common/Assert.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
namespace { namespace {
DXGI_FORMAT DXGIIndexFormat(nxt::IndexFormat format) { DXGI_FORMAT DXGIIndexFormat(nxt::IndexFormat format) {
@ -69,10 +68,13 @@ namespace d3d12 {
if (bindGroups[index] != group) { if (bindGroups[index] != group) {
bindGroups[index] = group; bindGroups[index] = group;
// Descriptors don't need to be recorded if they have already been recorded in the heap. Indices are only updated when descriptors are recorded // Descriptors don't need to be recorded if they have already been recorded in
// the heap. Indices are only updated when descriptors are recorded
const uint64_t serial = device->GetSerial(); const uint64_t serial = device->GetSerial();
if (group->GetHeapSerial() != serial) { if (group->GetHeapSerial() != serial) {
group->RecordDescriptors(cbvSrvUavCPUDescriptorHeap, &cbvSrvUavDescriptorIndex, samplerCPUDescriptorHeap, &samplerDescriptorIndex, serial); group->RecordDescriptors(
cbvSrvUavCPUDescriptorHeap, &cbvSrvUavDescriptorIndex,
samplerCPUDescriptorHeap, &samplerDescriptorIndex, serial);
} }
} }
} }
@ -88,37 +90,54 @@ namespace d3d12 {
} }
} }
void SetBindGroup(ComPtr<ID3D12GraphicsCommandList> commandList, PipelineLayout* pipelineLayout, BindGroup* group, void SetBindGroup(ComPtr<ID3D12GraphicsCommandList> commandList,
uint32_t index, bool force = false) { PipelineLayout* pipelineLayout,
BindGroup* group,
uint32_t index,
bool force = false) {
if (bindGroups[index] != group || force) { if (bindGroups[index] != group || force) {
bindGroups[index] = group; bindGroups[index] = group;
uint32_t cbvUavSrvCount = ToBackend(group->GetLayout())->GetCbvUavSrvDescriptorCount(); uint32_t cbvUavSrvCount =
uint32_t samplerCount = ToBackend(group->GetLayout())->GetSamplerDescriptorCount(); ToBackend(group->GetLayout())->GetCbvUavSrvDescriptorCount();
uint32_t samplerCount =
ToBackend(group->GetLayout())->GetSamplerDescriptorCount();
if (cbvUavSrvCount > 0) { if (cbvUavSrvCount > 0) {
uint32_t parameterIndex = pipelineLayout->GetCbvUavSrvRootParameterIndex(index); uint32_t parameterIndex =
pipelineLayout->GetCbvUavSrvRootParameterIndex(index);
if (inCompute) { if (inCompute) {
commandList->SetComputeRootDescriptorTable(parameterIndex, cbvSrvUavGPUDescriptorHeap.GetGPUHandle(group->GetCbvUavSrvHeapOffset())); commandList->SetComputeRootDescriptorTable(
parameterIndex, cbvSrvUavGPUDescriptorHeap.GetGPUHandle(
group->GetCbvUavSrvHeapOffset()));
} else { } else {
commandList->SetGraphicsRootDescriptorTable(parameterIndex, cbvSrvUavGPUDescriptorHeap.GetGPUHandle(group->GetCbvUavSrvHeapOffset())); commandList->SetGraphicsRootDescriptorTable(
parameterIndex, cbvSrvUavGPUDescriptorHeap.GetGPUHandle(
group->GetCbvUavSrvHeapOffset()));
} }
} }
if (samplerCount > 0) { if (samplerCount > 0) {
uint32_t parameterIndex = pipelineLayout->GetSamplerRootParameterIndex(index); uint32_t parameterIndex =
pipelineLayout->GetSamplerRootParameterIndex(index);
if (inCompute) { if (inCompute) {
commandList->SetComputeRootDescriptorTable(parameterIndex, samplerGPUDescriptorHeap.GetGPUHandle(group->GetSamplerHeapOffset())); commandList->SetComputeRootDescriptorTable(
parameterIndex, samplerGPUDescriptorHeap.GetGPUHandle(
group->GetSamplerHeapOffset()));
} else { } else {
commandList->SetGraphicsRootDescriptorTable(parameterIndex, samplerGPUDescriptorHeap.GetGPUHandle(group->GetSamplerHeapOffset())); commandList->SetGraphicsRootDescriptorTable(
parameterIndex, samplerGPUDescriptorHeap.GetGPUHandle(
group->GetSamplerHeapOffset()));
} }
} }
} }
} }
void SetInheritedBindGroups(ComPtr<ID3D12GraphicsCommandList> commandList, PipelineLayout* oldLayout, PipelineLayout* newLayout) { void SetInheritedBindGroups(ComPtr<ID3D12GraphicsCommandList> commandList,
PipelineLayout* oldLayout,
PipelineLayout* newLayout) {
if (oldLayout == nullptr) { if (oldLayout == nullptr) {
return; return;
} }
@ -136,13 +155,17 @@ namespace d3d12 {
} }
}; };
void AllocateAndSetDescriptorHeaps(Device* device, BindGroupStateTracker* bindingTracker, CommandIterator* commands) { void AllocateAndSetDescriptorHeaps(Device* device,
BindGroupStateTracker* bindingTracker,
CommandIterator* commands) {
auto* descriptorHeapAllocator = device->GetDescriptorHeapAllocator(); auto* descriptorHeapAllocator = device->GetDescriptorHeapAllocator();
// TODO(enga@google.com): This currently allocates CPU heaps of arbitrarily chosen sizes // TODO(enga@google.com): This currently allocates CPU heaps of arbitrarily chosen sizes
// This will not work if there are too many descriptors // This will not work if there are too many descriptors
bindingTracker->cbvSrvUavCPUDescriptorHeap = descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 8192); bindingTracker->cbvSrvUavCPUDescriptorHeap = descriptorHeapAllocator->AllocateCPUHeap(
bindingTracker->samplerCPUDescriptorHeap = descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 2048); D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 8192);
bindingTracker->samplerCPUDescriptorHeap =
descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 2048);
{ {
Command type; Command type;
@ -150,31 +173,27 @@ namespace d3d12 {
while (commands->NextCommandId(&type)) { while (commands->NextCommandId(&type)) {
switch (type) { switch (type) {
case Command::SetComputePipeline: case Command::SetComputePipeline: {
{ SetComputePipelineCmd* cmd =
SetComputePipelineCmd* cmd = commands->NextCommand<SetComputePipelineCmd>(); commands->NextCommand<SetComputePipelineCmd>();
PipelineLayout* layout = ToBackend(cmd->pipeline->GetLayout()); PipelineLayout* layout = ToBackend(cmd->pipeline->GetLayout());
bindingTracker->TrackInheritedGroups(lastLayout, layout); bindingTracker->TrackInheritedGroups(lastLayout, layout);
lastLayout = layout; lastLayout = layout;
} } break;
break;
case Command::SetRenderPipeline: case Command::SetRenderPipeline: {
{ SetRenderPipelineCmd* cmd =
SetRenderPipelineCmd* cmd = commands->NextCommand<SetRenderPipelineCmd>(); commands->NextCommand<SetRenderPipelineCmd>();
PipelineLayout* layout = ToBackend(cmd->pipeline->GetLayout()); PipelineLayout* layout = ToBackend(cmd->pipeline->GetLayout());
bindingTracker->TrackInheritedGroups(lastLayout, layout); bindingTracker->TrackInheritedGroups(lastLayout, layout);
lastLayout = layout; lastLayout = layout;
} } break;
break;
case Command::SetBindGroup: case Command::SetBindGroup: {
{
SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>(); SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
BindGroup* group = ToBackend(cmd->group.Get()); BindGroup* group = ToBackend(cmd->group.Get());
bindingTracker->TrackSetBindGroup(group, cmd->index); bindingTracker->TrackSetBindGroup(group, cmd->index);
} } break;
break;
default: default:
SkipCommand(commands, type); SkipCommand(commands, type);
} }
@ -184,8 +203,12 @@ namespace d3d12 {
} }
if (bindingTracker->cbvSrvUavDescriptorIndex > 0) { if (bindingTracker->cbvSrvUavDescriptorIndex > 0) {
// Allocate a GPU-visible heap and copy from the CPU-only heap to the GPU-visible heap // Allocate a GPU-visible heap and copy from the CPU-only heap to the GPU-visible
bindingTracker->cbvSrvUavGPUDescriptorHeap = descriptorHeapAllocator->AllocateGPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, bindingTracker->cbvSrvUavDescriptorIndex); // heap
bindingTracker->cbvSrvUavGPUDescriptorHeap =
descriptorHeapAllocator->AllocateGPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
bindingTracker->cbvSrvUavDescriptorIndex);
device->GetD3D12Device()->CopyDescriptorsSimple( device->GetD3D12Device()->CopyDescriptorsSimple(
bindingTracker->cbvSrvUavDescriptorIndex, bindingTracker->cbvSrvUavDescriptorIndex,
bindingTracker->cbvSrvUavGPUDescriptorHeap.GetCPUHandle(0), bindingTracker->cbvSrvUavGPUDescriptorHeap.GetCPUHandle(0),
@ -194,7 +217,8 @@ namespace d3d12 {
} }
if (bindingTracker->samplerDescriptorIndex > 0) { if (bindingTracker->samplerDescriptorIndex > 0) {
bindingTracker->samplerGPUDescriptorHeap = descriptorHeapAllocator->AllocateGPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, bindingTracker->samplerDescriptorIndex); bindingTracker->samplerGPUDescriptorHeap = descriptorHeapAllocator->AllocateGPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, bindingTracker->samplerDescriptorIndex);
device->GetD3D12Device()->CopyDescriptorsSimple( device->GetD3D12Device()->CopyDescriptorsSimple(
bindingTracker->samplerDescriptorIndex, bindingTracker->samplerDescriptorIndex,
bindingTracker->samplerGPUDescriptorHeap.GetCPUHandle(0), bindingTracker->samplerGPUDescriptorHeap.GetCPUHandle(0),
@ -202,7 +226,7 @@ namespace d3d12 {
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
} }
} }
} } // namespace
CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder) CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder)
: CommandBufferBase(builder), mDevice(device), mCommands(builder->AcquireCommands()) { : CommandBufferBase(builder), mDevice(device), mCommands(builder->AcquireCommands()) {
@ -217,7 +241,8 @@ namespace d3d12 {
AllocateAndSetDescriptorHeaps(mDevice, &bindingTracker, &mCommands); AllocateAndSetDescriptorHeaps(mDevice, &bindingTracker, &mCommands);
bindingTracker.Reset(); bindingTracker.Reset();
ID3D12DescriptorHeap* descriptorHeaps[2] = { bindingTracker.cbvSrvUavGPUDescriptorHeap.Get(), bindingTracker.samplerGPUDescriptorHeap.Get() }; ID3D12DescriptorHeap* descriptorHeaps[2] = {bindingTracker.cbvSrvUavGPUDescriptorHeap.Get(),
bindingTracker.samplerGPUDescriptorHeap.Get()};
if (descriptorHeaps[0] && descriptorHeaps[1]) { if (descriptorHeaps[0] && descriptorHeaps[1]) {
commandList->SetDescriptorHeaps(2, descriptorHeaps); commandList->SetDescriptorHeaps(2, descriptorHeaps);
} else if (descriptorHeaps[0]) { } else if (descriptorHeaps[0]) {
@ -234,393 +259,352 @@ namespace d3d12 {
Framebuffer* currentFramebuffer = nullptr; Framebuffer* currentFramebuffer = nullptr;
uint32_t currentSubpass = 0; uint32_t currentSubpass = 0;
while(mCommands.NextCommandId(&type)) { while (mCommands.NextCommandId(&type)) {
switch (type) { switch (type) {
case Command::BeginComputePass: case Command::BeginComputePass: {
{ mCommands.NextCommand<BeginComputePassCmd>();
mCommands.NextCommand<BeginComputePassCmd>(); bindingTracker.SetInComputePass(true);
bindingTracker.SetInComputePass(true); } break;
case Command::BeginRenderPass: {
BeginRenderPassCmd* beginRenderPassCmd =
mCommands.NextCommand<BeginRenderPassCmd>();
currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get());
currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get());
currentSubpass = 0;
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);
} break;
case Command::BeginRenderSubpass: {
mCommands.NextCommand<BeginRenderSubpassCmd>();
const auto& subpass = currentRenderPass->GetSubpassInfo(currentSubpass);
Framebuffer::OMSetRenderTargetArgs args =
currentFramebuffer->GetSubpassOMSetRenderTargetArgs(currentSubpass);
if (args.dsv.ptr) {
commandList->OMSetRenderTargets(args.numRTVs, args.RTVs.data(), FALSE,
&args.dsv);
} else {
commandList->OMSetRenderTargets(args.numRTVs, args.RTVs.data(), FALSE,
nullptr);
} }
break;
case Command::BeginRenderPass: // Clear framebuffer attachments as needed
{
BeginRenderPassCmd* beginRenderPassCmd = mCommands.NextCommand<BeginRenderPassCmd>();
currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get());
currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get());
currentSubpass = 0;
uint32_t width = currentFramebuffer->GetWidth(); for (unsigned int location : IterateBitSet(subpass.colorAttachmentsSet)) {
uint32_t height = currentFramebuffer->GetHeight(); uint32_t attachmentSlot = subpass.colorAttachments[location];
D3D12_VIEWPORT viewport = { 0.f, 0.f, static_cast<float>(width), static_cast<float>(height), 0.f, 1.f }; const auto& attachmentInfo =
D3D12_RECT scissorRect = { 0, 0, static_cast<long>(width), static_cast<long>(height) }; currentRenderPass->GetAttachmentInfo(attachmentSlot);
commandList->RSSetViewports(1, &viewport);
commandList->RSSetScissorRects(1, &scissorRect);
}
break;
case Command::BeginRenderSubpass: Texture* texture = ToBackend(
{ currentFramebuffer->GetTextureView(attachmentSlot)->GetTexture());
mCommands.NextCommand<BeginRenderSubpassCmd>(); constexpr auto usage = nxt::TextureUsageBit::OutputAttachment;
const auto& subpass = currentRenderPass->GetSubpassInfo(currentSubpass); // It's already validated that this texture is either frozen to the correct
// usage, or not frozen.
Framebuffer::OMSetRenderTargetArgs args = currentFramebuffer->GetSubpassOMSetRenderTargetArgs(currentSubpass); if (!texture->IsFrozen()) {
if (args.dsv.ptr) { texture->TransitionUsageImpl(texture->GetUsage(), usage);
commandList->OMSetRenderTargets(args.numRTVs, args.RTVs.data(), FALSE, &args.dsv); texture->UpdateUsageInternal(usage);
} else {
commandList->OMSetRenderTargets(args.numRTVs, args.RTVs.data(), FALSE, nullptr);
} }
// Clear framebuffer attachments as needed // Only perform load op on first use
if (attachmentInfo.firstSubpass == currentSubpass) {
for (unsigned int location : IterateBitSet(subpass.colorAttachmentsSet)) { // Load op - color
uint32_t attachmentSlot = subpass.colorAttachments[location]; if (attachmentInfo.colorLoadOp == nxt::LoadOp::Clear) {
const auto& attachmentInfo = currentRenderPass->GetAttachmentInfo(attachmentSlot); auto handle = currentFramebuffer->GetRTVDescriptor(attachmentSlot);
const auto& clear =
Texture* texture = ToBackend(currentFramebuffer->GetTextureView(attachmentSlot)->GetTexture()); currentFramebuffer->GetClearColor(attachmentSlot);
constexpr auto usage = nxt::TextureUsageBit::OutputAttachment; commandList->ClearRenderTargetView(handle, clear.color, 0, nullptr);
// It's already validated that this texture is either frozen to the correct usage, or not frozen.
if (!texture->IsFrozen()) {
texture->TransitionUsageImpl(texture->GetUsage(), usage);
texture->UpdateUsageInternal(usage);
}
// Only perform load op on first use
if (attachmentInfo.firstSubpass == currentSubpass) {
// Load op - color
if (attachmentInfo.colorLoadOp == nxt::LoadOp::Clear) {
auto handle = currentFramebuffer->GetRTVDescriptor(attachmentSlot);
const auto& clear = currentFramebuffer->GetClearColor(attachmentSlot);
commandList->ClearRenderTargetView(handle, clear.color, 0, nullptr);
}
} }
} }
}
if (subpass.depthStencilAttachmentSet) { if (subpass.depthStencilAttachmentSet) {
uint32_t attachmentSlot = subpass.depthStencilAttachment; uint32_t attachmentSlot = subpass.depthStencilAttachment;
const auto& attachmentInfo = currentRenderPass->GetAttachmentInfo(attachmentSlot); const auto& attachmentInfo =
currentRenderPass->GetAttachmentInfo(attachmentSlot);
// Only perform load op on first use // Only perform load op on first use
if (attachmentInfo.firstSubpass == currentSubpass) { if (attachmentInfo.firstSubpass == currentSubpass) {
// Load op - depth/stencil // Load op - depth/stencil
bool doDepthClear = TextureFormatHasDepth(attachmentInfo.format) && bool doDepthClear = TextureFormatHasDepth(attachmentInfo.format) &&
(attachmentInfo.depthLoadOp == nxt::LoadOp::Clear); (attachmentInfo.depthLoadOp == nxt::LoadOp::Clear);
bool doStencilClear = TextureFormatHasStencil(attachmentInfo.format) && bool doStencilClear =
(attachmentInfo.stencilLoadOp == nxt::LoadOp::Clear); TextureFormatHasStencil(attachmentInfo.format) &&
(attachmentInfo.stencilLoadOp == nxt::LoadOp::Clear);
D3D12_CLEAR_FLAGS clearFlags = {}; D3D12_CLEAR_FLAGS clearFlags = {};
if (doDepthClear) { if (doDepthClear) {
clearFlags |= D3D12_CLEAR_FLAG_DEPTH; clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
} }
if (doStencilClear) { if (doStencilClear) {
clearFlags |= D3D12_CLEAR_FLAG_STENCIL; clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
} }
if (clearFlags) { if (clearFlags) {
auto handle = currentFramebuffer->GetDSVDescriptor(attachmentSlot); auto handle = currentFramebuffer->GetDSVDescriptor(attachmentSlot);
const auto& clear = currentFramebuffer->GetClearDepthStencil(attachmentSlot); const auto& clear =
// TODO(kainino@chromium.org): investigate: should the NXT clear stencil type be uint8_t? currentFramebuffer->GetClearDepthStencil(attachmentSlot);
uint8_t clearStencil = static_cast<uint8_t>(clear.stencil); // TODO(kainino@chromium.org): investigate: should the NXT clear
commandList->ClearDepthStencilView(handle, clearFlags, clear.depth, clearStencil, 0, nullptr); // stencil type be uint8_t?
} uint8_t clearStencil = static_cast<uint8_t>(clear.stencil);
commandList->ClearDepthStencilView(handle, clearFlags, clear.depth,
clearStencil, 0, nullptr);
} }
} }
static constexpr std::array<float, 4> defaultBlendFactor = { 0, 0, 0, 0 };
commandList->OMSetBlendFactor(&defaultBlendFactor[0]);
} }
break;
case Command::CopyBufferToBuffer: static constexpr std::array<float, 4> defaultBlendFactor = {0, 0, 0, 0};
{ commandList->OMSetBlendFactor(&defaultBlendFactor[0]);
CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>(); } break;
auto src = ToBackend(copy->source.buffer.Get())->GetD3D12Resource();
auto dst = ToBackend(copy->destination.buffer.Get())->GetD3D12Resource(); case Command::CopyBufferToBuffer: {
commandList->CopyBufferRegion(dst.Get(), copy->destination.offset, src.Get(), copy->source.offset, copy->size); CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
auto src = ToBackend(copy->source.buffer.Get())->GetD3D12Resource();
auto dst = ToBackend(copy->destination.buffer.Get())->GetD3D12Resource();
commandList->CopyBufferRegion(dst.Get(), copy->destination.offset, src.Get(),
copy->source.offset, copy->size);
} break;
case Command::CopyBufferToTexture: {
CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
Buffer* buffer = ToBackend(copy->source.buffer.Get());
Texture* texture = ToBackend(copy->destination.texture.Get());
auto copySplit = ComputeTextureCopySplit(
copy->destination.x, copy->destination.y, copy->destination.z,
copy->destination.width, copy->destination.height, copy->destination.depth,
static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())),
copy->source.offset, copy->rowPitch);
D3D12_TEXTURE_COPY_LOCATION textureLocation;
textureLocation.pResource = texture->GetD3D12Resource();
textureLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
textureLocation.SubresourceIndex = copy->destination.level;
for (uint32_t i = 0; i < copySplit.count; ++i) {
auto& info = copySplit.copies[i];
D3D12_TEXTURE_COPY_LOCATION bufferLocation;
bufferLocation.pResource = buffer->GetD3D12Resource().Get();
bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
bufferLocation.PlacedFootprint.Offset = copySplit.offset;
bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format();
bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width;
bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height;
bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth;
bufferLocation.PlacedFootprint.Footprint.RowPitch = copy->rowPitch;
D3D12_BOX sourceRegion;
sourceRegion.left = info.bufferOffset.x;
sourceRegion.top = info.bufferOffset.y;
sourceRegion.front = info.bufferOffset.z;
sourceRegion.right = info.bufferOffset.x + info.copySize.width;
sourceRegion.bottom = info.bufferOffset.y + info.copySize.height;
sourceRegion.back = info.bufferOffset.z + info.copySize.depth;
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
info.textureOffset.y, info.textureOffset.z,
&bufferLocation, &sourceRegion);
} }
break; } break;
case Command::CopyBufferToTexture: case Command::CopyTextureToBuffer: {
{ CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>(); Texture* texture = ToBackend(copy->source.texture.Get());
Buffer* buffer = ToBackend(copy->source.buffer.Get()); Buffer* buffer = ToBackend(copy->destination.buffer.Get());
Texture* texture = ToBackend(copy->destination.texture.Get());
auto copySplit = ComputeTextureCopySplit( auto copySplit = ComputeTextureCopySplit(
copy->destination.x, copy->source.x, copy->source.y, copy->source.z, copy->source.width,
copy->destination.y, copy->source.height, copy->source.depth,
copy->destination.z, static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())),
copy->destination.width, copy->destination.offset, copy->rowPitch);
copy->destination.height,
copy->destination.depth,
static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())),
copy->source.offset,
copy->rowPitch
);
D3D12_TEXTURE_COPY_LOCATION textureLocation; D3D12_TEXTURE_COPY_LOCATION textureLocation;
textureLocation.pResource = texture->GetD3D12Resource(); textureLocation.pResource = texture->GetD3D12Resource();
textureLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; textureLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
textureLocation.SubresourceIndex = copy->destination.level; textureLocation.SubresourceIndex = copy->source.level;
for (uint32_t i = 0; i < copySplit.count; ++i) { for (uint32_t i = 0; i < copySplit.count; ++i) {
auto& info = copySplit.copies[i]; auto& info = copySplit.copies[i];
D3D12_TEXTURE_COPY_LOCATION bufferLocation; D3D12_TEXTURE_COPY_LOCATION bufferLocation;
bufferLocation.pResource = buffer->GetD3D12Resource().Get(); bufferLocation.pResource = buffer->GetD3D12Resource().Get();
bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
bufferLocation.PlacedFootprint.Offset = copySplit.offset; bufferLocation.PlacedFootprint.Offset = copySplit.offset;
bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format(); bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format();
bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width; bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width;
bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height; bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height;
bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth; bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth;
bufferLocation.PlacedFootprint.Footprint.RowPitch = copy->rowPitch; bufferLocation.PlacedFootprint.Footprint.RowPitch = copy->rowPitch;
D3D12_BOX sourceRegion; D3D12_BOX sourceRegion;
sourceRegion.left = info.bufferOffset.x; sourceRegion.left = info.textureOffset.x;
sourceRegion.top = info.bufferOffset.y; sourceRegion.top = info.textureOffset.y;
sourceRegion.front = info.bufferOffset.z; sourceRegion.front = info.textureOffset.z;
sourceRegion.right = info.bufferOffset.x + info.copySize.width; sourceRegion.right = info.textureOffset.x + info.copySize.width;
sourceRegion.bottom = info.bufferOffset.y + info.copySize.height; sourceRegion.bottom = info.textureOffset.y + info.copySize.height;
sourceRegion.back = info.bufferOffset.z + info.copySize.depth; sourceRegion.back = info.textureOffset.z + info.copySize.depth;
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x, info.textureOffset.y, info.textureOffset.z, &bufferLocation, &sourceRegion); commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
} info.bufferOffset.y, info.bufferOffset.z,
&textureLocation, &sourceRegion);
} }
break; } break;
case Command::CopyTextureToBuffer: case Command::Dispatch: {
{ DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>(); commandList->Dispatch(dispatch->x, dispatch->y, dispatch->z);
Texture* texture = ToBackend(copy->source.texture.Get()); } break;
Buffer* buffer = ToBackend(copy->destination.buffer.Get());
auto copySplit = ComputeTextureCopySplit( case Command::DrawArrays: {
copy->source.x, DrawArraysCmd* draw = mCommands.NextCommand<DrawArraysCmd>();
copy->source.y, commandList->DrawInstanced(draw->vertexCount, draw->instanceCount,
copy->source.z, draw->firstVertex, draw->firstInstance);
copy->source.width, } break;
copy->source.height,
copy->source.depth,
static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())),
copy->destination.offset,
copy->rowPitch
);
D3D12_TEXTURE_COPY_LOCATION textureLocation; case Command::DrawElements: {
textureLocation.pResource = texture->GetD3D12Resource(); DrawElementsCmd* draw = mCommands.NextCommand<DrawElementsCmd>();
textureLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
textureLocation.SubresourceIndex = copy->source.level;
for (uint32_t i = 0; i < copySplit.count; ++i) { commandList->DrawIndexedInstanced(draw->indexCount, draw->instanceCount,
auto& info = copySplit.copies[i]; draw->firstIndex, 0, draw->firstInstance);
} break;
D3D12_TEXTURE_COPY_LOCATION bufferLocation; case Command::EndComputePass: {
bufferLocation.pResource = buffer->GetD3D12Resource().Get(); mCommands.NextCommand<EndComputePassCmd>();
bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; bindingTracker.SetInComputePass(false);
bufferLocation.PlacedFootprint.Offset = copySplit.offset; } break;
bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format();
bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width;
bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height;
bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth;
bufferLocation.PlacedFootprint.Footprint.RowPitch = copy->rowPitch;
D3D12_BOX sourceRegion; case Command::EndRenderPass: {
sourceRegion.left = info.textureOffset.x; mCommands.NextCommand<EndRenderPassCmd>();
sourceRegion.top = info.textureOffset.y; } break;
sourceRegion.front = info.textureOffset.z;
sourceRegion.right = info.textureOffset.x + info.copySize.width;
sourceRegion.bottom = info.textureOffset.y + info.copySize.height;
sourceRegion.back = info.textureOffset.z + info.copySize.depth;
commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x, info.bufferOffset.y, info.bufferOffset.z, &textureLocation, &sourceRegion); case Command::EndRenderSubpass: {
} mCommands.NextCommand<EndRenderSubpassCmd>();
currentSubpass += 1;
} break;
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
ComputePipeline* pipeline = ToBackend(cmd->pipeline).Get();
PipelineLayout* layout = ToBackend(pipeline->GetLayout());
commandList->SetComputeRootSignature(layout->GetRootSignature().Get());
commandList->SetPipelineState(pipeline->GetPipelineState().Get());
// TODO(enga@google.com): Implement compute pipelines
bindingTracker.SetInheritedBindGroups(commandList, lastLayout, layout);
lastLayout = layout;
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();
PipelineLayout* layout = ToBackend(pipeline->GetLayout());
commandList->SetGraphicsRootSignature(layout->GetRootSignature().Get());
commandList->SetPipelineState(pipeline->GetPipelineState().Get());
commandList->IASetPrimitiveTopology(pipeline->GetD3D12PrimitiveTopology());
bindingTracker.SetInheritedBindGroups(commandList, lastLayout, layout);
lastRenderPipeline = pipeline;
lastLayout = layout;
} break;
case Command::SetPushConstants: {
mCommands.NextCommand<SetPushConstantsCmd>();
} break;
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
commandList->OMSetStencilRef(cmd->reference);
} break;
case Command::SetBlendColor: {
SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
ASSERT(lastRenderPipeline);
commandList->OMSetBlendFactor(static_cast<const FLOAT*>(&cmd->r));
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
BindGroup* group = ToBackend(cmd->group.Get());
bindingTracker.SetBindGroup(commandList, lastLayout, group, cmd->index);
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
Buffer* buffer = ToBackend(cmd->buffer.Get());
D3D12_INDEX_BUFFER_VIEW bufferView;
bufferView.BufferLocation = buffer->GetVA() + cmd->offset;
bufferView.SizeInBytes = buffer->GetSize() - cmd->offset;
// TODO(cwallez@chromium.org): Make index buffers lazily applied, right now
// this will break if the pipeline is changed for one with a different index
// format after SetIndexBuffer
bufferView.Format = DXGIIndexFormat(lastRenderPipeline->GetIndexFormat());
commandList->IASetIndexBuffer(&bufferView);
} break;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
auto offsets = mCommands.NextData<uint32_t>(cmd->count);
auto inputState = ToBackend(lastRenderPipeline->GetInputState());
std::array<D3D12_VERTEX_BUFFER_VIEW, kMaxVertexInputs> d3d12BufferViews;
for (uint32_t i = 0; i < cmd->count; ++i) {
auto input = inputState->GetInput(cmd->startSlot + i);
Buffer* buffer = ToBackend(buffers[i].Get());
d3d12BufferViews[i].BufferLocation = buffer->GetVA() + offsets[i];
d3d12BufferViews[i].StrideInBytes = input.stride;
d3d12BufferViews[i].SizeInBytes = buffer->GetSize() - offsets[i];
} }
break;
case Command::Dispatch: commandList->IASetVertexBuffers(cmd->startSlot, cmd->count,
{ d3d12BufferViews.data());
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>(); } break;
commandList->Dispatch(dispatch->x, dispatch->y, dispatch->z);
case Command::TransitionBufferUsage: {
TransitionBufferUsageCmd* cmd =
mCommands.NextCommand<TransitionBufferUsageCmd>();
Buffer* buffer = ToBackend(cmd->buffer.Get());
D3D12_RESOURCE_BARRIER barrier;
if (buffer->GetResourceTransitionBarrier(buffer->GetUsage(), cmd->usage,
&barrier)) {
commandList->ResourceBarrier(1, &barrier);
} }
break;
case Command::DrawArrays: buffer->UpdateUsageInternal(cmd->usage);
{ } break;
DrawArraysCmd* draw = mCommands.NextCommand<DrawArraysCmd>();
commandList->DrawInstanced( case Command::TransitionTextureUsage: {
draw->vertexCount, TransitionTextureUsageCmd* cmd =
draw->instanceCount, mCommands.NextCommand<TransitionTextureUsageCmd>();
draw->firstVertex,
draw->firstInstance Texture* texture = ToBackend(cmd->texture.Get());
);
D3D12_RESOURCE_BARRIER barrier;
if (texture->GetResourceTransitionBarrier(texture->GetUsage(), cmd->usage,
&barrier)) {
commandList->ResourceBarrier(1, &barrier);
} }
break;
case Command::DrawElements: texture->UpdateUsageInternal(cmd->usage);
{ } break;
DrawElementsCmd* draw = mCommands.NextCommand<DrawElementsCmd>();
commandList->DrawIndexedInstanced(
draw->indexCount,
draw->instanceCount,
draw->firstIndex,
0,
draw->firstInstance
);
}
break;
case Command::EndComputePass:
{
mCommands.NextCommand<EndComputePassCmd>();
bindingTracker.SetInComputePass(false);
}
break;
case Command::EndRenderPass:
{
mCommands.NextCommand<EndRenderPassCmd>();
}
break;
case Command::EndRenderSubpass:
{
mCommands.NextCommand<EndRenderSubpassCmd>();
currentSubpass += 1;
}
break;
case Command::SetComputePipeline:
{
SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
ComputePipeline* pipeline = ToBackend(cmd->pipeline).Get();
PipelineLayout* layout = ToBackend(pipeline->GetLayout());
commandList->SetComputeRootSignature(layout->GetRootSignature().Get());
commandList->SetPipelineState(pipeline->GetPipelineState().Get());
// TODO(enga@google.com): Implement compute pipelines
bindingTracker.SetInheritedBindGroups(commandList, lastLayout, layout);
lastLayout = layout;
}
break;
case Command::SetRenderPipeline:
{
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();
PipelineLayout* layout = ToBackend(pipeline->GetLayout());
commandList->SetGraphicsRootSignature(layout->GetRootSignature().Get());
commandList->SetPipelineState(pipeline->GetPipelineState().Get());
commandList->IASetPrimitiveTopology(pipeline->GetD3D12PrimitiveTopology());
bindingTracker.SetInheritedBindGroups(commandList, lastLayout, layout);
lastRenderPipeline = pipeline;
lastLayout = layout;
}
break;
case Command::SetPushConstants:
{
mCommands.NextCommand<SetPushConstantsCmd>();
}
break;
case Command::SetStencilReference:
{
SetStencilReferenceCmd *cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
commandList->OMSetStencilRef(cmd->reference);
}
break;
case Command::SetBlendColor:
{
SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
ASSERT(lastRenderPipeline);
commandList->OMSetBlendFactor(static_cast<const FLOAT*>(&cmd->r));
}
break;
case Command::SetBindGroup:
{
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
BindGroup* group = ToBackend(cmd->group.Get());
bindingTracker.SetBindGroup(commandList, lastLayout, group, cmd->index);
}
break;
case Command::SetIndexBuffer:
{
SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
Buffer* buffer = ToBackend(cmd->buffer.Get());
D3D12_INDEX_BUFFER_VIEW bufferView;
bufferView.BufferLocation = buffer->GetVA() + cmd->offset;
bufferView.SizeInBytes = buffer->GetSize() - cmd->offset;
//TODO(cwallez@chromium.org): Make index buffers lazily applied, right now
//this will break if the pipeline is changed for one with a different index
//format after SetIndexBuffer
bufferView.Format = DXGIIndexFormat(lastRenderPipeline->GetIndexFormat());
commandList->IASetIndexBuffer(&bufferView);
}
break;
case Command::SetVertexBuffers:
{
SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
auto offsets = mCommands.NextData<uint32_t>(cmd->count);
auto inputState = ToBackend(lastRenderPipeline->GetInputState());
std::array<D3D12_VERTEX_BUFFER_VIEW, kMaxVertexInputs> d3d12BufferViews;
for (uint32_t i = 0; i < cmd->count; ++i) {
auto input = inputState->GetInput(cmd->startSlot + i);
Buffer* buffer = ToBackend(buffers[i].Get());
d3d12BufferViews[i].BufferLocation = buffer->GetVA() + offsets[i];
d3d12BufferViews[i].StrideInBytes = input.stride;
d3d12BufferViews[i].SizeInBytes = buffer->GetSize() - offsets[i];
}
commandList->IASetVertexBuffers(cmd->startSlot, cmd->count, d3d12BufferViews.data());
}
break;
case Command::TransitionBufferUsage:
{
TransitionBufferUsageCmd* cmd = mCommands.NextCommand<TransitionBufferUsageCmd>();
Buffer* buffer = ToBackend(cmd->buffer.Get());
D3D12_RESOURCE_BARRIER barrier;
if (buffer->GetResourceTransitionBarrier(buffer->GetUsage(), cmd->usage, &barrier)) {
commandList->ResourceBarrier(1, &barrier);
}
buffer->UpdateUsageInternal(cmd->usage);
}
break;
case Command::TransitionTextureUsage:
{
TransitionTextureUsageCmd* cmd = mCommands.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;
} }
} }
} }
} }} // namespace backend::d3d12
}

View File

@ -20,23 +20,21 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class CommandBuffer : public CommandBufferBase { class CommandBuffer : public CommandBufferBase {
public: public:
CommandBuffer(Device* device, CommandBufferBuilder* builder); CommandBuffer(Device* device, CommandBufferBuilder* builder);
~CommandBuffer(); ~CommandBuffer();
void FillCommands(ComPtr<ID3D12GraphicsCommandList> commandList); void FillCommands(ComPtr<ID3D12GraphicsCommandList> commandList);
private: private:
Device* mDevice; Device* mDevice;
CommandIterator mCommands; CommandIterator mCommands;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_COMMANDBUFFERD3D12_H_ #endif // BACKEND_D3D12_COMMANDBUFFERD3D12_H_

View File

@ -15,14 +15,13 @@
#include "backend/d3d12/ComputePipelineD3D12.h" #include "backend/d3d12/ComputePipelineD3D12.h"
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/ShaderModuleD3D12.h"
#include "backend/d3d12/PipelineLayoutD3D12.h" #include "backend/d3d12/PipelineLayoutD3D12.h"
#include "backend/d3d12/ShaderModuleD3D12.h"
#include "common/Assert.h" #include "common/Assert.h"
#include <d3dcompiler.h> #include <d3dcompiler.h>
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
ComputePipeline::ComputePipeline(ComputePipelineBuilder* builder) ComputePipeline::ComputePipeline(ComputePipelineBuilder* builder)
: ComputePipelineBase(builder) { : ComputePipelineBase(builder) {
@ -41,19 +40,9 @@ namespace d3d12 {
ComPtr<ID3DBlob> compiledShader; ComPtr<ID3DBlob> compiledShader;
ComPtr<ID3DBlob> errors; ComPtr<ID3DBlob> errors;
if (FAILED(D3DCompile( if (FAILED(D3DCompile(hlslSource.c_str(), hlslSource.length(), nullptr, {nullptr}, nullptr,
hlslSource.c_str(), entryPoint.c_str(), "cs_5_1", compileFlags, 0, &compiledShader,
hlslSource.length(), &errors))) {
nullptr,
{ nullptr },
nullptr,
entryPoint.c_str(),
"cs_5_1",
compileFlags,
0,
&compiledShader,
&errors
))) {
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer())); printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
ASSERT(false); ASSERT(false);
} }
@ -64,12 +53,12 @@ namespace d3d12 {
descriptor.CS.BytecodeLength = compiledShader->GetBufferSize(); descriptor.CS.BytecodeLength = compiledShader->GetBufferSize();
Device* device = ToBackend(builder->GetDevice()); Device* device = ToBackend(builder->GetDevice());
device->GetD3D12Device()->CreateComputePipelineState(&descriptor, IID_PPV_ARGS(&mPipelineState)); device->GetD3D12Device()->CreateComputePipelineState(&descriptor,
IID_PPV_ARGS(&mPipelineState));
} }
ComPtr<ID3D12PipelineState> ComputePipeline::GetPipelineState() { ComPtr<ID3D12PipelineState> ComputePipeline::GetPipelineState() {
return mPipelineState; return mPipelineState;
} }
} }} // namespace backend::d3d12
}

View File

@ -19,20 +19,18 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class ComputePipeline : public ComputePipelineBase { class ComputePipeline : public ComputePipelineBase {
public: public:
ComputePipeline(ComputePipelineBuilder* builder); ComputePipeline(ComputePipelineBuilder* builder);
ComPtr<ID3D12PipelineState> GetPipelineState(); ComPtr<ID3D12PipelineState> GetPipelineState();
private: private:
ComPtr<ID3D12PipelineState> mPipelineState; ComPtr<ID3D12PipelineState> mPipelineState;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_COMPUTEPIPELINED3D12_H_ #endif // BACKEND_D3D12_COMPUTEPIPELINED3D12_H_

View File

@ -36,8 +36,7 @@
#include "backend/d3d12/TextureD3D12.h" #include "backend/d3d12/TextureD3D12.h"
#include "common/Assert.h" #include "common/Assert.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
nxtProcTable GetNonValidatingProcs(); nxtProcTable GetNonValidatingProcs();
nxtProcTable GetValidatingProcs(); nxtProcTable GetValidatingProcs();
@ -63,7 +62,8 @@ namespace d3d12 {
backendDevice->NextSerial(); backendDevice->NextSerial();
} }
void ExecuteCommandLists(nxtDevice device, std::initializer_list<ID3D12CommandList*> commandLists) { void ExecuteCommandLists(nxtDevice device,
std::initializer_list<ID3D12CommandList*> commandLists) {
Device* backendDevice = reinterpret_cast<Device*>(device); Device* backendDevice = reinterpret_cast<Device*>(device);
backendDevice->ExecuteCommandLists(commandLists); backendDevice->ExecuteCommandLists(commandLists);
} }
@ -89,13 +89,13 @@ namespace d3d12 {
mMapReadRequestTracker(new MapReadRequestTracker(this)), mMapReadRequestTracker(new MapReadRequestTracker(this)),
mResourceAllocator(new ResourceAllocator(this)), mResourceAllocator(new ResourceAllocator(this)),
mResourceUploader(new ResourceUploader(this)) { mResourceUploader(new ResourceUploader(this)) {
D3D12_COMMAND_QUEUE_DESC queueDesc = {}; D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
ASSERT_SUCCESS(d3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue))); ASSERT_SUCCESS(d3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)));
ASSERT_SUCCESS(d3d12Device->CreateFence(mSerial, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mFence))); ASSERT_SUCCESS(
d3d12Device->CreateFence(mSerial, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mFence)));
mFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); mFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
ASSERT(mFenceEvent != nullptr); ASSERT(mFenceEvent != nullptr);
@ -105,8 +105,8 @@ namespace d3d12 {
Device::~Device() { Device::~Device() {
const uint64_t currentSerial = GetSerial(); const uint64_t currentSerial = GetSerial();
NextSerial(); NextSerial();
WaitForSerial(currentSerial); // Wait for all in-flight commands to finish executing WaitForSerial(currentSerial); // Wait for all in-flight commands to finish executing
TickImpl(); // Call tick one last time so resources are cleaned up TickImpl(); // Call tick one last time so resources are cleaned up
delete mCommandAllocatorManager; delete mCommandAllocatorManager;
delete mDescriptorHeapAllocator; delete mDescriptorHeapAllocator;
delete mMapReadRequestTracker; delete mMapReadRequestTracker;
@ -139,22 +139,21 @@ namespace d3d12 {
} }
void Device::OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList) { void Device::OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList) {
ComPtr<ID3D12GraphicsCommandList> &cmdList = *commandList; ComPtr<ID3D12GraphicsCommandList>& cmdList = *commandList;
if (!cmdList) { if (!cmdList) {
ASSERT_SUCCESS(mD3d12Device->CreateCommandList( ASSERT_SUCCESS(mD3d12Device->CreateCommandList(
0, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
D3D12_COMMAND_LIST_TYPE_DIRECT, mCommandAllocatorManager->ReserveCommandAllocator().Get(), nullptr,
mCommandAllocatorManager->ReserveCommandAllocator().Get(), IID_PPV_ARGS(&cmdList)));
nullptr,
IID_PPV_ARGS(&cmdList)
));
} else { } else {
ASSERT_SUCCESS(cmdList->Reset(mCommandAllocatorManager->ReserveCommandAllocator().Get(), nullptr)); ASSERT_SUCCESS(
cmdList->Reset(mCommandAllocatorManager->ReserveCommandAllocator().Get(), nullptr));
} }
} }
ComPtr<ID3D12GraphicsCommandList> Device::GetPendingCommandList() { ComPtr<ID3D12GraphicsCommandList> Device::GetPendingCommandList() {
// Callers of GetPendingCommandList do so to record commands. Only reserve a command allocator when it is needed so we don't submit empty command lists // Callers of GetPendingCommandList do so to record commands. Only reserve a command
// allocator when it is needed so we don't submit empty command lists
if (!mPendingCommands.open) { if (!mPendingCommands.open) {
OpenCommandList(&mPendingCommands.commandList); OpenCommandList(&mPendingCommands.commandList);
mPendingCommands.open = true; mPendingCommands.open = true;
@ -197,10 +196,12 @@ namespace d3d12 {
mPendingCommands.open = false; mPendingCommands.open = false;
lists[0] = mPendingCommands.commandList.Get(); lists[0] = mPendingCommands.commandList.Get();
std::copy(commandLists.begin(), commandLists.end(), lists.begin() + 1); std::copy(commandLists.begin(), commandLists.end(), lists.begin() + 1);
mCommandQueue->ExecuteCommandLists(static_cast<UINT>(commandLists.size() + 1), lists.data()); mCommandQueue->ExecuteCommandLists(static_cast<UINT>(commandLists.size() + 1),
lists.data());
} else { } else {
std::vector<ID3D12CommandList*> lists(commandLists); std::vector<ID3D12CommandList*> lists(commandLists);
mCommandQueue->ExecuteCommandLists(static_cast<UINT>(commandLists.size()), lists.data()); mCommandQueue->ExecuteCommandLists(static_cast<UINT>(commandLists.size()),
lists.data());
} }
} }
@ -268,5 +269,4 @@ namespace d3d12 {
: RenderPassBase(builder), mDevice(device) { : RenderPassBase(builder), mDevice(device) {
} }
} }} // namespace backend::d3d12
}

View File

@ -24,8 +24,7 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class BindGroup; class BindGroup;
class BindGroupLayout; class BindGroupLayout;
@ -77,7 +76,7 @@ namespace d3d12 {
using TextureViewType = TextureView; using TextureViewType = TextureView;
}; };
template<typename T> template <typename T>
auto ToBackend(T&& common) -> decltype(ToBackendBase<D3D12BackendTraits>(common)) { auto ToBackend(T&& common) -> decltype(ToBackendBase<D3D12BackendTraits>(common)) {
return ToBackendBase<D3D12BackendTraits>(common); return ToBackendBase<D3D12BackendTraits>(common);
} }
@ -86,78 +85,77 @@ namespace d3d12 {
// Definition of backend types // Definition of backend types
class Device : public DeviceBase { class Device : public DeviceBase {
public: public:
Device(ComPtr<ID3D12Device> d3d12Device); Device(ComPtr<ID3D12Device> d3d12Device);
~Device(); ~Device();
BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override; BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override; BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override;
BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override; BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
BufferBase* CreateBuffer(BufferBuilder* builder) override; BufferBase* CreateBuffer(BufferBuilder* builder) override;
BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override; BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override; ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override; DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override;
FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override; FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override;
InputStateBase* CreateInputState(InputStateBuilder* builder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override;
PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override; PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override;
QueueBase* CreateQueue(QueueBuilder* builder) override; QueueBase* CreateQueue(QueueBuilder* builder) override;
RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override; RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override; RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SamplerBase* CreateSampler(SamplerBuilder* builder) override; SamplerBase* CreateSampler(SamplerBuilder* builder) override;
ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override; ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override; SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
TextureBase* CreateTexture(TextureBuilder* builder) override; TextureBase* CreateTexture(TextureBuilder* builder) override;
TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override; TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
void TickImpl() override; void TickImpl() override;
ComPtr<ID3D12Device> GetD3D12Device(); ComPtr<ID3D12Device> GetD3D12Device();
ComPtr<ID3D12CommandQueue> GetCommandQueue(); ComPtr<ID3D12CommandQueue> GetCommandQueue();
DescriptorHeapAllocator* GetDescriptorHeapAllocator(); DescriptorHeapAllocator* GetDescriptorHeapAllocator();
MapReadRequestTracker* GetMapReadRequestTracker() const; MapReadRequestTracker* GetMapReadRequestTracker() const;
ResourceAllocator* GetResourceAllocator(); ResourceAllocator* GetResourceAllocator();
ResourceUploader* GetResourceUploader(); ResourceUploader* GetResourceUploader();
void OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList); void OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList);
ComPtr<ID3D12GraphicsCommandList> GetPendingCommandList(); ComPtr<ID3D12GraphicsCommandList> GetPendingCommandList();
uint64_t GetSerial() const; uint64_t GetSerial() const;
void NextSerial(); void NextSerial();
void WaitForSerial(uint64_t serial); void WaitForSerial(uint64_t serial);
void ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists); void ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists);
private: private:
uint64_t mSerial = 0; uint64_t mSerial = 0;
ComPtr<ID3D12Fence> mFence; ComPtr<ID3D12Fence> mFence;
HANDLE mFenceEvent; HANDLE mFenceEvent;
ComPtr<ID3D12Device> mD3d12Device; ComPtr<ID3D12Device> mD3d12Device;
ComPtr<ID3D12CommandQueue> mCommandQueue; ComPtr<ID3D12CommandQueue> mCommandQueue;
CommandAllocatorManager* mCommandAllocatorManager; CommandAllocatorManager* mCommandAllocatorManager;
DescriptorHeapAllocator* mDescriptorHeapAllocator; DescriptorHeapAllocator* mDescriptorHeapAllocator;
MapReadRequestTracker* mMapReadRequestTracker; MapReadRequestTracker* mMapReadRequestTracker;
ResourceAllocator* mResourceAllocator; ResourceAllocator* mResourceAllocator;
ResourceUploader* mResourceUploader; ResourceUploader* mResourceUploader;
struct PendingCommandList { struct PendingCommandList {
ComPtr<ID3D12GraphicsCommandList> commandList; ComPtr<ID3D12GraphicsCommandList> commandList;
bool open = false; bool open = false;
} mPendingCommands; } mPendingCommands;
}; };
class RenderPass : public RenderPassBase { class RenderPass : public RenderPassBase {
public: public:
RenderPass(Device* device, RenderPassBuilder* builder); RenderPass(Device* device, RenderPassBuilder* builder);
private: private:
Device* mDevice; Device* mDevice;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_D3D12BACKEND_H_ #endif // BACKEND_D3D12_D3D12BACKEND_H_

View File

@ -16,8 +16,7 @@
#include "common/BitSetIterator.h" #include "common/BitSetIterator.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
static D3D12_STENCIL_OP StencilOp(nxt::StencilOperation op) { static D3D12_STENCIL_OP StencilOp(nxt::StencilOperation op) {
switch (op) { switch (op) {
@ -43,8 +42,7 @@ namespace d3d12 {
} }
static D3D12_COMPARISON_FUNC ComparisonFunc(nxt::CompareFunction func) { static D3D12_COMPARISON_FUNC ComparisonFunc(nxt::CompareFunction func) {
switch (func) switch (func) {
{
case nxt::CompareFunction::Always: case nxt::CompareFunction::Always:
return D3D12_COMPARISON_FUNC_ALWAYS; return D3D12_COMPARISON_FUNC_ALWAYS;
case nxt::CompareFunction::Equal: case nxt::CompareFunction::Equal:
@ -66,7 +64,8 @@ namespace d3d12 {
} }
} }
static D3D12_DEPTH_STENCILOP_DESC StencilOpDesc(backend::DepthStencilStateBase::StencilFaceInfo faceInfo) { static D3D12_DEPTH_STENCILOP_DESC StencilOpDesc(
backend::DepthStencilStateBase::StencilFaceInfo faceInfo) {
D3D12_DEPTH_STENCILOP_DESC desc; D3D12_DEPTH_STENCILOP_DESC desc;
desc.StencilFailOp = StencilOp(faceInfo.stencilFail); desc.StencilFailOp = StencilOp(faceInfo.stencilFail);
@ -79,9 +78,9 @@ namespace d3d12 {
DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder) DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder)
: DepthStencilStateBase(builder), mDevice(device) { : DepthStencilStateBase(builder), mDevice(device) {
mDepthStencilDescriptor.DepthEnable = TRUE; mDepthStencilDescriptor.DepthEnable = TRUE;
mDepthStencilDescriptor.DepthWriteMask = GetDepth().depthWriteEnabled ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO; mDepthStencilDescriptor.DepthWriteMask =
GetDepth().depthWriteEnabled ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
mDepthStencilDescriptor.DepthFunc = ComparisonFunc(GetDepth().compareFunction); mDepthStencilDescriptor.DepthFunc = ComparisonFunc(GetDepth().compareFunction);
mDepthStencilDescriptor.StencilEnable = StencilTestEnabled() ? TRUE : FALSE; mDepthStencilDescriptor.StencilEnable = StencilTestEnabled() ? TRUE : FALSE;
@ -90,11 +89,10 @@ namespace d3d12 {
mDepthStencilDescriptor.FrontFace = StencilOpDesc(GetStencil().front); mDepthStencilDescriptor.FrontFace = StencilOpDesc(GetStencil().front);
mDepthStencilDescriptor.BackFace = StencilOpDesc(GetStencil().back); mDepthStencilDescriptor.BackFace = StencilOpDesc(GetStencil().back);
} }
const D3D12_DEPTH_STENCIL_DESC& DepthStencilState::GetD3D12DepthStencilDescriptor() const { const D3D12_DEPTH_STENCIL_DESC& DepthStencilState::GetD3D12DepthStencilDescriptor() const {
return mDepthStencilDescriptor; return mDepthStencilDescriptor;
} }
} }} // namespace backend::d3d12
}

View File

@ -19,23 +19,21 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class DepthStencilState : public DepthStencilStateBase { class DepthStencilState : public DepthStencilStateBase {
public: public:
DepthStencilState(Device* device, DepthStencilStateBuilder* builder); DepthStencilState(Device* device, DepthStencilStateBuilder* builder);
const D3D12_DEPTH_STENCIL_DESC& GetD3D12DepthStencilDescriptor() const; const D3D12_DEPTH_STENCIL_DESC& GetD3D12DepthStencilDescriptor() const;
private: private:
Device* mDevice; Device* mDevice;
D3D12_DEPTH_STENCIL_DESC mDepthStencilDescriptor; D3D12_DEPTH_STENCIL_DESC mDepthStencilDescriptor;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_DEPTHSTENCILSTATED3D12_H_ #endif // BACKEND_D3D12_DEPTHSTENCILSTATED3D12_H_

View File

@ -17,14 +17,15 @@
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
#include "common/Assert.h" #include "common/Assert.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
DescriptorHeapHandle::DescriptorHeapHandle() DescriptorHeapHandle::DescriptorHeapHandle()
: mDescriptorHeap(nullptr), mSizeIncrement(0), mOffset(0) { : mDescriptorHeap(nullptr), mSizeIncrement(0), mOffset(0) {
} }
DescriptorHeapHandle::DescriptorHeapHandle(ComPtr<ID3D12DescriptorHeap> descriptorHeap, uint32_t sizeIncrement, uint32_t offset) DescriptorHeapHandle::DescriptorHeapHandle(ComPtr<ID3D12DescriptorHeap> descriptorHeap,
uint32_t sizeIncrement,
uint32_t offset)
: mDescriptorHeap(descriptorHeap), mSizeIncrement(sizeIncrement), mOffset(offset) { : mDescriptorHeap(descriptorHeap), mSizeIncrement(sizeIncrement), mOffset(offset) {
} }
@ -46,29 +47,39 @@ namespace d3d12 {
return handle; return handle;
} }
DescriptorHeapAllocator::DescriptorHeapAllocator(Device* device) DescriptorHeapAllocator::DescriptorHeapAllocator(Device* device)
: mDevice(device), : mDevice(device),
mSizeIncrements { mSizeIncrements{
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV), device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV), device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV), 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, uint32_t allocationSize, DescriptorHeapInfo* heapInfo, D3D12_DESCRIPTOR_HEAP_FLAGS flags) { DescriptorHeapHandle DescriptorHeapAllocator::Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type,
// TODO(enga@google.com): This is just a linear allocator so the heap will quickly run out of space causing a new one to be allocated uint32_t count,
// We should reuse heap subranges that have been released uint32_t allocationSize,
DescriptorHeapInfo* heapInfo,
D3D12_DESCRIPTOR_HEAP_FLAGS flags) {
// TODO(enga@google.com): This is just a linear allocator so the heap will quickly run out
// of space causing a new one to be allocated We should reuse heap subranges that have been
// released
if (count == 0) { if (count == 0) {
return DescriptorHeapHandle(); return DescriptorHeapHandle();
} }
{ {
// If the current pool for this type has space, linearly allocate count bytes in the pool // If the current pool for this type has space, linearly allocate count bytes in the
// pool
auto& allocationInfo = heapInfo->second; auto& allocationInfo = heapInfo->second;
if (allocationInfo.remaining >= count) { if (allocationInfo.remaining >= count) {
DescriptorHeapHandle handle(heapInfo->first, mSizeIncrements[type], allocationInfo.size - allocationInfo.remaining); DescriptorHeapHandle handle(heapInfo->first, mSizeIncrements[type],
allocationInfo.size - allocationInfo.remaining);
allocationInfo.remaining -= count; allocationInfo.remaining -= count;
Release(handle); Release(handle);
return handle; return handle;
@ -83,9 +94,10 @@ namespace d3d12 {
heapDescriptor.Flags = flags; heapDescriptor.Flags = flags;
heapDescriptor.NodeMask = 0; heapDescriptor.NodeMask = 0;
ComPtr<ID3D12DescriptorHeap> heap; ComPtr<ID3D12DescriptorHeap> heap;
ASSERT_SUCCESS(mDevice->GetD3D12Device()->CreateDescriptorHeap(&heapDescriptor, IID_PPV_ARGS(&heap))); ASSERT_SUCCESS(
mDevice->GetD3D12Device()->CreateDescriptorHeap(&heapDescriptor, IID_PPV_ARGS(&heap)));
AllocationInfo allocationInfo = { allocationSize, allocationSize - count }; AllocationInfo allocationInfo = {allocationSize, allocationSize - count};
*heapInfo = std::make_pair(heap, allocationInfo); *heapInfo = std::make_pair(heap, allocationInfo);
DescriptorHeapHandle handle(heap, mSizeIncrements[type], 0); DescriptorHeapHandle handle(heap, mSizeIncrements[type], 0);
@ -93,14 +105,21 @@ namespace d3d12 {
return handle; return handle;
} }
DescriptorHeapHandle DescriptorHeapAllocator::AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count) { DescriptorHeapHandle DescriptorHeapAllocator::AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type,
return Allocate(type, count, count, &mCpuDescriptorHeapInfos[type], D3D12_DESCRIPTOR_HEAP_FLAG_NONE); uint32_t count) {
return Allocate(type, count, count, &mCpuDescriptorHeapInfos[type],
D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
} }
DescriptorHeapHandle DescriptorHeapAllocator::AllocateGPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count) { DescriptorHeapHandle DescriptorHeapAllocator::AllocateGPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type,
ASSERT(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); uint32_t count) {
unsigned int heapSize = (type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ? kMaxCbvUavSrvHeapSize : kMaxSamplerHeapSize); ASSERT(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
return Allocate(type, count, heapSize, &mGpuDescriptorHeapInfos[type], D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
unsigned int heapSize =
(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ? kMaxCbvUavSrvHeapSize
: kMaxSamplerHeapSize);
return Allocate(type, count, heapSize, &mGpuDescriptorHeapInfos[type],
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
} }
void DescriptorHeapAllocator::Tick(uint64_t lastCompletedSerial) { void DescriptorHeapAllocator::Tick(uint64_t lastCompletedSerial) {
@ -110,5 +129,4 @@ namespace d3d12 {
void DescriptorHeapAllocator::Release(DescriptorHeapHandle handle) { void DescriptorHeapAllocator::Release(DescriptorHeapHandle handle) {
mReleasedHandles.Enqueue(handle, mDevice->GetSerial()); mReleasedHandles.Enqueue(handle, mDevice->GetSerial());
} }
} }} // namespace backend::d3d12
}

View File

@ -17,63 +17,67 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
#include "common/SerialQueue.h"
#include <array> #include <array>
#include <vector> #include <vector>
#include "common/SerialQueue.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class DescriptorHeapHandle { class DescriptorHeapHandle {
public:
DescriptorHeapHandle();
DescriptorHeapHandle(ComPtr<ID3D12DescriptorHeap> descriptorHeap,
uint32_t sizeIncrement,
uint32_t offset);
public: ID3D12DescriptorHeap* Get() const;
DescriptorHeapHandle(); D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHandle(uint32_t index) const;
DescriptorHeapHandle(ComPtr<ID3D12DescriptorHeap> descriptorHeap, uint32_t sizeIncrement, uint32_t offset); D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandle(uint32_t index) const;
ID3D12DescriptorHeap* Get() const; private:
D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHandle(uint32_t index) const; ComPtr<ID3D12DescriptorHeap> mDescriptorHeap;
D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandle(uint32_t index) const; uint32_t mSizeIncrement;
uint32_t mOffset;
private:
ComPtr<ID3D12DescriptorHeap> mDescriptorHeap;
uint32_t mSizeIncrement;
uint32_t mOffset;
}; };
class DescriptorHeapAllocator { class DescriptorHeapAllocator {
public: public:
DescriptorHeapAllocator(Device* device); DescriptorHeapAllocator(Device* device);
DescriptorHeapHandle AllocateGPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count); DescriptorHeapHandle AllocateGPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count);
DescriptorHeapHandle AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count); DescriptorHeapHandle AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count);
void Tick(uint64_t lastCompletedSerial); void Tick(uint64_t lastCompletedSerial);
private: private:
static constexpr unsigned int kMaxCbvUavSrvHeapSize = 1000000; static constexpr unsigned int kMaxCbvUavSrvHeapSize = 1000000;
static constexpr unsigned int kMaxSamplerHeapSize = 2048; static constexpr unsigned int kMaxSamplerHeapSize = 2048;
static constexpr unsigned int kDescriptorHeapTypes = D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; static constexpr unsigned int kDescriptorHeapTypes =
D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
struct AllocationInfo { struct AllocationInfo {
uint32_t size = 0; uint32_t size = 0;
uint32_t remaining = 0; uint32_t remaining = 0;
}; };
using DescriptorHeapInfo = std::pair<ComPtr<ID3D12DescriptorHeap>, AllocationInfo>; using DescriptorHeapInfo = std::pair<ComPtr<ID3D12DescriptorHeap>, AllocationInfo>;
DescriptorHeapHandle Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count, uint32_t allocationSize, DescriptorHeapInfo* heapInfo, D3D12_DESCRIPTOR_HEAP_FLAGS flags); DescriptorHeapHandle Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type,
void Release(DescriptorHeapHandle handle); uint32_t count,
uint32_t allocationSize,
DescriptorHeapInfo* heapInfo,
D3D12_DESCRIPTOR_HEAP_FLAGS flags);
void Release(DescriptorHeapHandle handle);
Device* mDevice; Device* mDevice;
std::array<uint32_t, kDescriptorHeapTypes> mSizeIncrements; std::array<uint32_t, kDescriptorHeapTypes> mSizeIncrements;
std::array<DescriptorHeapInfo, kDescriptorHeapTypes> mCpuDescriptorHeapInfos; std::array<DescriptorHeapInfo, kDescriptorHeapTypes> mCpuDescriptorHeapInfos;
std::array<DescriptorHeapInfo, kDescriptorHeapTypes> mGpuDescriptorHeapInfos; std::array<DescriptorHeapInfo, kDescriptorHeapTypes> mGpuDescriptorHeapInfos;
SerialQueue<DescriptorHeapHandle> mReleasedHandles; SerialQueue<DescriptorHeapHandle> mReleasedHandles;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_DESCRIPTORHEAPALLOCATOR_H_ #endif // BACKEND_D3D12_DESCRIPTORHEAPALLOCATOR_H_

View File

@ -14,12 +14,11 @@
#include "backend/d3d12/FramebufferD3D12.h" #include "backend/d3d12/FramebufferD3D12.h"
#include "common/BitSetIterator.h"
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/TextureD3D12.h" #include "backend/d3d12/TextureD3D12.h"
#include "common/BitSetIterator.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
Framebuffer::Framebuffer(Device* device, FramebufferBuilder* builder) Framebuffer::Framebuffer(Device* device, FramebufferBuilder* builder)
: FramebufferBase(builder), mDevice(device) { : FramebufferBase(builder), mDevice(device) {
@ -39,32 +38,36 @@ namespace d3d12 {
if (rtvCount) { if (rtvCount) {
mRtvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap( mRtvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_RTV, rtvCount); D3D12_DESCRIPTOR_HEAP_TYPE_RTV, rtvCount);
} }
if (dsvCount) { if (dsvCount) {
mDsvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap( mDsvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_DSV, dsvCount); D3D12_DESCRIPTOR_HEAP_TYPE_DSV, dsvCount);
} }
for (uint32_t attachment = 0; attachment < renderPass->GetAttachmentCount(); ++attachment) { for (uint32_t attachment = 0; attachment < renderPass->GetAttachmentCount(); ++attachment) {
uint32_t heapIndex = mAttachmentHeapIndices[attachment]; uint32_t heapIndex = mAttachmentHeapIndices[attachment];
auto* textureView = GetTextureView(attachment); auto* textureView = GetTextureView(attachment);
ComPtr<ID3D12Resource> texture = ToBackend(textureView->GetTexture())->GetD3D12Resource(); ComPtr<ID3D12Resource> texture =
ToBackend(textureView->GetTexture())->GetD3D12Resource();
auto format = textureView->GetTexture()->GetFormat(); auto format = textureView->GetTexture()->GetFormat();
if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) { if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) {
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = mDsvHeap.GetCPUHandle(heapIndex); D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = mDsvHeap.GetCPUHandle(heapIndex);
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = ToBackend(textureView)->GetDSVDescriptor(); D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = ToBackend(textureView)->GetDSVDescriptor();
device->GetD3D12Device()->CreateDepthStencilView(texture.Get(), &dsvDesc, dsvHandle); device->GetD3D12Device()->CreateDepthStencilView(texture.Get(), &dsvDesc,
dsvHandle);
} else { } else {
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRtvHeap.GetCPUHandle(heapIndex); D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRtvHeap.GetCPUHandle(heapIndex);
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = ToBackend(textureView)->GetRTVDescriptor(); D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = ToBackend(textureView)->GetRTVDescriptor();
device->GetD3D12Device()->CreateRenderTargetView(texture.Get(), &rtvDesc, rtvHandle); device->GetD3D12Device()->CreateRenderTargetView(texture.Get(), &rtvDesc,
rtvHandle);
} }
} }
} }
Framebuffer::OMSetRenderTargetArgs Framebuffer::GetSubpassOMSetRenderTargetArgs(uint32_t subpassIndex) { Framebuffer::OMSetRenderTargetArgs Framebuffer::GetSubpassOMSetRenderTargetArgs(
uint32_t subpassIndex) {
const auto& subpassInfo = GetRenderPass()->GetSubpassInfo(subpassIndex); const auto& subpassInfo = GetRenderPass()->GetSubpassInfo(subpassIndex);
OMSetRenderTargetArgs args = {}; OMSetRenderTargetArgs args = {};
@ -89,5 +92,4 @@ namespace d3d12 {
return mDsvHeap.GetCPUHandle(mAttachmentHeapIndices[attachmentSlot]); return mDsvHeap.GetCPUHandle(mAttachmentHeapIndices[attachmentSlot]);
} }
} }} // namespace backend::d3d12
}

View File

@ -17,41 +17,39 @@
#include "backend/Framebuffer.h" #include "backend/Framebuffer.h"
#include "common/Constants.h"
#include "backend/d3d12/d3d12_platform.h"
#include "backend/d3d12/DescriptorHeapAllocator.h" #include "backend/d3d12/DescriptorHeapAllocator.h"
#include "backend/d3d12/d3d12_platform.h"
#include "common/Constants.h"
#include <array> #include <array>
#include <vector> #include <vector>
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class Framebuffer : public FramebufferBase { class Framebuffer : public FramebufferBase {
public: public:
struct OMSetRenderTargetArgs { struct OMSetRenderTargetArgs {
unsigned int numRTVs = 0; unsigned int numRTVs = 0;
std::array<D3D12_CPU_DESCRIPTOR_HANDLE, kMaxColorAttachments> RTVs = {}; std::array<D3D12_CPU_DESCRIPTOR_HANDLE, kMaxColorAttachments> RTVs = {};
D3D12_CPU_DESCRIPTOR_HANDLE dsv = {}; D3D12_CPU_DESCRIPTOR_HANDLE dsv = {};
}; };
Framebuffer(Device* device, FramebufferBuilder* builder); Framebuffer(Device* device, FramebufferBuilder* builder);
OMSetRenderTargetArgs GetSubpassOMSetRenderTargetArgs(uint32_t subpassIndex); OMSetRenderTargetArgs GetSubpassOMSetRenderTargetArgs(uint32_t subpassIndex);
D3D12_CPU_DESCRIPTOR_HANDLE GetRTVDescriptor(uint32_t attachmentSlot); D3D12_CPU_DESCRIPTOR_HANDLE GetRTVDescriptor(uint32_t attachmentSlot);
D3D12_CPU_DESCRIPTOR_HANDLE GetDSVDescriptor(uint32_t attachmentSlot); D3D12_CPU_DESCRIPTOR_HANDLE GetDSVDescriptor(uint32_t attachmentSlot);
private: private:
Device* mDevice = nullptr; Device* mDevice = nullptr;
DescriptorHeapHandle mRtvHeap = {}; DescriptorHeapHandle mRtvHeap = {};
DescriptorHeapHandle mDsvHeap = {}; DescriptorHeapHandle mDsvHeap = {};
// Indices into either the RTV or DSV heap, depending on texture format. // Indices into either the RTV or DSV heap, depending on texture format.
std::vector<uint32_t> mAttachmentHeapIndices; std::vector<uint32_t> mAttachmentHeapIndices;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_FRAMEBUFFERD3D12_H_ #endif // BACKEND_D3D12_FRAMEBUFFERD3D12_H_

View File

@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/BindGroupD3D12.h" #include "backend/d3d12/BindGroupD3D12.h"
#include "backend/d3d12/BindGroupLayoutD3D12.h" #include "backend/d3d12/BindGroupLayoutD3D12.h"
#include "backend/d3d12/BlendStateD3D12.h" #include "backend/d3d12/BlendStateD3D12.h"
#include "backend/d3d12/BufferD3D12.h" #include "backend/d3d12/BufferD3D12.h"
#include "backend/d3d12/CommandBufferD3D12.h" #include "backend/d3d12/CommandBufferD3D12.h"
#include "backend/d3d12/ComputePipelineD3D12.h" #include "backend/d3d12/ComputePipelineD3D12.h"
#include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/DepthStencilStateD3D12.h" #include "backend/d3d12/DepthStencilStateD3D12.h"
#include "backend/d3d12/FramebufferD3D12.h" #include "backend/d3d12/FramebufferD3D12.h"
#include "backend/d3d12/InputStateD3D12.h" #include "backend/d3d12/InputStateD3D12.h"

View File

@ -16,8 +16,7 @@
#include "common/BitSetIterator.h" #include "common/BitSetIterator.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
static DXGI_FORMAT VertexFormatType(nxt::VertexFormat format) { static DXGI_FORMAT VertexFormatType(nxt::VertexFormat format) {
switch (format) { switch (format) {
@ -47,7 +46,6 @@ namespace d3d12 {
InputState::InputState(Device* device, InputStateBuilder* builder) InputState::InputState(Device* device, InputStateBuilder* builder)
: InputStateBase(builder), mDevice(device) { : InputStateBase(builder), mDevice(device) {
const auto& attributesSetMask = GetAttributesSetMask(); const auto& attributesSetMask = GetAttributesSetMask();
unsigned int count = 0; unsigned int count = 0;
@ -60,7 +58,8 @@ namespace d3d12 {
const AttributeInfo& attribute = GetAttribute(i); const AttributeInfo& attribute = GetAttribute(i);
// If the HLSL semantic is TEXCOORDN the SemanticName should be "TEXCOORD" and the SemanticIndex N // If the HLSL semantic is TEXCOORDN the SemanticName should be "TEXCOORD" and the
// SemanticIndex N
inputElementDescriptor.SemanticName = "TEXCOORD"; inputElementDescriptor.SemanticName = "TEXCOORD";
inputElementDescriptor.SemanticIndex = static_cast<uint32_t>(i); inputElementDescriptor.SemanticIndex = static_cast<uint32_t>(i);
inputElementDescriptor.Format = VertexFormatType(attribute.format); inputElementDescriptor.Format = VertexFormatType(attribute.format);
@ -70,7 +69,8 @@ namespace d3d12 {
inputElementDescriptor.AlignedByteOffset = attribute.offset; inputElementDescriptor.AlignedByteOffset = attribute.offset;
inputElementDescriptor.InputSlotClass = InputStepModeFunction(input.stepMode); inputElementDescriptor.InputSlotClass = InputStepModeFunction(input.stepMode);
if (inputElementDescriptor.InputSlotClass == D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA) { if (inputElementDescriptor.InputSlotClass ==
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA) {
inputElementDescriptor.InstanceDataStepRate = 0; inputElementDescriptor.InstanceDataStepRate = 0;
} else { } else {
inputElementDescriptor.InstanceDataStepRate = 1; inputElementDescriptor.InstanceDataStepRate = 1;
@ -79,12 +79,10 @@ namespace d3d12 {
mInputLayoutDescriptor.pInputElementDescs = mInputElementDescriptors; mInputLayoutDescriptor.pInputElementDescs = mInputElementDescriptors;
mInputLayoutDescriptor.NumElements = count; mInputLayoutDescriptor.NumElements = count;
} }
const D3D12_INPUT_LAYOUT_DESC& InputState::GetD3D12InputLayoutDescriptor() const { const D3D12_INPUT_LAYOUT_DESC& InputState::GetD3D12InputLayoutDescriptor() const {
return mInputLayoutDescriptor; return mInputLayoutDescriptor;
} }
} }} // namespace backend::d3d12
}

View File

@ -19,24 +19,22 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class InputState : public InputStateBase { class InputState : public InputStateBase {
public: public:
InputState(Device* device, InputStateBuilder* builder); InputState(Device* device, InputStateBuilder* builder);
const D3D12_INPUT_LAYOUT_DESC& GetD3D12InputLayoutDescriptor() const; const D3D12_INPUT_LAYOUT_DESC& GetD3D12InputLayoutDescriptor() const;
private: private:
Device* mDevice; Device* mDevice;
D3D12_INPUT_LAYOUT_DESC mInputLayoutDescriptor; D3D12_INPUT_LAYOUT_DESC mInputLayoutDescriptor;
D3D12_INPUT_ELEMENT_DESC mInputElementDescriptors[kMaxVertexAttributes]; D3D12_INPUT_ELEMENT_DESC mInputElementDescriptors[kMaxVertexAttributes];
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_INPUTSTATED3D12_H_ #endif // BACKEND_D3D12_INPUTSTATED3D12_H_

View File

@ -14,18 +14,16 @@
#include "backend/d3d12/PipelineLayoutD3D12.h" #include "backend/d3d12/PipelineLayoutD3D12.h"
#include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/BindGroupLayoutD3D12.h" #include "backend/d3d12/BindGroupLayoutD3D12.h"
#include "backend/d3d12/D3D12Backend.h"
#include "common/Assert.h" #include "common/Assert.h"
using Microsoft::WRL::ComPtr; using Microsoft::WRL::ComPtr;
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
PipelineLayout::PipelineLayout(Device* device, PipelineLayoutBuilder* builder) PipelineLayout::PipelineLayout(Device* device, PipelineLayoutBuilder* builder)
: PipelineLayoutBase(builder), mDevice(device) { : PipelineLayoutBase(builder), mDevice(device) {
D3D12_ROOT_PARAMETER rootParameters[kMaxBindGroups * 2]; D3D12_ROOT_PARAMETER rootParameters[kMaxBindGroups * 2];
// A root parameter is one of these types // A root parameter is one of these types
@ -34,7 +32,8 @@ namespace d3d12 {
D3D12_ROOT_CONSTANTS Constants; D3D12_ROOT_CONSTANTS Constants;
D3D12_ROOT_DESCRIPTOR Descriptor; D3D12_ROOT_DESCRIPTOR Descriptor;
} rootParameterValues[kMaxBindGroups * 2]; } rootParameterValues[kMaxBindGroups * 2];
// samplers must be in a separate descriptor table so we need at most twice as many tables as bind groups // 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) // Ranges are D3D12_DESCRIPTOR_RANGE_TYPE_(SRV|UAV|CBV|SAMPLER)
// They are grouped together so each bind group has at most 4 ranges // They are grouped together so each bind group has at most 4 ranges
@ -46,9 +45,11 @@ namespace d3d12 {
for (uint32_t group = 0; group < kMaxBindGroups; ++group) { for (uint32_t group = 0; group < kMaxBindGroups; ++group) {
const BindGroupLayout* bindGroupLayout = ToBackend(GetBindGroupLayout(group)); const BindGroupLayout* bindGroupLayout = ToBackend(GetBindGroupLayout(group));
// Set the root descriptor table parameter and copy ranges. Ranges are offset by the bind group index // Set the root descriptor table parameter and copy ranges. Ranges are offset by the
// Returns whether or not the parameter was set. A root parameter is not set if the number of ranges is 0 // bind group index Returns whether or not the parameter was set. A root parameter is
auto SetRootDescriptorTable = [&](uint32_t rangeCount, const D3D12_DESCRIPTOR_RANGE* descriptorRanges) -> bool { // not set if the number of ranges is 0
auto SetRootDescriptorTable =
[&](uint32_t rangeCount, const D3D12_DESCRIPTOR_RANGE* descriptorRanges) -> bool {
if (rangeCount == 0) { if (rangeCount == 0) {
return false; return false;
} }
@ -69,11 +70,13 @@ namespace d3d12 {
return true; return true;
}; };
if (SetRootDescriptorTable(bindGroupLayout->GetCbvUavSrvDescriptorTableSize(), bindGroupLayout->GetCbvUavSrvDescriptorRanges())) { if (SetRootDescriptorTable(bindGroupLayout->GetCbvUavSrvDescriptorTableSize(),
bindGroupLayout->GetCbvUavSrvDescriptorRanges())) {
mCbvUavSrvRootParameterInfo[group] = parameterIndex++; mCbvUavSrvRootParameterInfo[group] = parameterIndex++;
} }
if (SetRootDescriptorTable(bindGroupLayout->GetSamplerDescriptorTableSize(), bindGroupLayout->GetSamplerDescriptorRanges())) { if (SetRootDescriptorTable(bindGroupLayout->GetSamplerDescriptorTableSize(),
bindGroupLayout->GetSamplerDescriptorRanges())) {
mSamplerRootParameterInfo[group] = parameterIndex++; mSamplerRootParameterInfo[group] = parameterIndex++;
} }
} }
@ -83,15 +86,18 @@ namespace d3d12 {
rootSignatureDescriptor.pParameters = rootParameters; 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;
ComPtr<ID3DBlob> signature; ComPtr<ID3DBlob> signature;
ComPtr<ID3DBlob> error; ComPtr<ID3DBlob> error;
ASSERT_SUCCESS(D3D12SerializeRootSignature(&rootSignatureDescriptor, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); ASSERT_SUCCESS(D3D12SerializeRootSignature(
ASSERT_SUCCESS(device->GetD3D12Device()->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&mRootSignature))); &rootSignatureDescriptor, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
ASSERT_SUCCESS(device->GetD3D12Device()->CreateRootSignature(
0, signature->GetBufferPointer(), signature->GetBufferSize(),
IID_PPV_ARGS(&mRootSignature)));
} }
uint32_t PipelineLayout::GetCbvUavSrvRootParameterIndex(uint32_t group) const { uint32_t PipelineLayout::GetCbvUavSrvRootParameterIndex(uint32_t group) const {
ASSERT(group < kMaxBindGroups); ASSERT(group < kMaxBindGroups);
return mCbvUavSrvRootParameterInfo[group]; return mCbvUavSrvRootParameterInfo[group];
@ -105,5 +111,4 @@ namespace d3d12 {
ComPtr<ID3D12RootSignature> PipelineLayout::GetRootSignature() { ComPtr<ID3D12RootSignature> PipelineLayout::GetRootSignature() {
return mRootSignature; return mRootSignature;
} }
} }} // namespace backend::d3d12
}

View File

@ -19,30 +19,28 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class PipelineLayout : public PipelineLayoutBase { class PipelineLayout : public PipelineLayoutBase {
public: public:
PipelineLayout(Device* device, PipelineLayoutBuilder* builder); PipelineLayout(Device* device, PipelineLayoutBuilder* builder);
uint32_t GetCbvUavSrvRootParameterIndex(uint32_t group) const; uint32_t GetCbvUavSrvRootParameterIndex(uint32_t group) const;
uint32_t GetSamplerRootParameterIndex(uint32_t group) const; uint32_t GetSamplerRootParameterIndex(uint32_t group) const;
ComPtr<ID3D12RootSignature> GetRootSignature(); ComPtr<ID3D12RootSignature> GetRootSignature();
private: private:
Device* mDevice; Device* mDevice;
std::array<uint32_t, kMaxBindGroups> mCbvUavSrvRootParameterInfo; std::array<uint32_t, kMaxBindGroups> mCbvUavSrvRootParameterInfo;
std::array<uint32_t, kMaxBindGroups> mSamplerRootParameterInfo; std::array<uint32_t, kMaxBindGroups> mSamplerRootParameterInfo;
ComPtr<ID3D12RootSignature> mRootSignature; ComPtr<ID3D12RootSignature> mRootSignature;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_PIPELINELAYOUTD3D12_H_ #endif // BACKEND_D3D12_PIPELINELAYOUTD3D12_H_

View File

@ -14,17 +14,15 @@
#include "backend/d3d12/QueueD3D12.h" #include "backend/d3d12/QueueD3D12.h"
#include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/CommandBufferD3D12.h" #include "backend/d3d12/CommandBufferD3D12.h"
#include "backend/d3d12/D3D12Backend.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
Queue::Queue(Device* device, QueueBuilder* builder) Queue::Queue(Device* device, QueueBuilder* builder) : QueueBase(builder), mDevice(device) {
: QueueBase(builder), mDevice(device) {
} }
void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) { void Queue::Submit(uint32_t numCommands, CommandBuffer* const* commands) {
mDevice->Tick(); mDevice->Tick();
mDevice->OpenCommandList(&mCommandList); mDevice->OpenCommandList(&mCommandList);
@ -33,10 +31,9 @@ namespace d3d12 {
} }
ASSERT_SUCCESS(mCommandList->Close()); ASSERT_SUCCESS(mCommandList->Close());
mDevice->ExecuteCommandLists({ mCommandList.Get() }); mDevice->ExecuteCommandLists({mCommandList.Get()});
mDevice->NextSerial(); mDevice->NextSerial();
} }
} }} // namespace backend::d3d12
}

View File

@ -19,26 +19,24 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class CommandBuffer; class CommandBuffer;
class Queue : public QueueBase { class Queue : public QueueBase {
public: public:
Queue(Device* device, QueueBuilder* builder); Queue(Device* device, QueueBuilder* builder);
// NXT API // NXT API
void Submit(uint32_t numCommands, CommandBuffer* const * commands); void Submit(uint32_t numCommands, CommandBuffer* const* commands);
private: private:
Device* mDevice; Device* mDevice;
ComPtr<ID3D12GraphicsCommandList> mCommandList; ComPtr<ID3D12GraphicsCommandList> mCommandList;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_QUEUED3D12_H_ #endif // BACKEND_D3D12_QUEUED3D12_H_

View File

@ -18,15 +18,14 @@
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/DepthStencilStateD3D12.h" #include "backend/d3d12/DepthStencilStateD3D12.h"
#include "backend/d3d12/InputStateD3D12.h" #include "backend/d3d12/InputStateD3D12.h"
#include "backend/d3d12/PipelineLayoutD3D12.h"
#include "backend/d3d12/ShaderModuleD3D12.h" #include "backend/d3d12/ShaderModuleD3D12.h"
#include "backend/d3d12/TextureD3D12.h" #include "backend/d3d12/TextureD3D12.h"
#include "backend/d3d12/PipelineLayoutD3D12.h"
#include "common/Assert.h" #include "common/Assert.h"
#include <d3dcompiler.h> #include <d3dcompiler.h>
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
namespace { namespace {
D3D12_PRIMITIVE_TOPOLOGY D3D12PrimitiveTopology(nxt::PrimitiveTopology primitiveTopology) { D3D12_PRIMITIVE_TOPOLOGY D3D12PrimitiveTopology(nxt::PrimitiveTopology primitiveTopology) {
@ -46,7 +45,8 @@ namespace d3d12 {
} }
} }
D3D12_PRIMITIVE_TOPOLOGY_TYPE D3D12PrimitiveTopologyType(nxt::PrimitiveTopology primitiveTopology) { D3D12_PRIMITIVE_TOPOLOGY_TYPE D3D12PrimitiveTopologyType(
nxt::PrimitiveTopology primitiveTopology) {
switch (primitiveTopology) { switch (primitiveTopology) {
case nxt::PrimitiveTopology::PointList: case nxt::PrimitiveTopology::PointList:
return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
@ -60,10 +60,11 @@ namespace d3d12 {
UNREACHABLE(); UNREACHABLE();
} }
} }
} } // namespace
RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder) RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
: RenderPipelineBase(builder), mD3d12PrimitiveTopology(D3D12PrimitiveTopology(GetPrimitiveTopology())) { : RenderPipelineBase(builder),
mD3d12PrimitiveTopology(D3D12PrimitiveTopology(GetPrimitiveTopology())) {
uint32_t compileFlags = 0; uint32_t compileFlags = 0;
#if defined(_DEBUG) #if defined(_DEBUG)
// Enable better shader debugging with the graphics debugging tools. // Enable better shader debugging with the graphics debugging tools.
@ -86,32 +87,22 @@ namespace d3d12 {
D3D12_SHADER_BYTECODE* shader = nullptr; D3D12_SHADER_BYTECODE* shader = nullptr;
switch (stage) { switch (stage) {
case nxt::ShaderStage::Vertex: case nxt::ShaderStage::Vertex:
shader = &descriptor.VS; shader = &descriptor.VS;
compileTarget = "vs_5_1"; compileTarget = "vs_5_1";
break; break;
case nxt::ShaderStage::Fragment: case nxt::ShaderStage::Fragment:
shader = &descriptor.PS; shader = &descriptor.PS;
compileTarget = "ps_5_1"; compileTarget = "ps_5_1";
break; break;
case nxt::ShaderStage::Compute: case nxt::ShaderStage::Compute:
UNREACHABLE(); UNREACHABLE();
break; break;
} }
if(FAILED(D3DCompile( if (FAILED(D3DCompile(hlslSource.c_str(), hlslSource.length(), nullptr, nullptr,
hlslSource.c_str(), nullptr, entryPoint.c_str(), compileTarget, compileFlags, 0,
hlslSource.length(), &compiledShader[stage], &errors))) {
nullptr,
nullptr,
nullptr,
entryPoint.c_str(),
compileTarget,
compileFlags,
0,
&compiledShader[stage],
&errors
))) {
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer())); printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
ASSERT(false); ASSERT(false);
} }
@ -148,7 +139,8 @@ namespace d3d12 {
auto& subpassInfo = renderPass->GetSubpassInfo(GetSubPass()); auto& subpassInfo = renderPass->GetSubpassInfo(GetSubPass());
if (subpassInfo.depthStencilAttachmentSet) { if (subpassInfo.depthStencilAttachmentSet) {
const auto& attachmentInfo = renderPass->GetAttachmentInfo(subpassInfo.depthStencilAttachment); const auto& attachmentInfo =
renderPass->GetAttachmentInfo(subpassInfo.depthStencilAttachment);
descriptor.DSVFormat = D3D12TextureFormat(attachmentInfo.format); descriptor.DSVFormat = D3D12TextureFormat(attachmentInfo.format);
} }
@ -158,7 +150,8 @@ namespace d3d12 {
const auto& attachmentInfo = renderPass->GetAttachmentInfo(attachment); const auto& attachmentInfo = renderPass->GetAttachmentInfo(attachment);
descriptor.RTVFormats[attachmentSlot] = D3D12TextureFormat(attachmentInfo.format); descriptor.RTVFormats[attachmentSlot] = D3D12TextureFormat(attachmentInfo.format);
descriptor.BlendState.RenderTarget[attachmentSlot] = ToBackend(GetBlendState(attachmentSlot))->GetD3D12BlendDesc(); descriptor.BlendState.RenderTarget[attachmentSlot] =
ToBackend(GetBlendState(attachmentSlot))->GetD3D12BlendDesc();
attachmentCount = attachmentSlot + 1; attachmentCount = attachmentSlot + 1;
} }
descriptor.NumRenderTargets = attachmentCount; descriptor.NumRenderTargets = attachmentCount;
@ -174,7 +167,8 @@ namespace d3d12 {
descriptor.SampleDesc.Count = 1; descriptor.SampleDesc.Count = 1;
Device* device = ToBackend(builder->GetDevice()); Device* device = ToBackend(builder->GetDevice());
ASSERT_SUCCESS(device->GetD3D12Device()->CreateGraphicsPipelineState(&descriptor, IID_PPV_ARGS(&mPipelineState))); ASSERT_SUCCESS(device->GetD3D12Device()->CreateGraphicsPipelineState(
&descriptor, IID_PPV_ARGS(&mPipelineState)));
} }
D3D12_PRIMITIVE_TOPOLOGY RenderPipeline::GetD3D12PrimitiveTopology() const { D3D12_PRIMITIVE_TOPOLOGY RenderPipeline::GetD3D12PrimitiveTopology() const {
@ -185,5 +179,4 @@ namespace d3d12 {
return mPipelineState; return mPipelineState;
} }
} }} // namespace backend::d3d12
}

View File

@ -19,22 +19,20 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class RenderPipeline : public RenderPipelineBase { class RenderPipeline : public RenderPipelineBase {
public: public:
RenderPipeline(RenderPipelineBuilder* builder); RenderPipeline(RenderPipelineBuilder* builder);
D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const; D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const;
ComPtr<ID3D12PipelineState> GetPipelineState(); ComPtr<ID3D12PipelineState> GetPipelineState();
private: private:
D3D12_PRIMITIVE_TOPOLOGY mD3d12PrimitiveTopology; D3D12_PRIMITIVE_TOPOLOGY mD3d12PrimitiveTopology;
ComPtr<ID3D12PipelineState> mPipelineState; ComPtr<ID3D12PipelineState> mPipelineState;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_RENDERPIPELINED3D12_H_ #endif // BACKEND_D3D12_RENDERPIPELINED3D12_H_

View File

@ -16,41 +16,31 @@
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
namespace { namespace {
static constexpr D3D12_HEAP_PROPERTIES kDefaultHeapProperties = { static constexpr D3D12_HEAP_PROPERTIES kDefaultHeapProperties = {
D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_DEFAULT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0,
D3D12_CPU_PAGE_PROPERTY_UNKNOWN, 0};
D3D12_MEMORY_POOL_UNKNOWN,
0,
0
};
static constexpr D3D12_HEAP_PROPERTIES kUploadHeapProperties = { static constexpr D3D12_HEAP_PROPERTIES kUploadHeapProperties = {
D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_TYPE_UPLOAD, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0,
D3D12_CPU_PAGE_PROPERTY_UNKNOWN, 0};
D3D12_MEMORY_POOL_UNKNOWN,
0,
0
};
static constexpr D3D12_HEAP_PROPERTIES kReadbackHeapProperties = { static constexpr D3D12_HEAP_PROPERTIES kReadbackHeapProperties = {
D3D12_HEAP_TYPE_READBACK, D3D12_HEAP_TYPE_READBACK, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0,
D3D12_CPU_PAGE_PROPERTY_UNKNOWN, 0};
D3D12_MEMORY_POOL_UNKNOWN, } // namespace
0,
0
};
}
ResourceAllocator::ResourceAllocator(Device* device) : mDevice(device) { ResourceAllocator::ResourceAllocator(Device* device) : mDevice(device) {
} }
ComPtr<ID3D12Resource> ResourceAllocator::Allocate(D3D12_HEAP_TYPE heapType, const D3D12_RESOURCE_DESC &resourceDescriptor, D3D12_RESOURCE_STATES initialUsage) { ComPtr<ID3D12Resource> ResourceAllocator::Allocate(
D3D12_HEAP_TYPE heapType,
const D3D12_RESOURCE_DESC& resourceDescriptor,
D3D12_RESOURCE_STATES initialUsage) {
const D3D12_HEAP_PROPERTIES* heapProperties = nullptr; const D3D12_HEAP_PROPERTIES* heapProperties = nullptr;
switch(heapType) { switch (heapType) {
case D3D12_HEAP_TYPE_DEFAULT: case D3D12_HEAP_TYPE_DEFAULT:
heapProperties = &kDefaultHeapProperties; heapProperties = &kDefaultHeapProperties;
break; break;
@ -68,19 +58,15 @@ namespace d3d12 {
// TODO(enga@google.com): Use CreatePlacedResource // TODO(enga@google.com): Use CreatePlacedResource
ASSERT_SUCCESS(mDevice->GetD3D12Device()->CreateCommittedResource( ASSERT_SUCCESS(mDevice->GetD3D12Device()->CreateCommittedResource(
heapProperties, heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDescriptor, initialUsage, nullptr,
D3D12_HEAP_FLAG_NONE, IID_PPV_ARGS(&resource)));
&resourceDescriptor,
initialUsage,
nullptr,
IID_PPV_ARGS(&resource)
));
return resource; return resource;
} }
void ResourceAllocator::Release(ComPtr<ID3D12Resource> resource) { void ResourceAllocator::Release(ComPtr<ID3D12Resource> resource) {
// Resources may still be in use on the GPU. Enqueue them so that we hold onto them until GPU execution has completed // Resources may still be in use on the GPU. Enqueue them so that we hold onto them until
// GPU execution has completed
mReleasedResources.Enqueue(resource, mDevice->GetSerial()); mReleasedResources.Enqueue(resource, mDevice->GetSerial());
} }
@ -88,5 +74,4 @@ namespace d3d12 {
mReleasedResources.ClearUpTo(lastCompletedSerial); mReleasedResources.ClearUpTo(lastCompletedSerial);
} }
} }} // namespace backend::d3d12
}

View File

@ -19,27 +19,26 @@
#include "common/SerialQueue.h" #include "common/SerialQueue.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class ResourceAllocator { class ResourceAllocator {
public:
ResourceAllocator(Device* device);
public: ComPtr<ID3D12Resource> Allocate(D3D12_HEAP_TYPE heapType,
ResourceAllocator(Device* device); const D3D12_RESOURCE_DESC& resourceDescriptor,
D3D12_RESOURCE_STATES initialUsage);
void Release(ComPtr<ID3D12Resource> resource);
void Tick(uint64_t lastCompletedSerial);
ComPtr<ID3D12Resource> Allocate(D3D12_HEAP_TYPE heapType, const D3D12_RESOURCE_DESC &resourceDescriptor, D3D12_RESOURCE_STATES initialUsage); private:
void Release(ComPtr<ID3D12Resource> resource); Device* mDevice;
void Tick(uint64_t lastCompletedSerial);
private: SerialQueue<ComPtr<ID3D12Resource>> mReleasedResources;
Device* mDevice;
SerialQueue<ComPtr<ID3D12Resource>> mReleasedResources;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_RESOURCEALLOCATIONMANAGER_H_ #endif // BACKEND_D3D12_RESOURCEALLOCATIONMANAGER_H_

View File

@ -17,23 +17,29 @@
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/ResourceAllocator.h" #include "backend/d3d12/ResourceAllocator.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
ResourceUploader::ResourceUploader(Device* device) : mDevice(device) { ResourceUploader::ResourceUploader(Device* device) : mDevice(device) {
} }
void ResourceUploader::BufferSubData(ComPtr<ID3D12Resource> resource, uint32_t start, uint32_t count, const void* data) { void ResourceUploader::BufferSubData(ComPtr<ID3D12Resource> resource,
// TODO(enga@google.com): Use a handle to a subset of a large ring buffer. On Release, decrease reference count on the ring buffer and free when 0. uint32_t start,
// Alternatively, the SerialQueue could be used to track which last point of the ringbuffer is in use, and start reusing chunks of it that aren't in flight. uint32_t count,
const void* data) {
// TODO(enga@google.com): Use a handle to a subset of a large ring buffer. On Release,
// decrease reference count on the ring buffer and free when 0. Alternatively, the
// SerialQueue could be used to track which last point of the ringbuffer is in use, and
// start reusing chunks of it that aren't in flight.
UploadHandle uploadHandle = GetUploadBuffer(count); UploadHandle uploadHandle = GetUploadBuffer(count);
memcpy(uploadHandle.mappedBuffer, data, count); memcpy(uploadHandle.mappedBuffer, data, count);
mDevice->GetPendingCommandList()->CopyBufferRegion(resource.Get(), start, uploadHandle.resource.Get(), 0, count); mDevice->GetPendingCommandList()->CopyBufferRegion(resource.Get(), start,
uploadHandle.resource.Get(), 0, count);
Release(uploadHandle); Release(uploadHandle);
} }
ResourceUploader::UploadHandle ResourceUploader::GetUploadBuffer(uint32_t requiredSize) { ResourceUploader::UploadHandle ResourceUploader::GetUploadBuffer(uint32_t requiredSize) {
// TODO(enga@google.com): This will find or create a mapped buffer of sufficient size and return a handle to a mapped range // TODO(enga@google.com): This will find or create a mapped buffer of sufficient size and
// return a handle to a mapped range
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;
@ -48,12 +54,14 @@ namespace d3d12 {
resourceDescriptor.Flags = D3D12_RESOURCE_FLAG_NONE; resourceDescriptor.Flags = D3D12_RESOURCE_FLAG_NONE;
UploadHandle uploadHandle; UploadHandle uploadHandle;
uploadHandle.resource = mDevice->GetResourceAllocator()->Allocate(D3D12_HEAP_TYPE_UPLOAD, resourceDescriptor, D3D12_RESOURCE_STATE_GENERIC_READ); uploadHandle.resource = mDevice->GetResourceAllocator()->Allocate(
D3D12_HEAP_TYPE_UPLOAD, resourceDescriptor, D3D12_RESOURCE_STATE_GENERIC_READ);
D3D12_RANGE readRange; D3D12_RANGE readRange;
readRange.Begin = 0; readRange.Begin = 0;
readRange.End = 0; readRange.End = 0;
uploadHandle.resource->Map(0, &readRange, reinterpret_cast<void**>(&uploadHandle.mappedBuffer)); uploadHandle.resource->Map(0, &readRange,
reinterpret_cast<void**>(&uploadHandle.mappedBuffer));
return uploadHandle; return uploadHandle;
} }
@ -62,5 +70,4 @@ namespace d3d12 {
mDevice->GetResourceAllocator()->Release(uploadHandle.resource); mDevice->GetResourceAllocator()->Release(uploadHandle.resource);
} }
} }} // namespace backend::d3d12
}

View File

@ -19,29 +19,30 @@
#include "backend/Forward.h" #include "backend/Forward.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class ResourceUploader { class ResourceUploader {
public: public:
ResourceUploader(Device* device); ResourceUploader(Device* device);
void BufferSubData(ComPtr<ID3D12Resource> resource, uint32_t start, uint32_t count, const void* data); void BufferSubData(ComPtr<ID3D12Resource> resource,
uint32_t start,
uint32_t count,
const void* data);
private: private:
struct UploadHandle { struct UploadHandle {
ComPtr<ID3D12Resource> resource; ComPtr<ID3D12Resource> resource;
uint8_t* mappedBuffer; uint8_t* mappedBuffer;
}; };
UploadHandle GetUploadBuffer(uint32_t requiredSize); UploadHandle GetUploadBuffer(uint32_t requiredSize);
void Release(UploadHandle uploadHandle); void Release(UploadHandle uploadHandle);
Device* mDevice; Device* mDevice;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_RESOURCEUPLOADER_H_ #endif // BACKEND_D3D12_RESOURCEUPLOADER_H_

View File

@ -16,14 +16,12 @@
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
Sampler::Sampler(SamplerBuilder* builder)
: SamplerBase(builder) {
Sampler::Sampler(SamplerBuilder* builder) : SamplerBase(builder) {
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn770367(v=vs.85).aspx // 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 // hex value, decimal value, min linear, mag linear, mip linear
// D3D12_FILTER_MIN_MAG_MIP_POINT = 0 0 0 0 0
// D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR = 0x1 1 0 0 1 // 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_LINEAR_MIP_POINT = 0x4 4 0 1 0
// D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR = 0x5 5 0 1 1 // D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR = 0x5 5 0 1 1
@ -69,15 +67,14 @@ namespace d3d12 {
mSamplerDesc.MipLODBias = 0.f; mSamplerDesc.MipLODBias = 0.f;
mSamplerDesc.MaxAnisotropy = 1; mSamplerDesc.MaxAnisotropy = 1;
mSamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; mSamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
mSamplerDesc.BorderColor[0] = mSamplerDesc.BorderColor[1] = mSamplerDesc.BorderColor[2] = mSamplerDesc.BorderColor[3] = 0; mSamplerDesc.BorderColor[0] = mSamplerDesc.BorderColor[1] = mSamplerDesc.BorderColor[2] =
mSamplerDesc.BorderColor[3] = 0;
mSamplerDesc.MinLOD = 0; mSamplerDesc.MinLOD = 0;
mSamplerDesc.MaxLOD = D3D12_FLOAT32_MAX; mSamplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
} }
const D3D12_SAMPLER_DESC& Sampler::GetSamplerDescriptor() const { const D3D12_SAMPLER_DESC& Sampler::GetSamplerDescriptor() const {
return mSamplerDesc; return mSamplerDesc;
} }
} }} // namespace backend::d3d12
}

View File

@ -19,20 +19,18 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Sampler : public SamplerBase { class Sampler : public SamplerBase {
public: public:
Sampler(SamplerBuilder* builder); Sampler(SamplerBuilder* builder);
const D3D12_SAMPLER_DESC& GetSamplerDescriptor() const; const D3D12_SAMPLER_DESC& GetSamplerDescriptor() const;
private: private:
D3D12_SAMPLER_DESC mSamplerDesc; D3D12_SAMPLER_DESC mSamplerDesc;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_SAMPLERD3D12_H_ #endif // BACKEND_D3D12_SAMPLERD3D12_H_

View File

@ -16,8 +16,7 @@
#include <spirv-cross/spirv_hlsl.hpp> #include <spirv-cross/spirv_hlsl.hpp>
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
ShaderModule::ShaderModule(Device* device, ShaderModuleBuilder* builder) ShaderModule::ShaderModule(Device* device, ShaderModuleBuilder* builder)
: ShaderModuleBase(builder), mDevice(device) { : ShaderModuleBase(builder), mDevice(device) {
@ -34,15 +33,18 @@ namespace d3d12 {
ExtractSpirvInfo(compiler); ExtractSpirvInfo(compiler);
// rename bindings so that each register type b/u/t/s starts at 0 and then offset by kMaxBindingsPerGroup * bindGroupIndex // 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) { auto RenumberBindings = [&](std::vector<spirv_cross::Resource> resources) {
std::array<uint32_t, kMaxBindGroups> baseRegisters = {}; std::array<uint32_t, kMaxBindGroups> baseRegisters = {};
for (const auto& resource : resources) { for (const auto& resource : resources) {
auto bindGroupIndex = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet); auto bindGroupIndex =
compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);
auto& baseRegister = baseRegisters[bindGroupIndex]; auto& baseRegister = baseRegisters[bindGroupIndex];
auto bindGroupOffset = bindGroupIndex * kMaxBindingsPerGroup; auto bindGroupOffset = bindGroupIndex * kMaxBindingsPerGroup;
compiler.set_decoration(resource.id, spv::DecorationBinding, bindGroupOffset + baseRegister++); compiler.set_decoration(resource.id, spv::DecorationBinding,
bindGroupOffset + baseRegister++);
} }
}; };
@ -59,5 +61,4 @@ namespace d3d12 {
return mHlslSource; return mHlslSource;
} }
} }} // namespace backend::d3d12
}

View File

@ -17,24 +17,22 @@
#include "backend/ShaderModule.h" #include "backend/ShaderModule.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
class ShaderModule : public ShaderModuleBase { class ShaderModule : public ShaderModuleBase {
public: public:
ShaderModule(Device* device, ShaderModuleBuilder* builder); ShaderModule(Device* device, ShaderModuleBuilder* builder);
const std::string& GetHLSLSource() const; const std::string& GetHLSLSource() const;
private: private:
Device* mDevice; Device* mDevice;
std::string mHlslSource; std::string mHlslSource;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_SHADERMODULED3D12_H_ #endif // BACKEND_D3D12_SHADERMODULED3D12_H_

View File

@ -19,11 +19,9 @@
#include <nxt/nxt_wsi.h> #include <nxt/nxt_wsi.h>
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
SwapChain::SwapChain(SwapChainBuilder* builder) SwapChain::SwapChain(SwapChainBuilder* builder) : SwapChainBase(builder) {
: SwapChainBase(builder) {
const auto& im = GetImplementation(); const auto& im = GetImplementation();
nxtWSIContextD3D12 wsiContext = {}; nxtWSIContextD3D12 wsiContext = {};
wsiContext.device = reinterpret_cast<nxtDevice>(GetDevice()); wsiContext.device = reinterpret_cast<nxtDevice>(GetDevice());
@ -46,6 +44,4 @@ namespace d3d12 {
return new Texture(builder, nativeTexture); return new Texture(builder, nativeTexture);
} }
} }} // namespace backend::d3d12
}

View File

@ -17,19 +17,17 @@
#include "backend/SwapChain.h" #include "backend/SwapChain.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class SwapChain : public SwapChainBase { class SwapChain : public SwapChainBase {
public: public:
SwapChain(SwapChainBuilder* builder); SwapChain(SwapChainBuilder* builder);
~SwapChain(); ~SwapChain();
protected: protected:
TextureBase* GetNextTextureImpl(TextureBuilder* builder) override; TextureBase* GetNextTextureImpl(TextureBuilder* builder) override;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_SWAPCHAIN_D3D12_H_ #endif // BACKEND_D3D12_SWAPCHAIN_D3D12_H_

View File

@ -17,11 +17,16 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
#include "common/Assert.h" #include "common/Assert.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
namespace { namespace {
void ComputeTexelOffsets(uint32_t offset, uint32_t rowPitch, uint32_t slicePitch, uint32_t texelSize, uint32_t* texelOffsetX, uint32_t* texelOffsetY, uint32_t* texelOffsetZ) { void ComputeTexelOffsets(uint32_t offset,
uint32_t rowPitch,
uint32_t slicePitch,
uint32_t texelSize,
uint32_t* texelOffsetX,
uint32_t* texelOffsetY,
uint32_t* texelOffsetZ) {
uint32_t byteOffsetX = offset % rowPitch; uint32_t byteOffsetX = offset % rowPitch;
offset -= byteOffsetX; offset -= byteOffsetX;
uint32_t byteOffsetY = offset % slicePitch; uint32_t byteOffsetY = offset % slicePitch;
@ -31,10 +36,17 @@ namespace d3d12 {
*texelOffsetY = byteOffsetY / rowPitch; *texelOffsetY = byteOffsetY / rowPitch;
*texelOffsetZ = byteOffsetZ / slicePitch; *texelOffsetZ = byteOffsetZ / slicePitch;
} }
} } // namespace
TextureCopySplit ComputeTextureCopySplit(uint32_t x, uint32_t y, uint32_t z, uint32_t width, uint32_t height, uint32_t depth, uint32_t texelSize, uint32_t offset, uint32_t rowPitch) {
TextureCopySplit ComputeTextureCopySplit(uint32_t x,
uint32_t y,
uint32_t z,
uint32_t width,
uint32_t height,
uint32_t depth,
uint32_t texelSize,
uint32_t offset,
uint32_t rowPitch) {
TextureCopySplit copy; TextureCopySplit copy;
if (z != 0 || depth > 1) { if (z != 0 || depth > 1) {
@ -58,27 +70,30 @@ namespace d3d12 {
copy.copies[0].copySize.width = width; copy.copies[0].copySize.width = width;
copy.copies[0].copySize.height = height; copy.copies[0].copySize.height = height;
copy.copies[0].copySize.depth = depth; copy.copies[0].copySize.depth = depth;
copy.copies[0].bufferOffset.x = 0; copy.copies[0].bufferOffset.x = 0;
copy.copies[0].bufferOffset.y = 0; copy.copies[0].bufferOffset.y = 0;
copy.copies[0].bufferOffset.z = 0; copy.copies[0].bufferOffset.z = 0;
copy.copies[0].bufferSize.width = width; copy.copies[0].bufferSize.width = width;
copy.copies[0].bufferSize.height = height; copy.copies[0].bufferSize.height = height;
copy.copies[0].bufferSize.depth = depth; copy.copies[0].bufferSize.depth = depth;
// Return early. There is only one copy needed because the offset is already 512-byte aligned // Return early. There is only one copy needed because the offset is already 512-byte
// aligned
return copy; return copy;
} }
ASSERT(alignedOffset < offset); ASSERT(alignedOffset < offset);
uint32_t texelOffsetX, texelOffsetY, texelOffsetZ; uint32_t texelOffsetX, texelOffsetY, texelOffsetZ;
ComputeTexelOffsets(offset - alignedOffset, rowPitch, rowPitch * height, texelSize, &texelOffsetX, &texelOffsetY, &texelOffsetZ); ComputeTexelOffsets(offset - alignedOffset, rowPitch, rowPitch * height, texelSize,
&texelOffsetX, &texelOffsetY, &texelOffsetZ);
uint32_t rowPitchInTexels = rowPitch / texelSize; uint32_t rowPitchInTexels = rowPitch / texelSize;
if (width + texelOffsetX <= rowPitchInTexels) { if (width + texelOffsetX <= rowPitchInTexels) {
// The region's rows fit inside the row pitch. In this case, extend the width of the PlacedFootprint and copy the buffer with an offset location // The region's rows fit inside the row pitch. In this case, extend the width of the
// PlacedFootprint and copy the buffer with an offset location
// |<--------------- row pitch --------------->| // |<--------------- row pitch --------------->|
// //
// |-------------------------------------------| // |-------------------------------------------|
@ -133,7 +148,6 @@ namespace d3d12 {
// |+++++++++ | // |+++++++++ |
// |-------------------------------------------| // |-------------------------------------------|
// Copy 0: // Copy 0:
// |-------------------------------------------| // |-------------------------------------------|
// | | // | |
@ -173,7 +187,6 @@ namespace d3d12 {
copy.copies[0].bufferSize.height = height + texelOffsetY; copy.copies[0].bufferSize.height = height + texelOffsetY;
copy.copies[0].bufferSize.depth = depth + texelOffsetZ; copy.copies[0].bufferSize.depth = depth + texelOffsetZ;
copy.copies[1].textureOffset.x = x + copy.copies[0].copySize.width; copy.copies[1].textureOffset.x = x + copy.copies[0].copySize.width;
copy.copies[1].textureOffset.y = y; copy.copies[1].textureOffset.y = y;
copy.copies[1].textureOffset.z = z; copy.copies[1].textureOffset.z = z;
@ -190,10 +203,7 @@ namespace d3d12 {
copy.copies[1].bufferSize.height = height + texelOffsetY + 1; copy.copies[1].bufferSize.height = height + texelOffsetY + 1;
copy.copies[1].bufferSize.depth = depth + texelOffsetZ; copy.copies[1].bufferSize.depth = depth + texelOffsetZ;
return copy; return copy;
} }
} }} // namespace backend::d3d12
}

View File

@ -19,14 +19,11 @@
#include <array> #include <array>
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
struct TextureCopySplit { struct TextureCopySplit {
static constexpr unsigned int kMaxTextureCopyRegions = 2; static constexpr unsigned int kMaxTextureCopyRegions = 2;
struct Extent { struct Extent {
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
@ -52,9 +49,16 @@ namespace d3d12 {
std::array<CopyInfo, kMaxTextureCopyRegions> copies; std::array<CopyInfo, kMaxTextureCopyRegions> copies;
}; };
TextureCopySplit ComputeTextureCopySplit(uint32_t x, uint32_t y, uint32_t z, uint32_t width, uint32_t height, uint32_t depth, uint32_t texelSize, uint32_t offset, uint32_t rowPitch); TextureCopySplit ComputeTextureCopySplit(uint32_t x,
uint32_t y,
uint32_t z,
uint32_t width,
uint32_t height,
uint32_t depth,
uint32_t texelSize,
uint32_t offset,
uint32_t rowPitch);
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_TEXTURECOPYSPLITTER_H_ #endif // BACKEND_D3D12_TEXTURECOPYSPLITTER_H_

View File

@ -17,11 +17,11 @@
#include "backend/d3d12/D3D12Backend.h" #include "backend/d3d12/D3D12Backend.h"
#include "backend/d3d12/ResourceAllocator.h" #include "backend/d3d12/ResourceAllocator.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
namespace { namespace {
D3D12_RESOURCE_STATES D3D12TextureUsage(nxt::TextureUsageBit usage, nxt::TextureFormat format) { D3D12_RESOURCE_STATES D3D12TextureUsage(nxt::TextureUsageBit usage,
nxt::TextureFormat format) {
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON; D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON;
if (usage & nxt::TextureUsageBit::TransferSrc) { if (usage & nxt::TextureUsageBit::TransferSrc) {
@ -31,7 +31,8 @@ namespace d3d12 {
resourceState |= D3D12_RESOURCE_STATE_COPY_DEST; resourceState |= D3D12_RESOURCE_STATE_COPY_DEST;
} }
if (usage & nxt::TextureUsageBit::Sampled) { if (usage & nxt::TextureUsageBit::Sampled) {
resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
} }
if (usage & nxt::TextureUsageBit::Storage) { if (usage & nxt::TextureUsageBit::Storage) {
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS; resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
@ -47,7 +48,8 @@ namespace d3d12 {
return resourceState; return resourceState;
} }
D3D12_RESOURCE_FLAGS D3D12ResourceFlags(nxt::TextureUsageBit usage, nxt::TextureFormat format) { D3D12_RESOURCE_FLAGS D3D12ResourceFlags(nxt::TextureUsageBit usage,
nxt::TextureFormat format) {
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE; D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE;
if (usage & nxt::TextureUsageBit::Storage) { if (usage & nxt::TextureUsageBit::Storage) {
@ -62,7 +64,7 @@ namespace d3d12 {
} }
ASSERT(!(flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) || ASSERT(!(flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) ||
flags == D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL); flags == D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);
return flags; return flags;
} }
@ -75,7 +77,7 @@ namespace d3d12 {
} }
} }
} } // namespace
DXGI_FORMAT D3D12TextureFormat(nxt::TextureFormat format) { DXGI_FORMAT D3D12TextureFormat(nxt::TextureFormat format) {
switch (format) { switch (format) {
@ -94,7 +96,6 @@ namespace d3d12 {
Texture::Texture(TextureBuilder* builder) Texture::Texture(TextureBuilder* builder)
: TextureBase(builder), mDevice(ToBackend(builder->GetDevice())) { : TextureBase(builder), mDevice(ToBackend(builder->GetDevice())) {
D3D12_RESOURCE_DESC resourceDescriptor; D3D12_RESOURCE_DESC resourceDescriptor;
resourceDescriptor.Dimension = D3D12TextureDimension(GetDimension()); resourceDescriptor.Dimension = D3D12TextureDimension(GetDimension());
resourceDescriptor.Alignment = 0; resourceDescriptor.Alignment = 0;
@ -108,14 +109,17 @@ namespace d3d12 {
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resourceDescriptor.Flags = D3D12ResourceFlags(GetAllowedUsage(), GetFormat()); resourceDescriptor.Flags = D3D12ResourceFlags(GetAllowedUsage(), GetFormat());
mResource = mDevice->GetResourceAllocator()->Allocate(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor, D3D12TextureUsage(GetUsage(), GetFormat())); mResource =
mDevice->GetResourceAllocator()->Allocate(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor,
D3D12TextureUsage(GetUsage(), GetFormat()));
mResourcePtr = mResource.Get(); mResourcePtr = mResource.Get();
} }
// With this constructor, the lifetime of the ID3D12Resource is externally managed. // With this constructor, the lifetime of the ID3D12Resource is externally managed.
Texture::Texture(TextureBuilder* builder, ID3D12Resource* nativeTexture) Texture::Texture(TextureBuilder* builder, ID3D12Resource* nativeTexture)
: TextureBase(builder), mDevice(ToBackend(builder->GetDevice())), : TextureBase(builder),
mResourcePtr(nativeTexture) { mDevice(ToBackend(builder->GetDevice())),
mResourcePtr(nativeTexture) {
} }
Texture::~Texture() { Texture::~Texture() {
@ -133,7 +137,9 @@ namespace d3d12 {
return mResourcePtr; return mResourcePtr;
} }
bool Texture::GetResourceTransitionBarrier(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier) { bool Texture::GetResourceTransitionBarrier(nxt::TextureUsageBit currentUsage,
nxt::TextureUsageBit targetUsage,
D3D12_RESOURCE_BARRIER* barrier) {
D3D12_RESOURCE_STATES stateBefore = D3D12TextureUsage(currentUsage, GetFormat()); D3D12_RESOURCE_STATES stateBefore = D3D12TextureUsage(currentUsage, GetFormat());
D3D12_RESOURCE_STATES stateAfter = D3D12TextureUsage(targetUsage, GetFormat()); D3D12_RESOURCE_STATES stateAfter = D3D12TextureUsage(targetUsage, GetFormat());
@ -151,16 +157,15 @@ namespace d3d12 {
return true; return true;
} }
void Texture::TransitionUsageImpl(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage) { void Texture::TransitionUsageImpl(nxt::TextureUsageBit currentUsage,
nxt::TextureUsageBit targetUsage) {
D3D12_RESOURCE_BARRIER barrier; D3D12_RESOURCE_BARRIER barrier;
if (GetResourceTransitionBarrier(currentUsage, targetUsage, &barrier)) { if (GetResourceTransitionBarrier(currentUsage, targetUsage, &barrier)) {
mDevice->GetPendingCommandList()->ResourceBarrier(1, &barrier); mDevice->GetPendingCommandList()->ResourceBarrier(1, &barrier);
} }
} }
TextureView::TextureView(TextureViewBuilder* builder) TextureView::TextureView(TextureViewBuilder* builder) : TextureViewBase(builder) {
: TextureViewBase(builder) {
mSrvDesc.Format = D3D12TextureFormat(GetTexture()->GetFormat()); mSrvDesc.Format = D3D12TextureFormat(GetTexture()->GetFormat());
mSrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; mSrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
switch (GetTexture()->GetDimension()) { switch (GetTexture()->GetDimension()) {
@ -196,5 +201,4 @@ namespace d3d12 {
return dsvDesc; return dsvDesc;
} }
} }} // namespace backend::d3d12
}

View File

@ -19,43 +19,44 @@
#include "backend/d3d12/d3d12_platform.h" #include "backend/d3d12/d3d12_platform.h"
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
class Device; class Device;
DXGI_FORMAT D3D12TextureFormat(nxt::TextureFormat format); DXGI_FORMAT D3D12TextureFormat(nxt::TextureFormat format);
class Texture : public TextureBase { class Texture : public TextureBase {
public: public:
Texture(TextureBuilder* builder); Texture(TextureBuilder* builder);
Texture(TextureBuilder* builder, ID3D12Resource* nativeTexture); Texture(TextureBuilder* builder, ID3D12Resource* nativeTexture);
~Texture(); ~Texture();
DXGI_FORMAT GetD3D12Format() const; DXGI_FORMAT GetD3D12Format() const;
ID3D12Resource* GetD3D12Resource(); ID3D12Resource* GetD3D12Resource();
bool GetResourceTransitionBarrier(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier); bool GetResourceTransitionBarrier(nxt::TextureUsageBit currentUsage,
nxt::TextureUsageBit targetUsage,
D3D12_RESOURCE_BARRIER* barrier);
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage) override; void TransitionUsageImpl(nxt::TextureUsageBit currentUsage,
nxt::TextureUsageBit targetUsage) override;
private: private:
Device* mDevice; Device* mDevice;
ComPtr<ID3D12Resource> mResource = {}; ComPtr<ID3D12Resource> mResource = {};
ID3D12Resource* mResourcePtr = nullptr; ID3D12Resource* mResourcePtr = nullptr;
}; };
class TextureView : public TextureViewBase { class TextureView : public TextureViewBase {
public: public:
TextureView(TextureViewBuilder* builder); TextureView(TextureViewBuilder* builder);
const D3D12_SHADER_RESOURCE_VIEW_DESC& GetSRVDescriptor() const; const D3D12_SHADER_RESOURCE_VIEW_DESC& GetSRVDescriptor() const;
D3D12_RENDER_TARGET_VIEW_DESC GetRTVDescriptor(); D3D12_RENDER_TARGET_VIEW_DESC GetRTVDescriptor();
D3D12_DEPTH_STENCIL_VIEW_DESC GetDSVDescriptor(); D3D12_DEPTH_STENCIL_VIEW_DESC GetDSVDescriptor();
private: private:
D3D12_SHADER_RESOURCE_VIEW_DESC mSrvDesc; D3D12_SHADER_RESOURCE_VIEW_DESC mSrvDesc;
}; };
} }} // namespace backend::d3d12
}
#endif // BACKEND_D3D12_TEXTURED3D12_H_ #endif // BACKEND_D3D12_TEXTURED3D12_H_

View File

@ -15,10 +15,10 @@
#ifndef BACKEND_D3D12_D3D12PLATFORM_H_ #ifndef BACKEND_D3D12_D3D12PLATFORM_H_
#define BACKEND_D3D12_D3D12PLATFORM_H_ #define BACKEND_D3D12_D3D12PLATFORM_H_
#include <wrl.h>
#include <d3d12.h> #include <d3d12.h>
#include <dxgi1_4.h> #include <dxgi1_4.h>
#include <wrl.h>
using Microsoft::WRL::ComPtr; using Microsoft::WRL::ComPtr;
#endif // BACKEND_D3D12_D3D12PLATFORM_H_ #endif // BACKEND_D3D12_D3D12PLATFORM_H_