7 constexpr uint32_t k_workgroup_x = 8;
8 constexpr uint32_t k_workgroup_y = 8;
9 constexpr uint32_t k_workgroup_z = 4;
15 struct LatticePrefix {
26 constexpr size_t k_word3_offset = offsetof(LatticePrefix,
word3);
27 constexpr size_t k_word7_offset = offsetof(LatticePrefix,
word7);
28 constexpr size_t k_prefix_size =
sizeof(LatticePrefix);
32 std::vector<FieldBinding> bindings,
const std::string& shader_path)
34 , m_bindings(
std::move(bindings))
42 , m_bindings(
std::move(bindings))
51 =
ShaderBinding(0, entry.binding, vk::DescriptorType::eStorageBuffer);
70 if (!
m_volume->has_field(entry.field)) {
72 "VolumeFieldProcessor: volume has no field '{}' for binding '{}'",
73 entry.field, entry.name);
91 if (
m_volume->read_handle(entry.field) ==
m_volume->write_handle(entry.field)) {
93 "VolumeFieldProcessor: field '{}' is bound for both read and write "
94 "but is not double-buffered",
105 const glm::uvec3 res =
m_volume->get_lattice().resolution;
110 (res.x + k_workgroup_x - 1) / k_workgroup_x,
111 (res.y + k_workgroup_y - 1) / k_workgroup_y,
112 (res.z + k_workgroup_z - 1) / k_workgroup_z);
119 m_volume = std::dynamic_pointer_cast<VolumeGridBuffer>(buffer);
148 const glm::vec3 cell = lattice.
cell_size();
150 uint32_t preserved_3 = 0;
151 float preserved_7 = 0.0F;
152 std::memcpy(&preserved_3, data.data() + k_word3_offset,
sizeof(uint32_t));
153 std::memcpy(&preserved_7, data.data() + k_word7_offset,
sizeof(
float));
155 const LatticePrefix prefix {
159 .word3 = preserved_3,
160 .cell_size_x = cell.x,
161 .cell_size_y = cell.y,
162 .cell_size_z = cell.z,
163 .word7 = preserved_7,
166 std::memcpy(data.data(), &prefix, k_prefix_size);
172 if (data.size() < k_prefix_size) {
176 std::memcpy(data.data() + k_word3_offset, &
value,
sizeof(uint32_t));
182 if (data.size() < k_prefix_size) {
186 std::memcpy(data.data() + k_word7_offset, &
value,
sizeof(
float));
191 if (
offset < k_prefix_size) {
193 "VolumeFieldProcessor: parameter offset {} overlaps the prefix",
offset);
198 if (data.size() <
offset + size) {
199 data.resize(
offset + size);
202 std::memcpy(data.data() +
offset, data_in, size);
215 ?
m_volume->read_handle(entry.field)
216 :
m_volume->write_handle(entry.field);
218 foundry.update_descriptor_buffer(
220 handle, 0,
m_volume->get_field_bytes(entry.field));
248 const std::shared_ptr<VKBuffer>& buffer)
250 return m_volume && std::dynamic_pointer_cast<VolumeGridBuffer>(buffer) !=
nullptr;
#define MF_ERROR(comp, ctx,...)
virtual void on_attach(const std::shared_ptr< Buffer > &)
Called when this processor is attached to a buffer.
virtual void processing_function(const std::shared_ptr< Buffer > &buffer)=0
The core processing function that must be implemented by derived classes.
void set_workgroup_size(uint32_t x, uint32_t y=1, uint32_t z=1)
Set workgroup size (should match shader local_size)
void set_dispatch_mode(ShaderDispatchConfig::DispatchMode mode)
Set dispatch mode.
void set_manual_dispatch(uint32_t x, uint32_t y=1, uint32_t z=1)
Set manual dispatch group counts.
Specialized ShaderProcessor for Compute Pipelines.
const std::vector< uint8_t > & get_push_constant_data() const
Get current push constant data.
void set_push_constant_size()
Set push constant size from type.
bool are_descriptors_ready() const
Check if descriptors are initialized.
std::vector< Portal::Graphics::DescriptorSetID > m_descriptor_set_ids
void write_param_tail(size_t offset, const void *data, size_t size)
Write subclass parameters past the shared prefix.
bool validate_fields()
Check every named field exists and that read-write fields carry two slots.
void reserve_param_size(size_t size)
Raise the push constant block to at least this size.
void write_lattice_word7(float value)
Write word seven of the parameter prefix, at byte offset 28.
void size_dispatch()
Size the manual dispatch to cover the lattice.
VolumeFieldProcessor(std::vector< FieldBinding > bindings, const std::string &shader_path)
Construct from a shader path.
void processing_function(const std::shared_ptr< Buffer > &buffer) override
Rewrite field descriptors, run the shader, then swap.
void write_lattice_word3(uint32_t value)
Write word three of the shared prefix.
std::shared_ptr< VolumeGridBuffer > m_volume
The attached volume, null until on_attach validates it.
void register_bindings()
Register the binding table into m_config.bindings.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Cache and validate the volume, size the dispatch, write the shared parameter prefix,...
std::vector< std::string > m_swap_fields
bool on_before_execute(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer) override
Reject buffers that are not the validated volume.
std::vector< FieldBinding > m_bindings
void write_field_descriptors()
Issue descriptor writes for every entry in the binding table.
virtual void on_volume_ready()
Hook for subclass parameters, called at the end of on_attach.
@ READ
Resolves to VolumeGridBuffer::read_handle.
@ WRITE
Resolves to VolumeGridBuffer::write_handle.
void write_lattice_params()
Write the lattice dimensions and cell size into the staged push constant block, preserving word three...
virtual bool wants_swap() const
Whether this cycle's dispatch should be followed by a swap.
void add_swap_field(std::string field)
Register a field to swap after each dispatch.
void on_descriptors_created() override
Write every binding in the table for the current slot assignment.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
MAYAFLUX_API ShaderFoundry & get_shader_foundry()
Get the global shader compiler instance.
Describes how a VKBuffer binds to a shader descriptor.
std::unordered_map< std::string, ShaderBinding > bindings
size_t push_constant_size
@ MANUAL
Use explicit group counts.
std::string field
Field name on the attached volume.
FieldAccess access
Which slot of that field.
One shader binding and the field slot it draws from.
glm::vec3 cell_size() const noexcept
Edge length of one cell along each axis.
glm::uvec3 resolution
Cell count per axis. Zero on any axis is invalid.
A regular subdivision of an AABB3D into a cell count per axis.
Complete declarative description of a generated compute shader.