diff --git a/runtime/RHI/RHI_Definitions.h b/runtime/RHI/RHI_Definitions.h index 5434621c3..0888f8e0a 100644 --- a/runtime/RHI/RHI_Definitions.h +++ b/runtime/RHI/RHI_Definitions.h @@ -306,11 +306,12 @@ namespace Spartan } } - enum class RHI_Device_Resource + enum class RHI_Device_Bindless_Resource { - sampler_comparison, - sampler_regular, - textures_material + SamplersComparison, + SamplersRegular, + MaterialTextures, + Max }; static uint64_t rhi_hash_combine(uint64_t seed, uint64_t x) @@ -419,10 +420,10 @@ namespace Spartan // shader register slot shifts (required to produce spirv from hlsl) // 000-099 is push constant buffer range - const uint32_t rhi_shader_shift_register_u = 100; - const uint32_t rhi_shader_shift_register_b = 200; - const uint32_t rhi_shader_shift_register_t = 300; - const uint32_t rhi_shader_shift_register_s = 400; + const uint32_t rhi_shader_register_shift_u = 100; + const uint32_t rhi_shader_register_shift_b = 200; + const uint32_t rhi_shader_register_shift_t = 300; + const uint32_t rhi_shader_register_shift_s = 400; const Color rhi_color_dont_care = Color(std::numeric_limits::max(), 0.0f, 0.0f, 0.0f); const Color rhi_color_load = Color(std::numeric_limits::infinity(), 0.0f, 0.0f, 0.0f); const float rhi_depth_dont_care = std::numeric_limits::max(); diff --git a/runtime/RHI/RHI_DescriptorSetLayout.cpp b/runtime/RHI/RHI_DescriptorSetLayout.cpp index fa31a1e60..9d635a8bc 100644 --- a/runtime/RHI/RHI_DescriptorSetLayout.cpp +++ b/runtime/RHI/RHI_DescriptorSetLayout.cpp @@ -52,7 +52,7 @@ namespace Spartan { for (RHI_Descriptor& descriptor : m_descriptors) { - if (descriptor.slot == slot + rhi_shader_shift_register_b) + if (descriptor.slot == slot + rhi_shader_register_shift_b) { descriptor.data = static_cast(constant_buffer); // needed for vkUpdateDescriptorSets() descriptor.range = constant_buffer->GetStride(); // needed for vkUpdateDescriptorSets() @@ -70,7 +70,7 @@ namespace Spartan { for (RHI_Descriptor& descriptor : m_descriptors) { - if (descriptor.slot == slot + rhi_shader_shift_register_u) + if (descriptor.slot == slot + rhi_shader_register_shift_u) { descriptor.data = static_cast(buffer); descriptor.range = buffer->GetStride(); @@ -85,7 +85,7 @@ namespace Spartan { for (RHI_Descriptor& descriptor : m_descriptors) { - if (descriptor.slot == slot + rhi_shader_shift_register_s) + if (descriptor.slot == slot + rhi_shader_register_shift_s) { descriptor.data = static_cast(sampler); @@ -104,7 +104,7 @@ namespace Spartan for (RHI_Descriptor& descriptor : m_descriptors) { bool is_storage = layout == RHI_Image_Layout::General; - uint32_t shift = is_storage ? rhi_shader_shift_register_u : rhi_shader_shift_register_t; + uint32_t shift = is_storage ? rhi_shader_register_shift_u : rhi_shader_register_shift_t; if (descriptor.slot == (slot + shift)) { diff --git a/runtime/RHI/RHI_Device.h b/runtime/RHI/RHI_Device.h index f8f0af9a5..cb80571a0 100644 --- a/runtime/RHI/RHI_Device.h +++ b/runtime/RHI/RHI_Device.h @@ -49,8 +49,8 @@ namespace Spartan static void CreateDescriptorPool(); static void AllocateDescriptorSet(void*& resource, RHI_DescriptorSetLayout* descriptor_set_layout, const std::vector& descriptors); static std::unordered_map& GetDescriptorSets(); - static void* GetDescriptorSet(const RHI_Device_Resource resource_type); - static void* GetDescriptorSetLayout(const RHI_Device_Resource resource_type); + static void* GetDescriptorSet(const RHI_Device_Bindless_Resource resource_type); + static void* GetDescriptorSetLayout(const RHI_Device_Bindless_Resource resource_type); static void UpdateBindlessResources(const std::array, static_cast(Renderer_Sampler::Max)>* samplers, std::array* textures); // pipelines diff --git a/runtime/RHI/Vulkan/Vulkan_CommandList.cpp b/runtime/RHI/Vulkan/Vulkan_CommandList.cpp index ba0dcdf60..fd891a3b1 100644 --- a/runtime/RHI/Vulkan/Vulkan_CommandList.cpp +++ b/runtime/RHI/Vulkan/Vulkan_CommandList.cpp @@ -308,9 +308,9 @@ namespace Spartan { array resources = { - RHI_Device::GetDescriptorSet(RHI_Device_Resource::textures_material), - RHI_Device::GetDescriptorSet(RHI_Device_Resource::sampler_comparison), - RHI_Device::GetDescriptorSet(RHI_Device_Resource::sampler_regular) + RHI_Device::GetDescriptorSet(RHI_Device_Bindless_Resource::MaterialTextures), + RHI_Device::GetDescriptorSet(RHI_Device_Bindless_Resource::SamplersComparison), + RHI_Device::GetDescriptorSet(RHI_Device_Bindless_Resource::SamplersRegular) }; VkPipelineBindPoint bind_point = pso.IsCompute() ? VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_COMPUTE : VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS; diff --git a/runtime/RHI/Vulkan/Vulkan_Device.cpp b/runtime/RHI/Vulkan/Vulkan_Device.cpp index d40b0a535..cb16d9109 100644 --- a/runtime/RHI/Vulkan/Vulkan_Device.cpp +++ b/runtime/RHI/Vulkan/Vulkan_Device.cpp @@ -424,6 +424,10 @@ namespace Spartan // legit but they spam every frame { + // buffer update + if (p_callback_data->messageIdNumber == 0x376bc9df) + return VK_FALSE; + // present related, they happen without the renderer doing anything, imgui presenting is enough if (p_callback_data->messageIdNumber == 0xe17ab4ae || p_callback_data->messageIdNumber == 0x42f2f4ed) return VK_FALSE; @@ -897,14 +901,14 @@ namespace Spartan namespace bindless { - array sets; - array layouts; + array(RHI_Device_Bindless_Resource::Max)> sets; + array(RHI_Device_Bindless_Resource::Max)> layouts; - void create_layout(const RHI_Device_Resource resource_type, const uint32_t binding, const uint32_t resource_count, const string& debug_name) + void create_layout(const RHI_Device_Bindless_Resource resource_type, const uint32_t binding, const uint32_t resource_count, const string& debug_name) { VkDescriptorSetLayoutBinding layout_binding = {}; layout_binding.binding = binding; - layout_binding.descriptorType = resource_type == RHI_Device_Resource::textures_material ? VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE : VK_DESCRIPTOR_TYPE_SAMPLER; + layout_binding.descriptorType = resource_type == RHI_Device_Bindless_Resource::MaterialTextures ? VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE : VK_DESCRIPTOR_TYPE_SAMPLER; layout_binding.descriptorCount = rhi_max_array_size; layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT; layout_binding.pImmutableSamplers = nullptr; @@ -928,7 +932,7 @@ namespace Spartan RHI_Device::SetResourceName(static_cast(*layout), RHI_Resource_Type::DescriptorSetLayout, debug_name); } - void create_set(const RHI_Device_Resource resource_type, const uint32_t resource_count, const string& debug_name) + void create_set(const RHI_Device_Bindless_Resource resource_type, const uint32_t resource_count, const string& debug_name) { // allocate descriptor set with actual descriptor count VkDescriptorSetVariableDescriptorCountAllocateInfoEXT real_descriptor_count_info = {}; @@ -950,84 +954,69 @@ namespace Spartan RHI_Device::SetResourceName(static_cast(*descriptor_set), RHI_Resource_Type::DescriptorSet, debug_name); } - void update_samplers(const vector>& samplers, const uint32_t binding_slot, const RHI_Device_Resource resource_type) + void update(const void* data, const uint32_t count, const uint32_t slot, const RHI_Device_Bindless_Resource type, const string& name) { - uint32_t sampler_count = static_cast(samplers.size()); - uint32_t binding = rhi_shader_shift_register_s + binding_slot; - - // create layout and set (if needed) - if (layouts[static_cast(resource_type)] == nullptr) - { - string debug_name = resource_type == RHI_Device_Resource::sampler_comparison ? "samplers_comparison" : "samplers_regular"; - - create_layout(resource_type, binding, sampler_count, debug_name); - create_set(resource_type, sampler_count, debug_name); + // deduce binding from slot (HLSL register style) + uint32_t binding = 0; + if (type == RHI_Device_Bindless_Resource::MaterialTextures) + { + binding = rhi_shader_register_shift_t + slot; } - - // update + else { - vector image_infos(sampler_count); - for (uint32_t i = 0; i < sampler_count; i++) - { - image_infos[i].sampler = static_cast(samplers[i]->GetRhiResource()); - image_infos[i].imageView = nullptr; - image_infos[i].imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - } - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = sets[static_cast(resource_type)]; - descriptor_write.dstBinding = binding; - descriptor_write.dstArrayElement = 0; // starting element in that array - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - descriptor_write.descriptorCount = sampler_count; - descriptor_write.pImageInfo = image_infos.data(); - - vkUpdateDescriptorSets(RHI_Context::device, 1, &descriptor_write, 0, nullptr); + binding = rhi_shader_register_shift_s + slot; } - } - - void update_textures(const array* textures, const uint32_t binding_slot) - { - uint32_t texture_count = static_cast(textures->size()); - uint32_t binding = rhi_shader_shift_register_t + binding_slot; - // create layout and set (if needed) - if (layouts[static_cast(RHI_Device_Resource::textures_material)] == nullptr) + // create layout and and layout set (if needed) + if (layouts[static_cast(type)] == nullptr) { - string debug_name = "textures_material"; - - create_layout(RHI_Device_Resource::textures_material, binding, texture_count, debug_name); - create_set(RHI_Device_Resource::textures_material, texture_count, debug_name); + create_layout(type, binding, count, name); + create_set(type, count, name); } - + // update { - vector image_infos(texture_count); - for (uint32_t i = 0; i < texture_count; ++i) + vector image_infos(count); + if (type == RHI_Device_Bindless_Resource::MaterialTextures) { - RHI_Texture* texture = (*textures)[i]; - if (!texture) - continue; - - // get texture, if unable to do so, fallback to a checkerboard texture, so we can spot it by eye - void* srv_default = Renderer::GetStandardTexture(Renderer_StandardTexture::Checkerboard)->GetRhiSrv(); - void* resource = texture ? texture->GetRhiSrv() : srv_default; + const auto* textures = static_cast*>(data); - image_infos[i].sampler = nullptr; - image_infos[i].imageView = static_cast(resource); - image_infos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + for (uint32_t i = 0; i < count; ++i) + { + RHI_Texture* texture = (*textures)[i]; + if (!texture) + continue; + + // get texture, fallback to checkerboard texture if null + void* srv_default = Renderer::GetStandardTexture(Renderer_StandardTexture::Checkerboard)->GetRhiSrv(); + void* resource = texture ? texture->GetRhiSrv() : srv_default; + + image_infos[i].sampler = nullptr; + image_infos[i].imageView = static_cast(resource); + image_infos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } } + else if (type == RHI_Device_Bindless_Resource::SamplersRegular || type == RHI_Device_Bindless_Resource::SamplersComparison) + { + const auto* samplers = static_cast*>(data); + for (uint32_t i = 0; i < count; ++i) + { + image_infos[i].sampler = static_cast(samplers[i]->GetRhiResource()); + image_infos[i].imageView = nullptr; + image_infos[i].imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + } + VkWriteDescriptorSet descriptor_write = {}; descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = sets[static_cast(RHI_Device_Resource::textures_material)]; + descriptor_write.dstSet = sets[static_cast(type)]; descriptor_write.dstBinding = binding; descriptor_write.dstArrayElement = 0; // starting element in the array - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - descriptor_write.descriptorCount = texture_count; + descriptor_write.descriptorType = type == RHI_Device_Bindless_Resource::MaterialTextures ? VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE : VK_DESCRIPTOR_TYPE_SAMPLER; + descriptor_write.descriptorCount = count; descriptor_write.pImageInfo = image_infos.data(); - + vkUpdateDescriptorSets(RHI_Context::device, 1, &descriptor_write, 0, nullptr); } } @@ -1731,12 +1720,12 @@ namespace Spartan Profiler::m_descriptor_set_count++; } - void* RHI_Device::GetDescriptorSet(const RHI_Device_Resource resource_type) + void* RHI_Device::GetDescriptorSet(const RHI_Device_Bindless_Resource resource_type) { return static_cast(descriptors::bindless::sets[static_cast(resource_type)]); } - void* RHI_Device::GetDescriptorSetLayout(const RHI_Device_Resource resource_type) + void* RHI_Device::GetDescriptorSetLayout(const RHI_Device_Bindless_Resource resource_type) { return static_cast(descriptors::bindless::layouts[static_cast(resource_type)]); } @@ -1775,10 +1764,10 @@ namespace Spartan { vector> data = { - (*samplers)[0], + (*samplers)[0], // comparison }; - descriptors::bindless::update_samplers(data, 0, RHI_Device_Resource::sampler_comparison); + descriptors::bindless::update(&data[0], static_cast(data.size()), 0, RHI_Device_Bindless_Resource::SamplersComparison, "samplers_comparison"); } // regular @@ -1795,7 +1784,7 @@ namespace Spartan (*samplers)[8] // anisotropic_wrap }; - descriptors::bindless::update_samplers(data, 1, RHI_Device_Resource::sampler_regular); + descriptors::bindless::update(&data[0], static_cast(data.size()), 1, RHI_Device_Bindless_Resource::SamplersRegular, "samplers_regular"); } } @@ -1805,20 +1794,20 @@ namespace Spartan // by the time vkCmdBindDescriptorSets runs, we can't have a null descriptor set, so make sure there is something there { - bool first_run = descriptors::bindless::sets[static_cast(RHI_Device_Resource::textures_material)] == nullptr; + bool first_run = descriptors::bindless::sets[static_cast(RHI_Device_Bindless_Resource::MaterialTextures)] == nullptr; bool no_textures = textures == nullptr; if (first_run && no_textures) { array array_dummy; array_dummy.fill(nullptr); - descriptors::bindless::update_textures(&array_dummy, binding_slot); + descriptors::bindless::update(&array_dummy[0], static_cast(array_dummy.size()), binding_slot, RHI_Device_Bindless_Resource::MaterialTextures, "material_textures"); } } if (textures) { - descriptors::bindless::update_textures(textures, binding_slot); + descriptors::bindless::update(&textures[0], rhi_max_array_size, binding_slot, RHI_Device_Bindless_Resource::MaterialTextures, "material_textures"); } } } diff --git a/runtime/RHI/Vulkan/Vulkan_Pipeline.cpp b/runtime/RHI/Vulkan/Vulkan_Pipeline.cpp index 0c7e1bf81..238ac20f1 100644 --- a/runtime/RHI/Vulkan/Vulkan_Pipeline.cpp +++ b/runtime/RHI/Vulkan/Vulkan_Pipeline.cpp @@ -90,9 +90,9 @@ namespace Spartan array layouts = { descriptor_set_layout->GetRhiResource(), - RHI_Device::GetDescriptorSetLayout(RHI_Device_Resource::textures_material), - RHI_Device::GetDescriptorSetLayout(RHI_Device_Resource::sampler_comparison), - RHI_Device::GetDescriptorSetLayout(RHI_Device_Resource::sampler_regular) + RHI_Device::GetDescriptorSetLayout(RHI_Device_Bindless_Resource::MaterialTextures), + RHI_Device::GetDescriptorSetLayout(RHI_Device_Bindless_Resource::SamplersComparison), + RHI_Device::GetDescriptorSetLayout(RHI_Device_Bindless_Resource::SamplersRegular) }; // validate descriptor set layouts diff --git a/runtime/RHI/Vulkan/Vulkan_Shader.cpp b/runtime/RHI/Vulkan/Vulkan_Shader.cpp index 3fc9c7b37..f168b167a 100644 --- a/runtime/RHI/Vulkan/Vulkan_Shader.cpp +++ b/runtime/RHI/Vulkan/Vulkan_Shader.cpp @@ -118,10 +118,10 @@ namespace Spartan arguments.emplace_back("-fspv-preserve-interface"); // preserves all interface variables in the entry point, even when those variables are unused // shift registers to avoid conflicts - arguments.emplace_back("-fvk-u-shift"); arguments.emplace_back(to_string(rhi_shader_shift_register_u)); arguments.emplace_back("all"); // binding number shift for u-type (read/write buffer) register - arguments.emplace_back("-fvk-b-shift"); arguments.emplace_back(to_string(rhi_shader_shift_register_b)); arguments.emplace_back("all"); // binding number shift for b-type (buffer) register - arguments.emplace_back("-fvk-t-shift"); arguments.emplace_back(to_string(rhi_shader_shift_register_t)); arguments.emplace_back("all"); // binding number shift for t-type (texture) register - arguments.emplace_back("-fvk-s-shift"); arguments.emplace_back(to_string(rhi_shader_shift_register_s)); arguments.emplace_back("all"); // binding number shift for s-type (sampler) register + arguments.emplace_back("-fvk-u-shift"); arguments.emplace_back(to_string(rhi_shader_register_shift_u)); arguments.emplace_back("all"); // binding number shift for u-type (read/write buffer) register + arguments.emplace_back("-fvk-b-shift"); arguments.emplace_back(to_string(rhi_shader_register_shift_b)); arguments.emplace_back("all"); // binding number shift for b-type (buffer) register + arguments.emplace_back("-fvk-t-shift"); arguments.emplace_back(to_string(rhi_shader_register_shift_t)); arguments.emplace_back("all"); // binding number shift for t-type (texture) register + arguments.emplace_back("-fvk-s-shift"); arguments.emplace_back(to_string(rhi_shader_register_shift_s)); arguments.emplace_back("all"); // binding number shift for s-type (sampler) register } // directX conventions