28 "Cannot create pipeline without shader");
36 const auto& descriptor_bindings =
buffer->get_pipeline_context().descriptor_buffer_bindings;
37 for (
const auto& binding : descriptor_bindings) {
38 unified_bindings[{ binding.set, binding.binding }] = binding;
42 auto key = std::make_pair(binding.set, binding.binding);
43 if (unified_bindings.find(key) == unified_bindings.end()) {
46 .binding = binding.binding,
54 std::map<uint32_t, std::vector<Portal::Graphics::DescriptorBindingInfo>> bindings_by_set;
55 for (
const auto& [key, binding] : unified_bindings) {
56 bindings_by_set[binding.set].push_back(binding);
59 std::vector<std::vector<Portal::Graphics::DescriptorBindingInfo>> descriptor_sets;
61 descriptor_sets.reserve(bindings_by_set.size());
62 for (
const auto& [set_index, set_bindings] : bindings_by_set) {
63 descriptor_sets.push_back(set_bindings);
74 compute_press.destroy_pipeline(previous_pipeline);
79 "Failed to create compute pipeline");
86 "Compute pipeline created (ID: {}, {} descriptor sets, {} bytes push constants)",
94 "Cannot allocate descriptor sets without pipeline");
106 "Failed to allocate descriptor sets");
142 std::function<std::array<uint32_t, 3>(
const std::shared_ptr<VKBuffer>&)> calculator)
153 case DispatchMode::MANUAL:
156 case DispatchMode::ELEMENT_COUNT: {
157 uint64_t element_count = 0;
158 const auto& dimensions =
buffer->get_dimensions();
160 if (!dimensions.empty()) {
161 element_count = dimensions[0].size;
163 element_count =
buffer->get_size_bytes() /
sizeof(float);
166 auto groups_x =
static_cast<uint32_t
>(
168 return { groups_x, 1, 1 };
171 case DispatchMode::BUFFER_SIZE: {
172 uint64_t size_bytes =
buffer->get_size_bytes();
173 auto groups_x =
static_cast<uint32_t
>(
175 return { groups_x, 1, 1 };
178 case DispatchMode::CUSTOM:
196 const std::shared_ptr<VKBuffer>&,
204 const std::shared_ptr<VKBuffer>&
buffer,
210 vk::AccessFlagBits::eShaderWrite,
211 vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
212 vk::PipelineStageFlagBits::eComputeShader,
213 vk::PipelineStageFlagBits::eComputeShader);
220 "Cannot dispatch without pipeline and descriptors");
226 "Descriptor sets not initialized");
240 auto& descriptor_bindings =
buffer->get_pipeline_context().descriptor_buffer_bindings;
241 if (!descriptor_bindings.empty()) {
242 for (
const auto& binding : descriptor_bindings) {
245 "Descriptor set index {} out of range", binding.set);
249 foundry.update_descriptor_buffer(
253 binding.buffer_info.buffer,
254 binding.buffer_info.offset,
255 binding.buffer_info.range);
269 for (uint32_t i = 0; i < iterations; ++i) {
277 compute_press.push_constants(
283 compute_press.dispatch(cmd_id, dispatch_size[0], dispatch_size[1], dispatch_size[2]);
285 if (i + 1 < iterations) {
292 foundry.buffer_barrier(
295 vk::AccessFlagBits::eShaderWrite,
296 vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
297 vk::PipelineStageFlagBits::eComputeShader,
298 vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eTransfer);
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::shared_ptr< NetworkGeometryBuffer > buffer
virtual void on_iteration_barrier(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer, uint32_t index)
Called after each iteration except the last.
std::vector< uint8_t > m_push_constant_scratch
Merged push constant block, reused across iterations.
void set_workgroup_size(uint32_t x, uint32_t y=1, uint32_t z=1)
Set workgroup size (should match shader local_size)
ShaderDispatchConfig m_dispatch_config
void initialize_descriptors(const std::shared_ptr< VKBuffer > &buffer) override
void execute_shader(const std::shared_ptr< VKBuffer > &buffer) override
ComputeProcessor(const std::string &shader_path, uint32_t workgroup_x=256)
Construct processor with shader path.
void initialize_pipeline(const std::shared_ptr< VKBuffer > &buffer) override
Portal::Graphics::ComputePipelineID m_pipeline_id
void set_iteration_count(uint32_t count)
Set how many dispatches are recorded per execute cycle.
void set_dispatch_mode(ShaderDispatchConfig::DispatchMode mode)
Set dispatch mode.
virtual bool on_iteration(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer, uint32_t index)
Called before each iteration's push constants and dispatch.
void set_manual_dispatch(uint32_t x, uint32_t y=1, uint32_t z=1)
Set manual dispatch group counts.
virtual std::array< uint32_t, 3 > calculate_dispatch_size(const std::shared_ptr< VKBuffer > &buffer)
Calculate dispatch size from buffer.
void set_custom_dispatch(std::function< std::array< uint32_t, 3 >(const std::shared_ptr< VKBuffer > &)> calculator)
Set custom dispatch calculator.
Portal::Graphics::CommandBufferID m_last_command_buffer
Portal::Graphics::ShaderID m_shader_id
virtual void on_after_execute(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer)
Called after each process callback.
virtual void on_descriptors_created()
Called after descriptor sets are created.
size_t resolve_push_constant_size(const std::shared_ptr< VKBuffer > &buffer) const
Byte width of this processor's push constant block, extended to cover any fragment staged on the buff...
virtual void update_descriptors(const std::shared_ptr< VKBuffer > &buffer)
void resolve_push_constants_into(std::vector< uint8_t > &out, const std::shared_ptr< VKBuffer > &buffer) const
resolve_push_constants() written into out, reusing its storage.
virtual bool on_before_execute(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer)
Called before each process callback.
virtual void on_pipeline_created(Portal::Graphics::ComputePipelineID pipeline_id)
Called after pipeline is created.
std::shared_ptr< VKBuffer > m_last_processed_buffer
void submit_recorded(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer)
Submit a recorded command buffer honoring the submission mode.
virtual void on_before_descriptors_create()
Called before descriptor sets are created.
void pump_feeds(bool early=true)
Pull every feed and write its result.
bool resolve_pending_dispatch(bool block)
Resolve an outstanding asynchronous submission.
std::vector< Portal::Graphics::DescriptorSetID > m_descriptor_set_ids
Abstract base class for shader-based buffer processing.
void destroy_pipeline(ComputePipelineID pipeline_id)
void buffer_barrier(CommandBufferID cmd_id, vk::Buffer buffer, vk::AccessFlags src_access, vk::AccessFlags dst_access, vk::PipelineStageFlags src_stage, vk::PipelineStageFlags dst_stage)
Insert buffer memory barrier.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
constexpr ShaderID INVALID_SHADER
MAYAFLUX_API ShaderFoundry & get_shader_foundry()
Get the global shader compiler instance.
constexpr ComputePipelineID INVALID_COMPUTE_PIPELINE
MAYAFLUX_API ComputePress & get_compute_press()
std::unordered_map< std::string, ShaderBinding > bindings
size_t push_constant_size
enum MayaFlux::Buffers::ShaderDispatchConfig::DispatchMode mode
std::function< std::array< uint32_t, 3 >(const std::shared_ptr< VKBuffer > &)> custom_calculator
@ CUSTOM
User-provided calculation function.
@ MANUAL
Use explicit group counts.
uint32_t workgroup_x
Workgroup size X (should match shader)
uint32_t iteration_count
Dispatches recorded per execute cycle.
std::array< uint32_t, 3 > workgroup_size
Complete declarative description of a generated compute shader.