22 const D3D12_HEAP_PROPERTIES heap{.Type = isReadback ? D3D12_HEAP_TYPE_READBACK
23 : isUpload ? D3D12_HEAP_TYPE_UPLOAD
24 : D3D12_HEAP_TYPE_DEFAULT};
26 const D3D12_RESOURCE_DESC desc{
27 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
30 .DepthOrArraySize = 1,
32 .Format = DXGI_FORMAT_UNKNOWN,
33 .SampleDesc = {.Count = 1},
34 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
35 .Flags = isReadback || isUpload ? D3D12_RESOURCE_FLAG_NONE : D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
38 const D3D12_RESOURCE_STATES state = isReadback ? D3D12_RESOURCE_STATE_COPY_DEST
39 : isUpload ? D3D12_RESOURCE_STATE_GENERIC_READ
40 : D3D12_RESOURCE_STATE_COMMON;
42 ComPtr<ID3D12Resource> buffer;
45 nullptr, IID_PPV_ARGS(&buffer)))) {
52 bool ReadBuffer(ID3D12Resource* readback, std::span<std::byte> destination) {
53 const D3D12_RANGE readRange{.Begin = 0, .End = destination.size()};
54 void* mapped =
nullptr;
58 std::memcpy(destination.data(), mapped, destination.size());
59 const D3D12_RANGE writtenRange{};
60 readback->Unmap(0, &writtenRange);
65 D3D12_RESOURCE_BARRIER
Transition(ID3D12Resource* resource, D3D12_RESOURCE_STATES before,
66 D3D12_RESOURCE_STATES after) {
67 return {.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
68 .Transition = {.pResource = resource,
69 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
70 .StateBefore = before,
71 .StateAfter = after}};
78 void RecordCopyToReadback(ID3D12GraphicsCommandList* list, ID3D12Resource* source, ID3D12Resource* readback) {
79 const D3D12_RESOURCE_BARRIER barrier{
80 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
81 .Transition = {.pResource = source,
82 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
83 .StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
84 .StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE},
87 list->ResourceBarrier(1, &barrier);
88 list->CopyResource(readback, source);
94 const auto rootUav = [](uint32_t shaderRegister, uint32_t registerSpace) {
95 return D3D12_ROOT_PARAMETER1{.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV,
96 .Descriptor = {.ShaderRegister = shaderRegister,
97 .RegisterSpace = registerSpace,
98 .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE},
99 .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL};
102 std::vector<D3D12_ROOT_PARAMETER1> parameters;
104 for (uint32_t index = 0; index < layout.
uavCount; ++index)
105 parameters.push_back(rootUav(index, 0));
108 parameters.push_back(
109 {.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
110 .Constants = {.ShaderRegister = 0, .RegisterSpace = 0, .Num32BitValues = layout.
rootConstantCount},
111 .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL});
115 parameters.push_back(rootUav(0, DEBUG_RING_REGISTER_SPACE));
118 parameters.push_back(rootUav(WG_STATS_REGISTER, WG_STATS_REGISTER_SPACE));
121 parameters.push_back(rootUav(GT_REGISTER, GT_REGISTER_SPACE));
123 for (uint32_t index = 0; index < layout.
srvCount; ++index) {
124 parameters.push_back({.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV,
125 .Descriptor = {.ShaderRegister = index,
127 .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE},
128 .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL});
131 D3D12_VERSIONED_ROOT_SIGNATURE_DESC desc{.Version = D3D_ROOT_SIGNATURE_VERSION_1_1};
132 desc.Desc_1_1 = {.NumParameters =
static_cast<UINT
>(parameters.size()), .pParameters = parameters.data()};
134 ComPtr<ID3DBlob> blob;
135 ComPtr<ID3DBlob> error;
136 if (FAILED(D3D12SerializeVersionedRootSignature(&desc, &blob, &error))) {
137 const std::string_view message = error ?
static_cast<const char*
>(error->GetBufferPointer()) :
"";
143 ComPtr<ID3D12RootSignature> rootSignature;
145 device->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(),
146 IID_PPV_ARGS(&rootSignature)))) {
150 return rootSignature;
154 std::span<const std::byte> bytecode) {
155 const D3D12_COMPUTE_PIPELINE_STATE_DESC desc{
156 .pRootSignature = rootSignature,
157 .CS = {.pShaderBytecode = bytecode.data(), .BytecodeLength = bytecode.size()},
160 ComPtr<ID3D12PipelineState> pipeline;