Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
gpu_lab_box.cpp
Go to the documentation of this file.
1// gpu_lab_box.cpp — 実験室の箱の GPU 側(gpu_lab_box.h)。CPU リファレンスは sim/lab_box.cpp の StepLabBox。
2#include "sim/gpu_lab_box.h"
3
4#include <cstring>
5
6#include "gpu/resources.h"
7
8namespace bicameral::sim {
9
10 std::expected<GpuLabBox, std::string> GpuLabBox::Create(ID3D12Device5* device, const BakedReactionTable& table) {
11 auto nest = GpuMultires::Create(device, table, LabBoxCapacity(table));
12 if (!nest)
13 return std::unexpected(nest.error());
14
15 GpuLabBox result(std::move(*nest));
16 result.m_speciesCount = static_cast<uint32_t>(table.species.size());
17
18 const auto shader = gpu::LoadShader("sim/lab_box_apply.cso");
19 if (!shader)
20 return std::unexpected(shader.error());
21
22 result.m_applyPipeline = gpu::CreateComputePipeline(device, result.m_nest.RootSignature(), *shader);
23 if (!result.m_applyPipeline)
24 return std::unexpected("実験室の箱のパイプラインを作れない");
25
26 // --- コマンドの列(u4)と写し ---
27 constexpr uint64_t COMMAND_LIST_BYTES = uint64_t{LAB_MAX_COMMANDS_PER_TICK} * COMMAND_BYTES;
28 result.m_commands = gpu::CreateBuffer(device, COMMAND_LIST_BYTES, gpu::BufferKind::UnorderedAccess);
29 result.m_commandUpload = gpu::CreateBuffer(device, COMMAND_LIST_BYTES, gpu::BufferKind::Upload);
30 if (!result.m_commands || !result.m_commandUpload)
31 return std::unexpected("実験室の箱のバッファを作れない");
32
33 return result;
34 }
35
36 bool GpuLabBox::RecordUpload(ID3D12GraphicsCommandList10* list, const MultiresNest& nest) {
37 return m_nest.RecordUpload(list, nest);
38 }
39
40 bool GpuLabBox::RecordCommandUpload(ID3D12GraphicsCommandList10* list, std::span<const Command> commands) {
41 void* mapped = nullptr;
42 const D3D12_RANGE noRead{.Begin = 0, .End = 0};
43 if (FAILED(m_commandUpload->Map(0, &noRead, &mapped)))
44 return false;
45
46 std::memcpy(mapped, commands.data(), commands.size_bytes());
47 m_commandUpload->Unmap(0, nullptr);
48
49 // 列のバッファは COMMON から COPY_DEST へ暗黙に上がる(バッファはリストの終わりに COMMON へ戻る)
50 list->CopyBufferRegion(m_commands.Get(), 0, m_commandUpload.Get(), 0, commands.size_bytes());
51 const D3D12_RESOURCE_BARRIER toUav = gpu::Transition(m_commands.Get(), D3D12_RESOURCE_STATE_COPY_DEST,
52 D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
53 list->ResourceBarrier(1, &toUav);
54
55 return true;
56 }
57
58 bool GpuLabBox::RecordTick(ID3D12GraphicsCommandList10* list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, uint64_t tick,
59 std::span<const Command> commands) {
60 if (commands.size() > LAB_MAX_COMMANDS_PER_TICK)
61 return false;
62
63 // --- コマンドを当てる(無ければ投げない。CPU の ApplyLabCommands も何もしない)---
64 if (!commands.empty()) {
65 if (!RecordCommandUpload(list, commands))
66 return false;
67
68 const D3D12_GPU_VIRTUAL_ADDRESS commandAddress = m_commands->GetGPUVirtualAddress();
69 m_nest.SetExternalViews(commandAddress, commandAddress);
70 m_nest.RecordExternalDispatch(list, debugRing, m_applyPipeline.Get(), 1,
71 {static_cast<uint32_t>(commands.size()), LAB_BOX_SLOT, m_speciesCount, 0});
72 }
73
74 m_nest.RecordStep(list, debugRing, LAB_WORLD_SEED, tick, LAB_STEP_OPTIONS);
75
76 return true;
77 }
78
79} // namespace bicameral::sim
ComPtr< ID3D12Resource > m_commands
Definition gpu_lab_box.h:45
GpuLabBox(GpuMultires nest)
Definition gpu_lab_box.h:39
ComPtr< ID3D12Resource > m_commandUpload
Definition gpu_lab_box.h:46
bool RecordUpload(ID3D12GraphicsCommandList10 *list, const MultiresNest &nest)
ComPtr< ID3D12PipelineState > m_applyPipeline
Definition gpu_lab_box.h:44
static std::expected< GpuLabBox, std::string > Create(ID3D12Device5 *device, const BakedReactionTable &table)
bool RecordCommandUpload(ID3D12GraphicsCommandList10 *list, std::span< const Command > commands)
bool RecordTick(ID3D12GraphicsCommandList10 *list, D3D12_GPU_VIRTUAL_ADDRESS debugRing, uint64_t tick, std::span< const Command > commands)
ID3D12RootSignature * RootSignature() const
static std::expected< GpuMultires, std::string > Create(ID3D12Device5 *device, const BakedReactionTable &table, const MultiresCapacity &capacity, const GpuMultiresOptions &options={})
std::expected< std::vector< std::byte >, std::string > LoadShader(std::string_view relativePath)
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
constexpr MultiresStepOptions LAB_STEP_OPTIONS
Definition lab_box.h:36
constexpr uint32_t LAB_MAX_COMMANDS_PER_TICK
Definition lab_box.h:31
constexpr uint32_t COMMAND_BYTES
Definition command.h:16
constexpr uint64_t LAB_WORLD_SEED
Definition lab_box.h:32
MultiresCapacity LabBoxCapacity(const BakedReactionTable &table)
Definition lab_box.cpp:152
std::vector< reaction::RxSpecies > species