MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TextureLoom.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <vulkan/vulkan.hpp>
4
5#include "GraphicsUtils.hpp"
6
7namespace MayaFlux::Core {
8class VulkanBackend;
9class VKImage;
10class BackendResourceManager;
11}
12
14
15/**
16 * @struct SamplerConfig
17 * @brief Sampler configuration
18 */
28
29/**
30 * @class TextureLoom
31 * @brief Portal-level texture creation and management
32 *
33 * TextureLoom is the primary Portal::Graphics class for creating and
34 * managing GPU textures. It bridges between user-friendly Portal API and
35 * backend VKImage resources via BufferService registry.
36 *
37 * Key Responsibilities:
38 * - Create textures (2D, 3D, cubemaps, render targets)
39 * - Load textures from files (delegates to IO namespace)
40 * - Manage sampler objects (filtering, addressing)
41 * - Track texture lifecycle for cleanup
42 * - Provide convenient format conversions
43 *
44 * Design Philosophy:
45 * - Manages creation, NOT rendering (that's Pipeline/RenderPass)
46 * - Returns VKImage directly (no wrapping yet)
47 * - Simple, focused API (file loading deferred to IO)
48 * - Integrates with BufferService for backend independence
49 *
50 * Usage:
51 * auto& mgr = Portal::Graphics::TextureLoom::instance();
52 *
53 * // Create basic texture
54 * auto texture = mgr.create_2d(512, 512, ImageFormat::RGBA8);
55 *
56 * // Create with data
57 * std::vector<uint8_t> pixels = {...};
58 * auto texture = mgr.create_2d(512, 512, ImageFormat::RGBA8, pixels.data());
59 *
60 * // Create render target
61 * auto target = mgr.create_render_target(1920, 1080);
62 *
63 * // Get sampler
64 * SamplerConfig config;
65 * config.mag_filter = FilterMode::LINEAR;
66 * auto sampler = mgr.get_or_create_sampler(config);
67 */
68class MAYAFLUX_API TextureLoom {
69public:
71 {
72 static TextureLoom manager;
73 return manager;
74 }
75
76 // Non-copyable, movable
77 TextureLoom(const TextureLoom&) = delete;
79 TextureLoom(TextureLoom&&) noexcept = default;
80 TextureLoom& operator=(TextureLoom&&) noexcept = default;
81
82 /**
83 * @brief Initialize texture manager
84 * @param backend Shared pointer to VulkanBackend
85 * @return True if initialization succeeded
86 *
87 * Queries BufferService from BackendRegistry.
88 * Must be called before creating any textures.
89 */
90 bool initialize(const std::shared_ptr<Core::VulkanBackend>& backend);
91
92 /**
93 * @brief Shutdown and cleanup all textures
94 *
95 * Destroys all managed textures and samplers.
96 * Safe to call multiple times.
97 */
98 void shutdown();
99
100 /**
101 * @brief Check if manager is initialized
102 */
103 [[nodiscard]] bool is_initialized() const { return m_backend != nullptr; }
104
105 //==========================================================================
106 // Texture Creation
107 //==========================================================================
108
109 /**
110 * @brief Create a 2D texture
111 * @param width Width in pixels
112 * @param height Height in pixels
113 * @param format Image format
114 * @param data Optional initial pixel data (nullptr = empty)
115 * @param mip_levels Number of mipmap levels (1 = no mipmaps)
116 * @return Initialized VKImage ready for use
117 *
118 * Creates device-local texture optimized for shader sampling.
119 * If data provided, uploads immediately and transitions to shader read layout.
120 */
121 std::shared_ptr<Core::VKImage> create_2d(
122 uint32_t width,
123 uint32_t height,
124 ImageFormat format = ImageFormat::RGBA8,
125 const void* data = nullptr,
126 uint32_t mip_levels = 1);
127
128 /**
129 * @brief Create a 3D texture (volumetric)
130 * @param width Width in pixels
131 * @param height Height in pixels
132 * @param depth Depth in pixels
133 * @param format Image format
134 * @param data Optional initial pixel data
135 * @return Initialized VKImage
136 */
137 std::shared_ptr<Core::VKImage> create_3d(
138 uint32_t width,
139 uint32_t height,
140 uint32_t depth,
141 ImageFormat format = ImageFormat::RGBA8,
142 const void* data = nullptr);
143
144 /**
145 * @brief Create a cubemap texture
146 * @param size Cubemap face size in pixels (square)
147 * @param format Image format
148 * @param data Optional face data (6 faces in order: +X,-X,+Y,-Y,+Z,-Z)
149 * @return Initialized VKImage configured as cubemap
150 */
151 std::shared_ptr<Core::VKImage> create_cubemap(
152 uint32_t size,
153 ImageFormat format = ImageFormat::RGBA8,
154 const void* data = nullptr);
155
156 /**
157 * @brief Create a render target (color attachment)
158 * @param width Width in pixels
159 * @param height Height in pixels
160 * @param format Image format (default RGBA8)
161 * @return Initialized VKImage configured for rendering
162 *
163 * Creates image suitable for use as framebuffer color attachment.
164 * Can also be sampled in shaders after rendering.
165 */
166 std::shared_ptr<Core::VKImage> create_render_target(
167 uint32_t width,
168 uint32_t height,
169 ImageFormat format = ImageFormat::RGBA8);
170
171 /**
172 * @brief Create a depth buffer
173 * @param width Width in pixels
174 * @param height Height in pixels
175 * @param with_stencil Whether to include stencil component
176 * @return Initialized VKImage configured as depth/stencil attachment
177 */
178 std::shared_ptr<Core::VKImage> create_depth_buffer(
179 uint32_t width,
180 uint32_t height,
181 bool with_stencil = false);
182
183 /**
184 * @brief Create a storage image (compute shader read/write)
185 * @param width Width in pixels
186 * @param height Height in pixels
187 * @param format Image format
188 * @return Initialized VKImage configured for compute storage
189 */
190 std::shared_ptr<Core::VKImage> create_storage_image(
191 uint32_t width,
192 uint32_t height,
193 ImageFormat format = ImageFormat::RGBA8);
194
195 //==========================================================================
196 // Data Upload/Download
197 //==========================================================================
198
199 /**
200 * @brief Upload pixel data to an existing texture
201 * @param image Target image
202 * @param data Pixel data pointer
203 * @param size Data size in bytes
204 *
205 * Handles staging buffer, layout transitions, and cleanup.
206 * Blocks until upload completes.
207 */
208 void upload_data(
209 const std::shared_ptr<Core::VKImage>& image,
210 const void* data,
211 size_t size);
212
213 /**
214 * @brief Download pixel data from a texture
215 * @param image Source image
216 * @param data Destination buffer
217 * @param size Buffer size in bytes
218 *
219 * Handles staging buffer, layout transitions, and cleanup.
220 * Blocks until download completes.
221 */
222 void download_data(
223 const std::shared_ptr<Core::VKImage>& image,
224 void* data,
225 size_t size);
226
227 //==========================================================================
228 // Sampler Management
229 //==========================================================================
230
231 /**
232 * @brief Get or create a sampler with the given configuration
233 * @param config Sampler configuration
234 * @return Vulkan sampler handle (cached)
235 *
236 * Samplers are cached - identical configs return same sampler.
237 * Managed by TextureLoom, destroyed on shutdown.
238 */
239 vk::Sampler get_or_create_sampler(const SamplerConfig& config);
240
241 /**
242 * @brief Get a default linear sampler (for convenience)
243 */
244 vk::Sampler get_default_sampler();
245
246 /**
247 * @brief Get a default nearest sampler (for pixel-perfect sampling)
248 */
249 vk::Sampler get_nearest_sampler();
250
251 //==========================================================================
252 // Utilities
253 //==========================================================================
254
255 /**
256 * @brief Convert Portal ImageFormat to Vulkan format
257 */
258 static vk::Format to_vulkan_format(ImageFormat format);
259
260 /**
261 * @brief Get bytes per pixel for a format
262 */
263 static size_t get_bytes_per_pixel(ImageFormat format);
264
265 /**
266 * @brief Calculate image data size
267 */
268 static size_t calculate_image_size(
269 uint32_t width,
270 uint32_t height,
271 uint32_t depth,
272 ImageFormat format);
273
274private:
275 TextureLoom() = default;
277
278 std::shared_ptr<Core::VulkanBackend> m_backend;
279 Core::BackendResourceManager* m_resource_manager = nullptr;
280
281 // Managed textures (for cleanup)
282 std::vector<std::shared_ptr<Core::VKImage>> m_textures;
283
284 // Sampler cache (config hash -> sampler)
285 std::unordered_map<size_t, vk::Sampler> m_sampler_cache;
286
287 // Helper: create sampler from config
288 vk::Sampler create_sampler(const SamplerConfig& config);
289
290 // Helper: hash sampler config for caching
291 static size_t hash_sampler_config(const SamplerConfig& config);
292
293 static bool s_initialized;
294};
295
296/**
297 * @brief Get the global texture manager instance
298 * @return Reference to singleton texture manager
299 *
300 * Must call initialize() before first use.
301 * Thread-safe after initialization.
302 */
303inline MAYAFLUX_API TextureLoom& get_texture_manager()
304{
305 return TextureLoom::instance();
306}
307
308} // namespace MayaFlux::Portal::Graphics
Manages Vulkan resources (buffers, images, samplers) for the graphics backend.
TextureLoom(const TextureLoom &)=delete
std::shared_ptr< Core::VulkanBackend > m_backend
TextureLoom(TextureLoom &&) noexcept=default
TextureLoom & operator=(const TextureLoom &)=delete
std::vector< std::shared_ptr< Core::VKImage > > m_textures
std::unordered_map< size_t, vk::Sampler > m_sampler_cache
Portal-level texture creation and management.
void initialize()
Definition main.cpp:11
MAYAFLUX_API TextureLoom & get_texture_manager()
Get the global texture manager instance.
void shutdown()
Shutdown Portal::Graphics subsystem.
Definition Graphics.cpp:69
AddressMode
Texture addressing mode (wrapping)
FilterMode
Texture filtering mode.
@ LINEAR
Bilinear filtering (smooth)
ImageFormat
User-friendly image format enum.