16 vk::DescriptorType
type = vk::DescriptorType::eStorageBuffer;
27 ,
type(to_vk_descriptor_type(role))
54 std::unordered_map<std::string, ShaderBinding>
bindings;
58 std::vector<Portal::Graphics::PushConstantField>
pc_fields;
131 OUTPUT_WRITE = 1 << 1,
153 void processing_function(
const std::shared_ptr<Buffer>& buffer)
override;
154 void on_attach(
const std::shared_ptr<Buffer>& buffer)
override;
155 void on_detach(
const std::shared_ptr<Buffer>& buffer)
override;
157 [[nodiscard]]
bool is_compatible_with(
const std::shared_ptr<Buffer>& buffer)
const override;
171 void bind_buffer(
const std::string& descriptor_name,
const std::shared_ptr<VKBuffer>& buffer);
177 void unbind_buffer(
const std::string& descriptor_name);
184 [[nodiscard]] std::shared_ptr<VKBuffer> get_bound_buffer(
const std::string& descriptor_name)
const;
194 void auto_bind_buffer(
const std::shared_ptr<VKBuffer>& buffer);
205 const std::string& descriptor_name,
208 const std::shared_ptr<VKBuffer>& staging =
nullptr)
const;
210 template <
typename T>
211 bool download_bound(
const std::string& descriptor_name, std::vector<T>& data)
const
213 auto buffer = get_bound_buffer(descriptor_name);
215 MF_ERROR(Journal::Component::Buffers, Journal::Context::BufferProcessing,
216 "download_bound: no buffer bound to descriptor '{}'", descriptor_name);
234 using FeedValue = std::variant<double, Kakshya::DataVariant>;
266 void feed(
const std::string&
name,
FeedSource source, uint32_t
offset,
size_t size =
sizeof(
float));
269 void remove_feed(
const std::string&
name);
272 [[nodiscard]]
bool has_feed(
const std::string&
name)
const;
275 [[nodiscard]] std::vector<std::string> get_feed_names()
const;
288 bool hot_reload_shader();
294 void set_shader(
const std::string& shader_path);
299 [[nodiscard]]
const std::string&
get_shader_path()
const {
return m_config.shader_path; }
309 void set_push_constant_size(
size_t size);
315 template <
typename T>
318 set_push_constant_size(
sizeof(T));
328 template <
typename T>
329 void set_push_constant_data(
const T& data);
336 virtual void set_push_constant_data_raw(
const void* data,
size_t size);
355 void set_specialization_constant(uint32_t constant_id, uint32_t
value);
360 void clear_specialization_constants();
384 void add_binding(
const std::string& descriptor_name,
const ShaderBinding& binding);
395 [[nodiscard]]
virtual BufferUsageHint get_buffer_usage_hint(
const std::string& descriptor_name)
const;
402 [[nodiscard]]
virtual bool is_in_place_operation(
const std::string& descriptor_name)
const;
409 [[nodiscard]]
bool has_binding(
const std::string& descriptor_name)
const;
417 [[nodiscard]] std::vector<std::string> get_binding_names()
const;
423 [[nodiscard]]
bool are_bindings_complete()
const;
432 [[nodiscard]]
bool is_shader_loaded()
const {
return m_shader_id != Portal::Graphics::INVALID_SHADER; }
454 [[nodiscard]]
virtual std::shared_ptr<VKBuffer>
get_output_buffer()
const {
return m_last_processed_buffer; }
465 void set_deferred_submission(
bool deferred);
473 return m_pending_fence != Portal::Graphics::INVALID_FENCE;
486 bool resolve_pending_dispatch(
bool block);
494 return m_last_command_buffer != Portal::Graphics::INVALID_COMMAND_BUFFER;
502 [[nodiscard]]
size_t resolve_push_constant_size(
const std::shared_ptr<VKBuffer>& buffer)
const;
508 [[nodiscard]] std::vector<uint8_t> resolve_push_constants(
const std::shared_ptr<VKBuffer>& buffer)
const;
529 virtual void on_before_compile(
const std::string& shader_path);
560 virtual void on_before_descriptors_create();
567 virtual void on_descriptors_created();
597 virtual void on_dispatch_complete(
const std::shared_ptr<VKBuffer>& buffer);
620 [[nodiscard]] std::optional<uint32_t> resolve_ds_index(uint32_t set)
const;
635 bool m_deferred_submission {};
641 bool m_initialized {};
642 bool m_needs_pipeline_rebuild =
true;
643 bool m_needs_descriptor_rebuild =
true;
645 size_t m_auto_bind_index {};
659 bool m_engine_owns_set_zero {};
665 virtual void update_descriptors(
const std::shared_ptr<VKBuffer>& buffer);
666 virtual void cleanup();
684 bool mismatch_logged {};
687 std::unordered_map<std::string, Feed>
m_feeds;
689 void initialize_shader();
695 const auto size =
sizeof(T);
696 static_assert(size <= 128,
"Push constants typically limited to 128 bytes");
#define MF_ERROR(comp, ctx,...)
virtual void initialize_pipeline(const std::shared_ptr< VKBuffer > &buffer)=0
const std::vector< uint8_t > & get_push_constant_data() const
Get current push constant data.
size_t get_bound_buffer_count() const
Get number of bound buffers.
virtual void execute_shader(const std::shared_ptr< VKBuffer > &buffer)=0
std::unordered_map< std::string, std::shared_ptr< VKBuffer > > m_bound_buffers
std::vector< uint8_t > m_push_constant_data
virtual void initialize_descriptors(const std::shared_ptr< VKBuffer > &buffer)=0
std::shared_ptr< VKBuffer > m_pending_buffer
Buffer retained for the outstanding submission.
std::vector< uint8_t > & get_push_constant_data()
bool is_deferred_submission() const
Whether this processor submits asynchronously.
const std::string & get_shader_path() const
Get current shader path.
void set_push_constant_size()
Set push constant size from type.
const ShaderConfig & get_config() const
Get current configuration.
virtual bool has_executed() const
Check if compute has been executed at least once.
void set_push_constant_data(const T &data)
Update push constant data (type-safe)
bool are_descriptors_ready() const
Check if descriptors are initialized.
std::shared_ptr< VKBuffer > m_last_processed_buffer
std::variant< double, Kakshya::DataVariant > FeedValue
What a feed callable returns.
bool is_shader_loaded() const
Check if shader is loaded.
virtual std::shared_ptr< VKBuffer > get_output_buffer() const
Get the output buffer after compute dispatch.
BufferUsageHint
Get buffer usage characteristics needed for safe data flow.
virtual void on_before_pipeline_create(Portal::Graphics::ComputePipelineID pipeline_id)
Called before pipeline creation.
bool is_dispatch_pending() const
True while an asynchronous submission is outstanding.
std::unordered_map< std::string, Feed > m_feeds
std::function< FeedValue()> FeedSource
A callable pulled once per processing cycle.
bool download_bound(const std::string &descriptor_name, std::vector< T > &data) const
std::vector< Portal::Graphics::DescriptorSetID > m_descriptor_set_ids
Abstract base class for shader-based buffer processing.
void download_from_gpu(const std::shared_ptr< VKBuffer > &source, void *data, size_t size, const std::shared_ptr< VKBuffer > &staging)
Download from GPU buffer to raw data (auto-detects host-visible vs device-local)
uint64_t ComputePipelineID
constexpr ShaderID INVALID_SHADER
ShaderStage
User-friendly shader stage enum.
DescriptorRole
Semantic descriptor type — maps to Vulkan descriptor types internally.
@ STORAGE
Large arrays or buffers the shader may write (SSBO)
static constexpr DomainSpec Graphics
Domain constant for Graphics domain.
uint32_t binding
Binding point within set.
ShaderBinding(uint32_t s, uint32_t b, vk::DescriptorType t, uint32_t c=1)
Construct with explicit Vulkan type — internal / advanced use only.
uint32_t set
Descriptor set index.
ShaderBinding(uint32_t s, uint32_t b, Portal::Graphics::DescriptorRole role=Portal::Graphics::DescriptorRole::STORAGE, uint32_t c=1)
Construct with semantic role — preferred public API.
uint32_t count
Array count for array descriptors (default 1)
Describes how a VKBuffer binds to a shader descriptor.
ShaderConfig(const Portal::Graphics::ShaderSpec &spec)
std::string shader_path
Path to shader file.
std::unordered_map< uint32_t, uint32_t > specialization_constants
std::unordered_map< std::string, ShaderBinding > bindings
ShaderConfig(std::string path)
size_t push_constant_size
Portal::Graphics::ShaderStage stage
std::vector< Portal::Graphics::PushConstantField > pc_fields
Retained from a ShaderSpec so feeds can resolve a field name to an offset. Empty for file shaders.
Portal::Graphics::ShaderID shader_id
std::string descriptor_name
std::shared_ptr< VKBuffer > buffer
One registered callable and where its result is written.
Complete declarative description of a generated compute shader.