16 const std::shared_ptr<Core::VulkanBackend>& backend,
21 "ShaderFoundry already initialized (static flag)");
27 "Cannot initialize ShaderFoundry with null backend");
33 "ShaderFoundry already initialized");
50 "ShaderFoundry initialized");
61 "Stopping ShaderFoundry - freeing command buffers...");
70 "ShaderFoundry stopped - command buffers freed");
84 "Shutting down ShaderFoundry...");
88 "{} command buffers still exist during shutdown - freeing now",
103 "ShaderFoundry shutdown complete");
111 const std::string& filepath,
112 std::optional<ShaderStage> stage,
113 const std::string& entry_point)
117 "ShaderFoundry not initialized");
124 "Using cached shader: {}", filepath);
128 std::optional<vk::ShaderStageFlagBits> vk_stage;
129 if (stage.has_value()) {
135 if (filepath.ends_with(
".spv")) {
136 if (!shader->create_from_spirv_file(
138 vk_stage.value_or(vk::ShaderStageFlagBits::eCompute),
141 "Failed to compile SPIR-V shader: {}", filepath);
145 if (!shader->create_from_glsl_file(
146 get_device(), filepath, vk_stage, entry_point,
150 "Failed to compile GLSL shader: {}", filepath);
157 "Compiled shader: {} ({})", filepath, vk::to_string(shader->get_stage()));
162 const std::string& source,
164 const std::string& entry_point)
168 "ShaderFoundry not initialized");
175 if (!shader->create_from_glsl(
180 "Failed to compile GLSL source");
185 "Compiled shader from source ({})", vk::to_string(vk_stage));
190 const std::string& source,
192 const std::string& cache_key,
193 const std::string& entry_point)
198 "Using cached shader: {}", cache_key);
212 const std::string& spirv_path,
214 const std::string& entry_point)
218 "ShaderFoundry not initialized");
225 "Using cached SPIR-V shader: {}", spirv_path);
232 if (!shader->create_from_spirv_file(
233 get_device(), spirv_path, vk_stage, entry_point,
236 "Failed to load SPIR-V shader: {}", spirv_path);
242 "Loaded SPIR-V shader: {}", spirv_path);
248 switch (shader_source.
type) {
260 "Unknown shader source type");
266 const std::string& content,
267 std::optional<ShaderStage> stage,
268 const std::string& entry_point)
272 "ShaderFoundry not initialized");
278 std::string cache_key;
288 "Using cached shader ID for: {}", cache_key);
289 return id_it->second;
292 if (!stage.has_value()) {
295 std::filesystem::path p(content);
296 std::string stem = p.stem().string();
303 if (!stage.has_value()) {
305 "Cannot auto-detect shader stage from '{}' - must specify explicitly",
311 std::shared_ptr<Core::VKShaderModule> shader_module;
313 switch (source_type) {
325 "Cannot determine shader source type");
329 if (!shader_module) {
336 state.module = shader_module;
338 state.
stage = *stage;
344 "Shader loaded: {} (ID: {}, stage: {})",
345 cache_key,
id,
static_cast<int>(*stage));
357 namespace fs = std::filesystem;
359 fs::path path(filepath);
361 if (path.is_absolute() || fs::exists(filepath)) {
365 std::vector<std::string> search_paths = {
366 Core::SHADER_BUILD_OUTPUT_DIR,
367 Core::SHADER_INSTALL_DIR,
368 Core::SHADER_SOURCE_DIR,
373 for (
const auto& search_path : search_paths) {
374 fs::path full_path = fs::path(search_path) / filepath;
375 if (fs::exists(full_path)) {
387 if (resolved_path.has_value()) {
388 std::string ext = resolved_path->extension().string();
389 std::ranges::transform(ext, ext.begin(), ::tolower);
398 if (content.size() > 1024 || content.find(
'\n') != std::string::npos) {
407 std::hash<std::string> hasher;
408 size_t hash = hasher(source + std::to_string(
static_cast<int>(stage)));
409 return "source_" + std::to_string(hash);
429 if (!it->second.filepath.empty()) {
433 if (!it->second.filepath.empty()) {
452 const auto& reflection = it->second.module->get_reflection();
455 info.
stage = it->second.stage;
459 for (
const auto& binding : reflection.bindings) {
461 .binding = binding.binding,
462 .type = binding.type,
463 .name = binding.name });
466 for (
const auto& pc : reflection.push_constants) {
468 pc_info.
offset = pc.offset;
469 pc_info.size = pc.size;
480 return it->second.
stage;
489 return it->second.entry_point;
501 std::vector<std::string> keys;
515 shader_module->cleanup(device);
524 "Cleaned up shader modules");
537 "Invalidated shader cache: {}", cache_key);
545 "Cleared shader cache");
562 "Updated shader compiler configuration");
592 vk::DescriptorType type,
602 vk::DescriptorBufferInfo buffer_info;
603 buffer_info.buffer = buffer;
604 buffer_info.offset = offset;
605 buffer_info.range = size;
607 vk::WriteDescriptorSet write;
608 write.dstSet = it->second.descriptor_set;
609 write.dstBinding = binding;
610 write.dstArrayElement = 0;
611 write.descriptorCount = 1;
612 write.descriptorType = type;
613 write.pBufferInfo = &buffer_info;
615 get_device().updateDescriptorSets(1, &write, 0,
nullptr);
621 vk::ImageView image_view,
623 vk::ImageLayout layout)
630 vk::DescriptorImageInfo image_info;
631 image_info.imageView = image_view;
632 image_info.sampler = sampler;
633 image_info.imageLayout = layout;
635 vk::WriteDescriptorSet write;
636 write.dstSet = it->second.descriptor_set;
637 write.dstBinding = binding;
638 write.dstArrayElement = 0;
639 write.descriptorCount = 1;
640 write.descriptorType = vk::DescriptorType::eCombinedImageSampler;
641 write.pImageInfo = &image_info;
643 get_device().updateDescriptorSets(1, &write, 0,
nullptr);
649 vk::ImageView image_view,
650 vk::ImageLayout layout)
657 vk::DescriptorImageInfo image_info;
658 image_info.imageView = image_view;
659 image_info.imageLayout = layout;
661 vk::WriteDescriptorSet write;
662 write.dstSet = it->second.descriptor_set;
663 write.dstBinding = binding;
664 write.dstArrayElement = 0;
665 write.descriptorCount = 1;
666 write.descriptorType = vk::DescriptorType::eStorageImage;
667 write.pImageInfo = &image_info;
669 get_device().updateDescriptorSets(1, &write, 0,
nullptr);
676 error<std::invalid_argument>(
679 std::source_location::current(),
680 "Invalid DescriptorSetID: {}", descriptor_set_id);
682 return it->second.descriptor_set;
697 "Cleaned up descriptor resources");
706 auto& cmd_manager =
m_backend->get_command_manager();
711 state.
cmd = cmd_manager.begin_single_time_commands();
720 auto& cmd_manager =
m_backend->get_command_manager();
724 vk::CommandBuffer cmd = cmd_manager.allocate_command_buffer(vk::CommandBufferLevel::eSecondary);
726 vk::CommandBufferInheritanceRenderingInfo inheritance_rendering;
727 inheritance_rendering.colorAttachmentCount = 1;
728 inheritance_rendering.pColorAttachmentFormats = &color_format;
729 inheritance_rendering.rasterizationSamples = vk::SampleCountFlagBits::e1;
731 vk::CommandBufferInheritanceInfo inheritance_info;
732 inheritance_info.pNext = &inheritance_rendering;
734 vk::CommandBufferBeginInfo begin_info;
735 begin_info.flags = vk::CommandBufferUsageFlagBits::eRenderPassContinue | vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
736 begin_info.pInheritanceInfo = &inheritance_info;
738 cmd.begin(begin_info);
747 "Began secondary command buffer (ID: {}) for dynamic rendering",
id);
756 return it->second.cmd;
768 it->second.cmd.end();
769 it->second.is_active =
false;
779 auto& cmd_manager =
m_backend->get_command_manager();
784 if (state.is_active) {
785 cmd_manager.free_command_buffer(state.cmd);
787 if (state.timestamp_pool) {
788 device.destroyQueryPool(state.timestamp_pool);
794 "Freed all command buffers");
808 auto& cmd_manager =
m_backend->get_command_manager();
810 it->second.cmd.end();
812 vk::SubmitInfo submit_info;
813 submit_info.commandBufferCount = 1;
814 submit_info.pCommandBuffers = &it->second.cmd;
817 switch (it->second.type) {
829 if (queue.submit(1, &submit_info,
nullptr) != vk::Result::eSuccess) {
831 "Failed to submit command buffer");
836 cmd_manager.free_command_buffer(it->second.cmd);
838 it->second.is_active =
false;
849 cmd_it->second.cmd.end();
853 vk::FenceCreateInfo fence_info;
858 vk::SubmitInfo submit_info;
859 submit_info.commandBufferCount = 1;
860 submit_info.pCommandBuffers = &cmd_it->second.cmd;
863 switch (cmd_it->second.type) {
875 if (queue.submit(1, &submit_info, fence_state.
fence) != vk::Result::eSuccess) {
877 "Failed to submit command buffer");
881 cmd_it->second.is_active =
false;
893 cmd_it->second.cmd.end();
897 vk::SemaphoreCreateInfo semaphore_info;
901 vk::SubmitInfo submit_info;
902 submit_info.commandBufferCount = 1;
903 submit_info.pCommandBuffers = &cmd_it->second.cmd;
904 submit_info.signalSemaphoreCount = 1;
905 submit_info.pSignalSemaphores = &semaphore_state.
semaphore;
908 switch (cmd_it->second.type) {
920 if (queue.submit(1, &submit_info,
nullptr) != vk::Result::eSuccess) {
922 "Failed to submit command buffer");
926 cmd_it->second.is_active =
false;
938 if (
get_device().waitForFences(1, &it->second.fence, VK_TRUE, UINT64_MAX) != vk::Result::eSuccess) {
940 "Failed to wait for fence: {}", fence_id);
943 it->second.signaled =
true;
948 std::vector<vk::Fence> fences;
949 for (
auto fence_id : fence_ids) {
952 fences.push_back(it->second.fence);
956 if (!fences.empty()) {
957 if (
get_device().waitForFences(
static_cast<uint32_t
>(fences.size()), fences.data(), VK_TRUE, UINT64_MAX) != vk::Result::eSuccess) {
959 "Failed to wait for fences");
964 for (
auto fence_id : fence_ids) {
967 it->second.signaled =
true;
979 if (it->second.signaled) {
983 auto result =
get_device().getFenceStatus(it->second.fence);
984 it->second.signaled = (result == vk::Result::eSuccess);
985 return it->second.signaled;
991 vk::PipelineStageFlags )
1005 return it->second.semaphore;
1014 for (
auto& [
id, state] :
m_fences) {
1016 device.destroyFence(state.fence);
1022 if (state.semaphore) {
1023 device.destroySemaphore(state.semaphore);
1029 "Cleaned up sync objects");
1039 vk::AccessFlags src_access,
1040 vk::AccessFlags dst_access,
1041 vk::PipelineStageFlags src_stage,
1042 vk::PipelineStageFlags dst_stage)
1049 vk::BufferMemoryBarrier barrier;
1050 barrier.srcAccessMask = src_access;
1051 barrier.dstAccessMask = dst_access;
1052 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1053 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1054 barrier.buffer = buffer;
1056 barrier.size = VK_WHOLE_SIZE;
1058 it->second.cmd.pipelineBarrier(
1061 vk::DependencyFlags {},
1070 vk::ImageLayout old_layout,
1071 vk::ImageLayout new_layout,
1072 vk::AccessFlags src_access,
1073 vk::AccessFlags dst_access,
1074 vk::PipelineStageFlags src_stage,
1075 vk::PipelineStageFlags dst_stage)
1082 vk::ImageMemoryBarrier barrier;
1083 barrier.srcAccessMask = src_access;
1084 barrier.dstAccessMask = dst_access;
1085 barrier.oldLayout = old_layout;
1086 barrier.newLayout = new_layout;
1087 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1088 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1089 barrier.image = image;
1090 barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
1091 barrier.subresourceRange.baseMipLevel = 0;
1092 barrier.subresourceRange.levelCount = 1;
1093 barrier.subresourceRange.baseArrayLayer = 0;
1094 barrier.subresourceRange.layerCount = 1;
1096 it->second.cmd.pipelineBarrier(
1099 vk::DependencyFlags {},
1124 if (!it->second.timestamp_pool) {
1125 vk::QueryPoolCreateInfo pool_info;
1126 pool_info.queryType = vk::QueryType::eTimestamp;
1127 pool_info.queryCount = 128;
1128 it->second.timestamp_pool =
get_device().createQueryPool(pool_info);
1131 auto query_index =
static_cast<uint32_t
>(it->second.timestamp_queries.size() * 2);
1132 it->second.timestamp_queries[label] = query_index;
1134 it->second.cmd.resetQueryPool(it->second.timestamp_pool, query_index, 2);
1135 it->second.cmd.writeTimestamp(vk::PipelineStageFlagBits::eTopOfPipe, it->second.timestamp_pool, query_index);
1145 auto query_it = it->second.timestamp_queries.find(label);
1146 if (query_it == it->second.timestamp_queries.end()) {
1150 uint32_t query_index = query_it->second;
1151 it->second.cmd.writeTimestamp(vk::PipelineStageFlagBits::eBottomOfPipe, it->second.timestamp_pool, query_index + 1);
1158 return { .
label = label, .duration_ns = 0, .valid =
false };
1161 auto query_it = it->second.timestamp_queries.find(label);
1162 if (query_it == it->second.timestamp_queries.end()) {
1163 return { .label = label, .duration_ns = 0, .valid =
false };
1166 if (!it->second.timestamp_pool) {
1167 return { .label = label, .duration_ns = 0, .valid =
false };
1170 uint32_t query_index = query_it->second;
1171 uint64_t timestamps[2];
1173 auto result =
get_device().getQueryPoolResults(
1174 it->second.timestamp_pool,
1180 vk::QueryResultFlagBits::e64 | vk::QueryResultFlagBits::eWait);
1182 if (result != vk::Result::eSuccess) {
1183 return { .label = label, .duration_ns = 0, .valid =
false };
1186 auto props =
m_backend->get_context().get_physical_device().getProperties();
1187 float timestamp_period = props.limits.timestampPeriod;
1189 auto duration_ns =
static_cast<uint64_t
>((timestamps[1] - timestamps[0]) * timestamp_period);
1191 return { .label = label, .duration_ns = duration_ns, .valid =
true };
1201 auto it = foundry.m_shaders.find(shader_id);
1202 if (it != foundry.m_shaders.end()) {
1203 return it->second.module;
1216 return vk::ShaderStageFlagBits::eCompute;
1218 return vk::ShaderStageFlagBits::eVertex;
1220 return vk::ShaderStageFlagBits::eFragment;
1222 return vk::ShaderStageFlagBits::eGeometry;
1224 return vk::ShaderStageFlagBits::eTessellationControl;
1226 return vk::ShaderStageFlagBits::eTessellationEvaluation;
1228 return vk::ShaderStageFlagBits::eCompute;
1235 if (!vk_stage.has_value()) {
1236 return std::nullopt;
1239 switch (*vk_stage) {
1240 case vk::ShaderStageFlagBits::eCompute:
1242 case vk::ShaderStageFlagBits::eVertex:
1244 case vk::ShaderStageFlagBits::eFragment:
1246 case vk::ShaderStageFlagBits::eGeometry:
1248 case vk::ShaderStageFlagBits::eTessellationControl:
1250 case vk::ShaderStageFlagBits::eTessellationEvaluation:
1253 return std::nullopt;
1263 return std::make_shared<Core::VKShaderModule>();
1268 return m_backend->get_context().get_device();
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_RT_TRACE(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
static std::optional< vk::ShaderStageFlagBits > detect_stage_from_extension(const std::string &filepath)
Auto-detect shader stage from file extension.
vk::DescriptorSet get_descriptor_set(DescriptorSetID descriptor_set_id)
Get Vulkan descriptor set handle from DescriptorSetID.
vk::Queue get_graphics_queue() const
Get Vulkan graphics queue.
void wait_for_fences(const std::vector< FenceID > &fence_ids)
Wait for multiple fences to be signaled.
static std::optional< ShaderStage > detect_stage_from_extension(const std::string &filepath)
Auto-detect shader stage from file extension.
vk::Device get_device() const
static bool s_initialized
void shutdown()
Shutdown and cleanup all ShaderFoundry resources.
std::atomic< uint64_t > m_next_fence_id
void wait_for_fence(FenceID fence_id)
Wait for fence to be signaled.
bool is_cached(const std::string &cache_key) const
Check if shader is cached.
std::shared_ptr< Core::VKShaderModule > compile(const ShaderSource &shader_source)
Compile shader from ShaderSource descriptor.
ShaderID reload_shader(const std::string &filepath)
Hot-reload shader (returns new ID)
void cleanup_sync_objects()
std::shared_ptr< Core::VKShaderModule > hot_reload(const std::string &filepath)
Hot-reload a shader from file.
std::atomic< uint64_t > m_next_shader_id
void set_config(const ShaderCompilerConfig &config)
Update compiler configuration.
void update_descriptor_storage_image(DescriptorSetID descriptor_set_id, uint32_t binding, vk::ImageView image_view, vk::ImageLayout layout=vk::ImageLayout::eGeneral)
Update descriptor set with storage image binding.
CommandBufferID begin_commands(CommandBufferType type)
Begin recording command buffer.
vk::Semaphore get_semaphore_handle(SemaphoreID semaphore_id)
Get Vulkan fence handle from FenceID.
std::shared_ptr< Core::VKShaderModule > get_vk_shader_module(ShaderID shader_id)
DetectedSourceType
Internal enum for source type detection.
vk::Queue m_transfer_queue
bool initialize(const std::shared_ptr< Core::VulkanBackend > &backend, const ShaderCompilerConfig &config={})
Initialize shader compiler.
std::unordered_map< std::string, ShaderID > m_shader_filepath_cache
DetectedSourceType detect_source_type(const std::string &content) const
std::unordered_map< FenceID, FenceState > m_fences
std::shared_ptr< Core::VKShaderModule > create_shader_module()
void cleanup_shader_modules()
void free_all_command_buffers()
Free all allocated command buffers.
void invalidate_cache(const std::string &cache_key)
Invalidate cache for specific shader.
std::atomic< uint64_t > m_next_command_id
TimestampResult get_timestamp_result(CommandBufferID cmd_id, const std::string &label)
void add_define(const std::string &name, const std::string &value="")
Add preprocessor define for shader compilation.
std::unordered_map< std::string, std::shared_ptr< Core::VKShaderModule > > m_shader_cache
static vk::ShaderStageFlagBits to_vulkan_stage(ShaderStage stage)
Convert Portal ShaderStage to Vulkan ShaderStageFlagBits.
void update_descriptor_buffer(DescriptorSetID descriptor_set_id, uint32_t binding, vk::DescriptorType type, vk::Buffer buffer, size_t offset, size_t size)
Update descriptor set with buffer binding.
vk::Queue m_graphics_queue
CommandBufferID begin_commands_with_wait(CommandBufferType type, SemaphoreID wait_semaphore, vk::PipelineStageFlags wait_stage)
Begin command buffer that waits on a semaphore.
std::optional< std::filesystem::path > resolve_shader_path(const std::string &filepath) const
void stop()
Stop active command recording and free command buffers.
std::unordered_map< DescriptorSetID, DescriptorSetState > m_descriptor_sets
std::unordered_map< CommandBufferID, CommandBufferState > m_command_buffers
ShaderCompilerConfig m_config
SemaphoreID submit_with_signal(CommandBufferID cmd_id)
Submit command buffer asynchronously, returning a semaphore.
void cleanup_descriptor_resources()
std::shared_ptr< Core::VKDescriptorManager > m_global_descriptor_manager
vk::Queue get_compute_queue() const
Get Vulkan compute queue.
FenceID submit_async(CommandBufferID cmd_id)
Submit command buffer asynchronously, returning a fence.
void update_descriptor_image(DescriptorSetID descriptor_set_id, uint32_t binding, vk::ImageView image_view, vk::Sampler sampler, vk::ImageLayout layout=vk::ImageLayout::eShaderReadOnlyOptimal)
Update descriptor set with image binding.
std::string get_shader_entry_point(ShaderID shader_id)
Get entry point name for compiled shader.
std::shared_ptr< Core::VKShaderModule > compile_from_source_cached(const std::string &source, ShaderStage stage, const std::string &cache_key, const std::string &entry_point="main")
bool end_commands(CommandBufferID cmd_id)
End recording command buffer.
bool is_initialized() const
Check if compiler is initialized.
void destroy_shader(ShaderID shader_id)
Destroy shader (cleanup internal state)
void begin_timestamp(CommandBufferID cmd_id, const std::string &label="")
void image_barrier(CommandBufferID cmd_id, vk::Image image, vk::ImageLayout old_layout, vk::ImageLayout new_layout, vk::AccessFlags src_access, vk::AccessFlags dst_access, vk::PipelineStageFlags src_stage, vk::PipelineStageFlags dst_stage)
Insert image memory barrier.
static ShaderFoundry & instance()
void submit_and_wait(CommandBufferID cmd_id)
Submit command buffer and wait for completion.
vk::CommandBuffer get_command_buffer(CommandBufferID cmd_id)
Get Vulkan command buffer handle from CommandBufferID.
vk::Queue get_transfer_queue() const
Get Vulkan transfer queue.
void add_include_directory(const std::string &directory)
Add include directory for shader compilation.
std::vector< std::string > get_cached_keys() const
Get all cached shader keys.
vk::Queue m_compute_queue
void clear_cache()
Invalidate entire shader cache.
ShaderReflectionInfo get_shader_reflection(ShaderID shader_id)
Get reflection info for compiled shader.
std::shared_ptr< Core::VKShaderModule > compile_from_source(const std::string &source, ShaderStage stage, const std::string &entry_point="main")
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.
std::atomic< uint64_t > m_next_descriptor_set_id
std::shared_ptr< Core::VKShaderModule > compile_from_file(const std::string &filepath, std::optional< ShaderStage > stage=std::nullopt, const std::string &entry_point="main")
void end_timestamp(CommandBufferID cmd_id, const std::string &label="")
std::shared_ptr< Core::VKShaderModule > compile_from_spirv(const std::string &spirv_path, ShaderStage stage, const std::string &entry_point="main")
ShaderID load_shader(const std::string &content, std::optional< ShaderStage > stage=std::nullopt, const std::string &entry_point="main")
Universal shader loader - auto-detects source type.
std::string generate_source_cache_key(const std::string &source, ShaderStage stage) const
std::shared_ptr< Core::VulkanBackend > m_backend
bool is_fence_signaled(FenceID fence_id)
Check if fence is signaled.
std::unordered_map< SemaphoreID, SemaphoreState > m_semaphores
ShaderStage get_shader_stage(ShaderID shader_id)
Get shader stage for compiled shader.
CommandBufferID begin_secondary_commands(vk::Format color_format)
Begin recording a secondary command buffer for dynamic rendering.
std::unordered_map< ShaderID, ShaderState > m_shaders
DescriptorSetID allocate_descriptor_set(vk::DescriptorSetLayout layout)
Allocate descriptor set for a pipeline.
std::atomic< uint64_t > m_next_semaphore_id
@ Rendering
GPU rendering operations (graphics pipeline, frame rendering)
@ ShaderCompilation
Shader compilation tasks (Portal::Graphics::ShaderCompiler)
@ Portal
High-level user-facing API layer.
constexpr ShaderID INVALID_SHADER
ShaderStage
User-friendly shader stage enum.
constexpr FenceID INVALID_FENCE
constexpr SemaphoreID INVALID_SEMAPHORE
constexpr CommandBufferID INVALID_COMMAND_BUFFER
Extracted push constant range from shader reflection.
bool enable_reflection
Extract descriptor bindings and metadata.
std::vector< std::string > include_directories
Paths for #include resolution.
std::unordered_map< std::string, std::string > defines
Preprocessor macros.
Configuration for shader compilation.
vk::DescriptorSet descriptor_set
std::shared_ptr< Core::VKShaderModule > std::string filepath
std::optional< std::array< uint32_t, 3 > > workgroup_size
std::vector< PushConstantRangeInfo > push_constant_ranges
std::vector< DescriptorBindingInfo > descriptor_bindings
Extracted reflection information from compiled shader.
std::string content
Shader source code or SPIR-V path.
enum MayaFlux::Portal::Graphics::ShaderSource::SourceType type
@ GLSL_FILE
Path to .comp/.vert/.frag/etc.
@ GLSL_STRING
In-memory GLSL source.
@ SPIRV_FILE
Path to .spv file.
Shader source descriptor for compilation.