Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
resources.cpp
Go to the documentation of this file.
1// resources.cpp — バッファ・ルート署名・パイプライン・シェーダーのファイル(T-0013)。
2#include "gpu/resources.h"
3
4#include "common/debug_ring.hlsli"
5#include "common/graph_trace.hlsli"
6#include "common/work_graph_stats.hlsli"
7#include "core/aliases.h"
8#include "core/hresult.h"
9#include "core/log.h"
10#include "core/paths.h"
11#include "core/unicode.h"
12#include "gpu/com_ptr.h"
13
14namespace bicameral::gpu {
15
16 // --- バッファ ---
17
18 ComPtr<ID3D12Resource> CreateBuffer(ID3D12Device* device, uint64_t sizeBytes, BufferKind kind) {
19 const bool isReadback = kind == BufferKind::Readback;
20 const bool isUpload = kind == BufferKind::Upload;
21
22 const D3D12_HEAP_PROPERTIES heap{.Type = isReadback ? D3D12_HEAP_TYPE_READBACK
23 : isUpload ? D3D12_HEAP_TYPE_UPLOAD
24 : D3D12_HEAP_TYPE_DEFAULT};
25
26 const D3D12_RESOURCE_DESC desc{
27 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
28 .Width = sizeBytes,
29 .Height = 1,
30 .DepthOrArraySize = 1,
31 .MipLevels = 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,
36 };
37
38 const D3D12_RESOURCE_STATES state = isReadback ? D3D12_RESOURCE_STATE_COPY_DEST
39 : isUpload ? D3D12_RESOURCE_STATE_GENERIC_READ
40 : D3D12_RESOURCE_STATE_COMMON;
41
42 ComPtr<ID3D12Resource> buffer;
43
44 if (!BICAMERAL_CHECK_HR(Channel::Gpu, device->CreateCommittedResource(&heap, D3D12_HEAP_FLAG_NONE, &desc, state,
45 nullptr, IID_PPV_ARGS(&buffer)))) {
46 return nullptr;
47 }
48
49 return buffer;
50 }
51
52 bool ReadBuffer(ID3D12Resource* readback, std::span<std::byte> destination) {
53 const D3D12_RANGE readRange{.Begin = 0, .End = destination.size()};
54 void* mapped = nullptr;
55 if (!BICAMERAL_CHECK_HR(Channel::Gpu, readback->Map(0, &readRange, &mapped)))
56 return false;
57
58 std::memcpy(destination.data(), mapped, destination.size());
59 const D3D12_RANGE writtenRange{}; // CPU は書いていない
60 readback->Unmap(0, &writtenRange);
61
62 return true;
63 }
64
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}};
72 }
73
74 D3D12_RESOURCE_BARRIER UavBarrier(ID3D12Resource* resource) {
75 return {.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV, .UAV = {.pResource = resource}};
76 }
77
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},
85 };
86
87 list->ResourceBarrier(1, &barrier);
88 list->CopyResource(readback, source);
89 }
90
91 // --- ルート署名とパイプライン ---
92
93 ComPtr<ID3D12RootSignature> CreateRootSignature(ID3D12Device* device, const RootSignatureLayout& layout) {
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};
100 };
101
102 std::vector<D3D12_ROOT_PARAMETER1> parameters;
103 parameters.reserve(layout.uavCount + layout.srvCount + 4);
104 for (uint32_t index = 0; index < layout.uavCount; ++index)
105 parameters.push_back(rootUav(index, 0));
106
107 if (layout.rootConstantCount > 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});
112 }
113
114 if (layout.debugRing)
115 parameters.push_back(rootUav(0, DEBUG_RING_REGISTER_SPACE));
116
117 if (layout.graphStats)
118 parameters.push_back(rootUav(WG_STATS_REGISTER, WG_STATS_REGISTER_SPACE));
119
120 if (layout.graphTrace)
121 parameters.push_back(rootUav(GT_REGISTER, GT_REGISTER_SPACE));
122
123 for (uint32_t index = 0; index < layout.srvCount; ++index) {
124 parameters.push_back({.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV,
125 .Descriptor = {.ShaderRegister = index,
126 .RegisterSpace = 0,
127 .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE},
128 .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL});
129 }
130
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()};
133
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()) : "";
138 Log(Channel::Gpu, Level::Error, "ルート署名をシリアライズできない: {}", message);
139
140 return nullptr;
141 }
142
143 ComPtr<ID3D12RootSignature> rootSignature;
145 device->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(),
146 IID_PPV_ARGS(&rootSignature)))) {
147 return nullptr;
148 }
149
150 return rootSignature;
151 }
152
153 ComPtr<ID3D12PipelineState> CreateComputePipeline(ID3D12Device* device, ID3D12RootSignature* 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()},
158 };
159
160 ComPtr<ID3D12PipelineState> pipeline;
161 if (!BICAMERAL_CHECK_HR(Channel::Gpu, device->CreateComputePipelineState(&desc, IID_PPV_ARGS(&pipeline))))
162 return nullptr;
163
164 return pipeline;
165 }
166
167 // --- シェーダーのファイル ---
168
169 std::expected<std::vector<std::byte>, std::string> LoadShader(std::string_view relativePath) {
170 const fs::path path = ExecutableDirectory() / "shaders" / ToWide(relativePath);
171 std::ifstream file(path, std::ios::binary | std::ios::ate);
172 if (!file)
173 return std::unexpected("シェーダーを開けない: " + ToUtf8(path.wstring()));
174
175 std::vector<std::byte> bytes(static_cast<size_t>(file.tellg()));
176 file.seekg(0);
177 file.read(reinterpret_cast<char*>(bytes.data()), static_cast<std::streamsize>(bytes.size()));
178 if (!file)
179 return std::unexpected("シェーダーを読めない: " + ToUtf8(path.wstring()));
180
181 return bytes;
182 }
183
184} // namespace bicameral::gpu
#define BICAMERAL_CHECK_HR(channel, expression)
Definition hresult.h:32
ComPtr< ID3D12RootSignature > CreateRootSignature(ID3D12Device *device, const RootSignatureLayout &layout)
Definition resources.cpp:93
std::expected< std::vector< std::byte >, std::string > LoadShader(std::string_view relativePath)
bool ReadBuffer(ID3D12Resource *readback, std::span< std::byte > destination)
Definition resources.cpp:52
ComPtr< ID3D12PipelineState > CreateComputePipeline(ID3D12Device *device, ID3D12RootSignature *rootSignature, std::span< const std::byte > bytecode)
D3D12_RESOURCE_BARRIER Transition(ID3D12Resource *resource, D3D12_RESOURCE_STATES before, D3D12_RESOURCE_STATES after)
Definition resources.cpp:65
ComPtr< ID3D12Resource > CreateBuffer(ID3D12Device *device, uint64_t sizeBytes, BufferKind kind)
Definition resources.cpp:18
void RecordCopyToReadback(ID3D12GraphicsCommandList *list, ID3D12Resource *source, ID3D12Resource *readback)
Definition resources.cpp:78
D3D12_RESOURCE_BARRIER UavBarrier(ID3D12Resource *resource)
Definition resources.cpp:74
fs::path ExecutableDirectory()
Definition paths.cpp:12
void Log(Channel channel, Level level, FormatWithLocation< std::type_identity_t< Args >... > pattern, Args &&... args)
Definition log.h:140
std::string ToUtf8(std::wstring_view text)
Definition unicode.cpp:10
std::wstring ToWide(std::string_view text)
Definition unicode.cpp:22