diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index 0e05481750..4f3c19cdc9 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -699,10 +699,13 @@ bool Pass::init_pipeline_layout() if (reflection.ubo_stage_mask & SLANG_STAGE_FRAGMENT_MASK) ubo_mask |= VK_SHADER_STAGE_FRAGMENT_BIT; - bindings.push_back({ reflection.ubo_binding, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, - ubo_mask, nullptr }); - desc_counts.push_back({ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, num_sync_indices }); + if (ubo_mask != 0) + { + bindings.push_back({ reflection.ubo_binding, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, + ubo_mask, nullptr }); + desc_counts.push_back({ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, num_sync_indices }); + } // Semantic textures. for (unsigned i = 0; i < SLANG_NUM_TEXTURE_SEMANTICS; i++) @@ -965,9 +968,12 @@ CommonResources::~CommonResources() bool Pass::init_buffers() { ubos.clear(); - for (unsigned i = 0; i < num_sync_indices; i++) - ubos.emplace_back(new Buffer(device, - memory_properties, reflection.ubo_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)); + if (reflection.ubo_stage_mask) + { + for (unsigned i = 0; i < num_sync_indices; i++) + ubos.emplace_back(new Buffer(device, + memory_properties, reflection.ubo_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)); + } return true; } @@ -1070,7 +1076,7 @@ void Pass::set_semantic_texture(VkDescriptorSet set, void Pass::build_semantic_texture_vec4(uint8_t *data, slang_texture_semantic semantic, unsigned width, unsigned height) { - if (reflection.semantic_texture_ubo_mask & (1 << semantic)) + if (data && (reflection.semantic_texture_ubo_mask & (1 << semantic))) { build_vec4( reinterpret_cast(data + reflection.semantic_textures[semantic].ubo_offset), @@ -1082,7 +1088,7 @@ void Pass::build_semantic_texture_vec4(uint8_t *data, slang_texture_semantic sem void Pass::build_semantic_vec4(uint8_t *data, slang_semantic semantic, unsigned width, unsigned height) { - if (reflection.semantic_ubo_mask & (1 << semantic)) + if (data && (reflection.semantic_ubo_mask & (1 << semantic))) { build_vec4( reinterpret_cast(data + reflection.semantics[semantic].ubo_offset), @@ -1102,7 +1108,7 @@ void Pass::build_semantic_texture(VkDescriptorSet set, uint8_t *buffer, void Pass::build_semantics(VkDescriptorSet set, uint8_t *buffer, const float *mvp, const Texture &original, const Texture &source) { - if (reflection.semantic_ubo_mask & (1u << SLANG_SEMANTIC_MVP)) + if (buffer && (reflection.semantic_ubo_mask & (1u << SLANG_SEMANTIC_MVP))) { size_t offset = reflection.semantics[SLANG_SEMANTIC_MVP].ubo_offset; if (mvp) @@ -1140,12 +1146,20 @@ void Pass::build_commands( current_framebuffer_size = size; } - uint8_t *u = static_cast(ubos[sync_index]->map()); - build_semantics(sets[sync_index], u, mvp, original, source); - ubos[sync_index]->unmap(); + if (reflection.ubo_stage_mask) + { + uint8_t *u = static_cast(ubos[sync_index]->map()); + build_semantics(sets[sync_index], u, mvp, original, source); + ubos[sync_index]->unmap(); + } + else + build_semantics(sets[sync_index], nullptr, mvp, original, source); - set_uniform_buffer(sets[sync_index], 0, - ubos[sync_index]->get_buffer(), 0, reflection.ubo_size); + if (reflection.ubo_stage_mask) + { + set_uniform_buffer(sets[sync_index], 0, + ubos[sync_index]->get_buffer(), 0, reflection.ubo_size); + } // The final pass is always executed inside // another render pass since the frontend will diff --git a/gfx/drivers_shader/slang_reflection.cpp b/gfx/drivers_shader/slang_reflection.cpp index 410acdf6ef..4165e69c4a 100644 --- a/gfx/drivers_shader/slang_reflection.cpp +++ b/gfx/drivers_shader/slang_reflection.cpp @@ -261,16 +261,11 @@ static bool slang_reflect(const Compiler &vertex_compiler, const Compiler &fragm return false; } - if (!vertex_ubo && !fragment_ubo) - { - RARCH_ERR("[slang]: No UBO is in use. This cannot be a correct shader.\n"); - return false; - } - unsigned vertex_ubo_binding = vertex_ubo ? vertex_compiler.get_decoration(vertex_ubo, spv::DecorationBinding) : -1u; unsigned fragment_ubo_binding = fragment_ubo ? fragment_compiler.get_decoration(fragment_ubo, spv::DecorationBinding) : -1u; + bool has_ubo = vertex_ubo || fragment_ubo; if (vertex_ubo_binding != -1u && fragment_ubo_binding != -1u && @@ -282,13 +277,13 @@ static bool slang_reflect(const Compiler &vertex_compiler, const Compiler &fragm unsigned ubo_binding = vertex_ubo_binding != -1u ? vertex_ubo_binding : fragment_ubo_binding; - if (ubo_binding >= SLANG_NUM_BINDINGS) + if (has_ubo && ubo_binding >= SLANG_NUM_BINDINGS) { RARCH_ERR("[slang]: Binding %u is out of range.\n", ubo_binding); return false; } - reflection->ubo_binding = ubo_binding; + reflection->ubo_binding = has_ubo ? ubo_binding : 0; reflection->ubo_stage_mask = 0; reflection->ubo_size = 0; @@ -312,7 +307,7 @@ static bool slang_reflect(const Compiler &vertex_compiler, const Compiler &fragm if (fragment_ubo && !add_active_buffer_ranges(fragment_compiler, fragment.uniform_buffers[0], reflection)) return false; - uint32_t binding_mask = 1 << ubo_binding; + uint32_t binding_mask = has_ubo ? (1 << ubo_binding) : 0; // On to textures. for (auto &texture : fragment.sampled_images)