MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TextureExecutionContext.hpp
Go to the documentation of this file.
1#pragma once
2
4
7
9
10namespace MayaFlux::Yantra {
11
12/**
13 * @class TextureExecutionContext
14 * @brief GpuExecutionContext specialisation for image-only compute shaders.
15 *
16 * Operates on Datum<shared_ptr<SignalSourceContainer>> where the runtime
17 * type is always TextureContainer. Bypasses channel extraction entirely:
18 * extract_inputs() returns empty channels and the input TextureContainer
19 * is uploaded to a VKImage and staged as an IMAGE_STORAGE or IMAGE_SAMPLED
20 * binding before dispatch_core runs.
21 *
22 * collect_gpu_outputs() ignores the float readback and instead wraps the
23 * output VKImage (registered at binding index 0) in a new TextureContainer
24 * via a blocking GPU->CPU download.
25 *
26 * calculate_dispatch_size() derives workgroup counts from the image
27 * dimensions stored at construction, bypassing the structure-info path
28 * which is meaningless for empty channels.
29 *
30 * Concrete texture ops subclass TextureOp (not this class directly).
31 * They call stage_input() and set_push_constants() inside
32 * on_before_gpu_dispatch(), then set_texture_backend() on the owning op.
33 */
34class MAYAFLUX_API TextureExecutionContext
35 : public GpuExecutionContext<
36 std::shared_ptr<Kakshya::SignalSourceContainer>,
37 std::shared_ptr<Kakshya::SignalSourceContainer>> {
38public:
40
41 /**
42 * @param config Shader path, workgroup size, push constant size.
43 * @param output_format Pixel format of the storage image created per dispatch.
44 */
46 GpuShaderConfig config,
48 : GpuExecutionContext(std::move(config))
49 , m_output_format(output_format)
50 {
51 }
52
53 /**
54 * @brief Stage the input TextureContainer as a VKImage for the given binding.
55 *
56 * Uploads pixel data to a new VKImage via TextureLoom and registers it as
57 * IMAGE_SAMPLED at @p binding_index. A default linear sampler from
58 * SamplerForge is used. Call from on_before_gpu_dispatch() in subclasses.
59 *
60 * @param container Source TextureContainer. Must be non-null.
61 * @param binding_index Binding slot matching the IMAGE_SAMPLED declaration.
62 */
63 void stage_input(const Kakshya::TextureContainer& container, size_t binding_index, uint32_t layer = 0)
64 {
65 auto img = container.to_image(layer);
66 auto sampler = Portal::Graphics::SamplerForge::instance().get_default_linear();
67 stage_image_sampled(binding_index, std::move(img), sampler);
68 }
69
70protected:
71 /**
72 * @brief Returns empty channels -- no numeric extraction for image shaders.
73 */
74 std::pair<std::vector<std::vector<double>>, DataStructureInfo>
75 extract_inputs(const ContainerDatum& /*input*/) override
76 {
77 return { {}, {} };
78 }
79
80 /**
81 * @brief Derives dispatch groups from stored image dimensions.
82 *
83 * Ignores total_elements and structure_info (both meaningless for image
84 * dispatch). Uses m_width and m_height set by the most recent
85 * prepare_output_image() call.
86 */
87 [[nodiscard]] std::array<uint32_t, 3> calculate_dispatch_size(
88 size_t /*total_elements*/,
89 const DataStructureInfo& /*structure_info*/) const override
90 {
91 const auto& ws = gpu_config().workgroup_size;
92 return {
93 (m_width + ws[0] - 1) / ws[0],
94 (m_height + ws[1] - 1) / ws[1],
95 1U
96 };
97 }
98
99 /**
100 * @brief Creates the output storage image and stages it at binding 0.
101 *
102 * Must be called by subclasses inside on_before_gpu_dispatch() after
103 * dimensions are known, and before the base dispatch runs.
104 *
105 * @param width Output image width in pixels.
106 * @param height Output image height in pixels.
107 */
108 void prepare_output_image(uint32_t width, uint32_t height)
109 {
110 m_width = width;
111 m_height = height;
112 auto out = Portal::Graphics::TextureLoom::instance()
113 .create_storage_image(width, height, m_output_format);
114 stage_image_storage(0, std::move(out));
115 }
116
117 /**
118 * @brief Wraps the written output image in a TextureContainer.
119 *
120 * Ignores the float readback in @p raw. Downloads the storage image at
121 * binding 0 into a new TextureContainer and returns it as a ContainerDatum.
122 */
124 const GpuChannelResult& /*raw*/,
125 const std::vector<std::vector<double>>& /*channels*/,
126 const DataStructureInfo& /*structure_info*/) override
127 {
128 auto img = get_output_image(0);
129 if (!img) {
130 error<std::runtime_error>(
131 Journal::Component::Yantra,
132 Journal::Context::BufferProcessing,
133 std::source_location::current(),
134 "TextureExecutionContext: no output image at binding 0 after dispatch");
135 }
136
137 Portal::Graphics::TextureLoom::instance().transition_layout(
138 img, vk::ImageLayout::eGeneral, vk::ImageLayout::eShaderReadOnlyOptimal);
139
140 auto container = std::make_shared<Kakshya::TextureContainer>(m_width, m_height, m_output_format);
141
142 container->from_image(img, 0);
143 return ContainerDatum { std::static_pointer_cast<Kakshya::SignalSourceContainer>(container) };
144 }
145
146private:
148 uint32_t m_width { 0 };
149 uint32_t m_height { 0 };
150};
151
152} // namespace MayaFlux::Yantra
uint32_t width
std::shared_ptr< Core::VKImage > to_image(uint32_t layer=0) const
Upload the pixel buffer to a new VKImage via TextureLoom.
SignalSourceContainer wrapping GPU texture data as addressable pixel bytes.
Type-parameterised shell over GpuDispatchCore.
void prepare_output_image(uint32_t width, uint32_t height)
Creates the output storage image and stages it at binding 0.
std::array< uint32_t, 3 > calculate_dispatch_size(size_t, const DataStructureInfo &) const override
Derives dispatch groups from stored image dimensions.
void stage_input(const Kakshya::TextureContainer &container, size_t binding_index, uint32_t layer=0)
Stage the input TextureContainer as a VKImage for the given binding.
TextureExecutionContext(GpuShaderConfig config, Portal::Graphics::ImageFormat output_format)
ContainerDatum collect_gpu_outputs(const GpuChannelResult &, const std::vector< std::vector< double > > &, const DataStructureInfo &) override
Wraps the written output image in a TextureContainer.
std::pair< std::vector< std::vector< double > >, DataStructureInfo > extract_inputs(const ContainerDatum &) override
Returns empty channels – no numeric extraction for image shaders.
GpuExecutionContext specialisation for image-only compute shaders.
ImageFormat
User-friendly image format enum.
Metadata about data structure for reconstruction.
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:24
Erased output of a GPU dispatch: reconstructed float data plus any raw auxiliary outputs keyed by bin...
Plain-data description of the compute shader to dispatch.