25 std::optional<Kakshya::GpuDataFormat> resolve_state(
26 const RelaxationGridBuffer::GridConfig::Stage& stage,
27 std::string_view binding)
33 const auto* spec = std::get_if<Portal::Graphics::ShaderSpec>(&stage.shader);
38 const auto it = std::ranges::find_if(
40 [binding](
const auto& slot) { return slot.name == binding; });
42 if (it == spec->bindings.end()) {
54 size_t resolve_stride(
const RelaxationGridBuffer::GridConfig& config)
56 const auto rule = resolve_state(config.rule,
"state_in");
57 const auto emit = resolve_state(config.emit,
"cell_state");
60 error<std::invalid_argument>(
62 std::source_location::current(),
63 "GridConfig: a stage whose shader is a path must declare its state format");
67 error<std::invalid_argument>(
69 std::source_location::current(),
70 "GridConfig: rule and emit disagree on the cell format");
74 error<std::invalid_argument>(
76 std::source_location::current(),
77 "GridConfig: a three component cell strides 16 bytes in std430, declare a four component format");
92 template <
typename Processor>
94 const std::shared_ptr<Processor>& processor,
96 const std::vector<RelaxationGridBuffer::GridConfig::Constant>& constants)
98 if (constants.empty()) {
102 const size_t end =
offset + constants.size() *
sizeof(uint32_t);
103 if (processor->get_push_constant_data().size() < end) {
104 processor->set_push_constant_size(end);
107 auto& data = processor->get_push_constant_data();
108 if (data.size() < end) {
113 for (
const auto& constant : constants) {
115 at +=
sizeof(uint32_t);
123 config.
width, config.
height, resolve_stride(config),
124 config.rule.shader, config.emit.shader)
135 size_t cell_stride_bytes,
139 static_cast<size_t>(
width) *
height * sizeof(Kakshya::Vertex),
141 Kakshya::DataModality::VERTEX_POSITIONS_3D)
144 , m_cell_stride_bytes(cell_stride_bytes)
145 , m_rule_source(
std::move(rule_source))
146 , m_emit_source(
std::move(emit_source))
151 if (!buffer_service) {
152 error<std::runtime_error>(
155 std::source_location::current(),
156 "RelaxationGridBuffer requires a valid BufferService");
160 const auto usage_flags =
static_cast<uint32_t
>(
161 VkBufferUsageFlags(vk::BufferUsageFlagBits::eStorageBuffer));
162 const auto memory_flags =
static_cast<uint32_t
>(
163 VkMemoryPropertyFlags(vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent));
166 resources.back_buffers.resize(2);
168 for (uint32_t i = 0; i < 2; ++i) {
169 void* out_buffer =
nullptr;
170 void* out_memory =
nullptr;
171 void* out_mapped =
nullptr;
173 buffer_service->allocate_raw_buffer(
174 state_bytes, usage_flags, memory_flags,
true,
175 out_buffer, out_memory, out_mapped);
177 resources.back_buffers[i].buffer =
static_cast<vk::Buffer
>(
static_cast<VkBuffer
>(out_buffer));
178 resources.back_buffers[i].memory =
static_cast<vk::DeviceMemory
>(
static_cast<VkDeviceMemory
>(out_memory));
179 resources.back_buffers[i].mapped_ptr = out_mapped;
183 "RelaxationGridBuffer: {}x{} grid, {} bytes/cell, {} bytes/generation",
194 [](
const auto&
src) {
return std::make_shared<RelaxationStepProcessor>(
src); },
203 chain = std::make_shared<BufferProcessingChain>();
206 chain->set_preferred_token(token);
209 [](
const auto&
src) {
return std::make_shared<RelaxationEmitProcessor>(
src); },
218 "RelaxationGridBuffer setup_processors: step + emit attached");
237 "RelaxationGridBuffer: rendering configured");
249 auto& front = resources.back_buffers[
front_index()];
251 if (!front.mapped_ptr) {
253 "seed_state: front generation buffer has no mapped pointer");
257 std::memcpy(front.mapped_ptr, data,
size);
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
BufferProcessingChain * chain
void setup_rendering(const RenderConfig &config)
Attach a RenderProcessor drawing the emitted vertex output as ordinary untextured point geometry.
std::vector< GridConfig::Constant > m_rule_constants
Rule constants from GridConfig, written at setup_processors.
std::vector< GridConfig::Constant > m_emit_constants
Emit constants from GridConfig, written at setup_processors.
std::shared_ptr< RelaxationEmitProcessor > m_emit_processor
Emit stage, retained for parameter access.
ShaderSource m_emit_source
Either a path to a hand-written emit shader or a generated ShaderSpec.
RelaxationGridBuffer(uint32_t width, uint32_t height, size_t cell_stride_bytes, ShaderSource rule_source, ShaderSource emit_source)
Construct an unregistered double-buffered grid buffer.
void setup_processors(ProcessingToken token) override
Create and attach RelaxationStepProcessor (default processor) and RelaxationEmitProcessor (flat proce...
void seed_state(const void *data, size_t size)
Write initial state directly into the current front generation.
uint32_t get_cell_count() const
Total cell count, width * height.
std::shared_ptr< RelaxationStepProcessor > m_step_processor
Rule stage, retained for parameter access.
size_t get_state_bytes() const
Total byte size of one generation's state buffer.
size_t m_cell_stride_bytes
Size in bytes of one cell's state, fixed at construction.
uint32_t m_width
Grid width in cells.
ShaderSource m_rule_source
Either a path to a hand-written rule shader or a generated ShaderSpec.
std::variant< std::string, Portal::Graphics::ShaderSpec > ShaderSource
Either a shader file path or a generated ShaderSpec, resolved at construction time by setup_processor...
float m_extent
Emit extent applied at setup_processors.
uint32_t front_index() const
Index into m_resources.back_buffers currently holding the most recently completed generation's state.
uint32_t m_height
Grid height in cells.
float m_point_size
Emit point size applied at setup_processors.
GPU-resident, double-buffered SSBO state for synchronous local-rule systems evaluated over a fixed 2D...
void set_vertex_layout(const Kakshya::VertexLayout &layout)
Set vertex layout for this buffer.
std::shared_ptr< Buffers::BufferProcessingChain > get_processing_chain() override
Access the buffer's processing chain.
void set_default_processor(const std::shared_ptr< BufferProcessor > &processor) override
Set the buffer's default processor.
void set_processing_chain(const std::shared_ptr< BufferProcessingChain > &chain, bool force=false) override
Replace the buffer's processing chain.
void apply_render_config(const RenderConfig &config, const ShaderConfig &shader_config)
Configure the internal m_render_processor from a RenderConfig.
std::shared_ptr< RenderProcessor > m_render_processor
const VKBufferResources & get_buffer_resources() const
Get all buffer resources at once (read-only)
Vulkan-backed buffer wrapper used in processing chains.
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
@ BufferManagement
Buffer Management (Buffers::BufferManager, creating buffers)
@ Init
Engine/subsystem initialization.
@ Buffers
Buffers, Managers, processors and processing chains.
size_t gpu_data_format_bytes(GpuDataFormat fmt) noexcept
Byte size of one element of a GpuDataFormat.
@ VEC3_F64
glm::dvec3 (64-bit components)
@ VEC3_F32
glm::vec3 (32-bit components), not a sampled image format
Tendency< D, R > constant(R value)
Tendency returning a fixed value regardless of input.
BufferUsageHint
Semantic usage hint for buffer allocation and memory properties.
Push constant block for the packed-vertex emit shader.
std::vector< Constant > constants
Initial words after the stage's fixed prefix (GridExtent for a rule, EmitParams for an emit),...
Stage emit
Required. Reads "cell_state", writes packed vertices.
Stage rule
Required. Reads "state_in", writes "state_out".
float point_size
Per-point size written to the vertex scalar field.
float extent
NDC half-span the grid occupies.
Arrangement of a relaxation grid: extent, the update rule, the emit stage that draws it,...
Leading push constant fields every relaxation rule shader receives: grid width then height,...
static VertexLayout for_raw(uint32_t stride=60)
Factory: layout for raw vertex data with common attributes.
Type-neutral vertex carrying the universal 60-byte attribute layout.
PrimitiveTopology topology
std::string vertex_shader
std::string fragment_shader
Unified rendering configuration for graphics buffers.
Backend buffer management service interface.