Vulkan: descriptor binding without using shader reflection and using mutable descriptors

This commit is contained in:
Turánszki János
2026-01-26 18:45:12 +01:00
parent 77ea441087
commit aedea5bf18
8 changed files with 538 additions and 14107 deletions
+5 -2
View File
@@ -115,12 +115,15 @@ struct StackVector
constexpr void push_back(T&& item) { items[last++] = static_cast<T&&>(item); }
constexpr void pop_back() { if (!empty()) items[--last] = {}; }
constexpr void clear() { for (unsigned i = 0; i < count; ++i) items[i] = {}; last = 0; }
constexpr T* data() { return items; }
constexpr const T* data() const { return items; }
constexpr T* begin() { return items; }
constexpr T* end() { return items + last; }
constexpr const T& back() const { return items[last - 1]; }
constexpr T& back() { return items[0]; }
constexpr const T& front() const { return items[last - 1]; }
constexpr T& back() { return items[last - 1]; }
constexpr const T& front() const { return items[0]; }
constexpr T& front() { return items[0]; }
constexpr T& emplace_back() { push_back({}); return back(); }
constexpr const T& operator[](unsigned index) const { return items[index]; }
constexpr T& operator[](unsigned index) { return items[index]; }
};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-12
View File
@@ -345,9 +345,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\dxcapi.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\flat_hash_map.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\GLSL.std.450.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\include\spirv\unified1\spirv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\sal.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\stb_image.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\stb_image_write.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\stb_truetype.h" />
@@ -629,16 +627,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)wiPhysics_Jolt.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiRenderPath3D_PathTracing.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_1spp.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.c">
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</CompileAsWinRT>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\stb_vorbis.c">
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsWinRT>
@@ -399,12 +399,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiSDLInput.h">
<Filter>ENGINE\Input</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.h">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\include\spirv\unified1\spirv.h">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\volk.h">
<Filter>UTILITY</Filter>
</ClInclude>
@@ -1697,9 +1691,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\stb_vorbis.c">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.c">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiShaderCompiler.cpp">
<Filter>ENGINE\Graphics\API</Filter>
</ClCompile>
File diff suppressed because it is too large Load Diff
+22 -108
View File
@@ -32,80 +32,6 @@
#define vulkan_assert(cond, fname) { wilog_assert(cond, "Vulkan error: %s failed with %s (%s:%d)", fname, string_VkResult(res), relative_path(__FILE__), __LINE__); }
#define vulkan_check(call) [&]() { VkResult res = call; vulkan_assert((res >= VK_SUCCESS), extract_function_name(#call).c_str()); return res; }()
namespace wi::graphics
{
struct PSOLayoutHash
{
VkPushConstantRange push = {};
struct Item
{
bool used = true;
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D;
VkDescriptorSetLayoutBinding binding = {};
};
wi::vector<Item> items;
size_t hash = 0;
inline bool operator==(const PSOLayoutHash& other) const
{
if (hash != other.hash)
return false;
if (items.size() != other.items.size())
return false;
for (size_t i = 0; i < items.size(); ++i)
{
const Item& a = items[i];
const Item& b = other.items[i];
if (
a.used != b.used ||
a.viewType != b.viewType ||
a.binding.binding != b.binding.binding ||
a.binding.descriptorCount != b.binding.descriptorCount ||
a.binding.descriptorType != b.binding.descriptorType ||
a.binding.stageFlags != b.binding.stageFlags ||
a.binding.pImmutableSamplers != b.binding.pImmutableSamplers
)
return false;
}
return
push.offset == other.push.offset &&
push.size == other.push.size &&
push.stageFlags == other.push.stageFlags;
}
inline void embed_hash()
{
hash = 0;
for (auto& x : items)
{
wi::helper::hash_combine(hash, x.used);
wi::helper::hash_combine(hash, x.viewType);
wi::helper::hash_combine(hash, x.binding.binding);
wi::helper::hash_combine(hash, x.binding.descriptorCount);
wi::helper::hash_combine(hash, x.binding.descriptorType);
wi::helper::hash_combine(hash, x.binding.stageFlags);
}
wi::helper::hash_combine(hash, push.offset);
wi::helper::hash_combine(hash, push.size);
wi::helper::hash_combine(hash, push.stageFlags);
}
constexpr size_t get_hash() const
{
return hash;
}
};
}
namespace std
{
template <>
struct hash<wi::graphics::PSOLayoutHash>
{
constexpr size_t operator()(const wi::graphics::PSOLayoutHash& hash) const
{
return hash.get_hash();
}
};
}
namespace wi::graphics
{
class GraphicsDevice_Vulkan final : public GraphicsDevice
@@ -155,6 +81,7 @@ namespace wi::graphics
VkPhysicalDeviceRayQueryFeaturesKHR raytracing_query_features = {};
VkPhysicalDeviceFragmentShadingRateFeaturesKHR fragment_shading_rate_features = {};
VkPhysicalDeviceConditionalRenderingFeaturesEXT conditional_rendering_features = {};
VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT mutable_descriptor_features = {};
VkPhysicalDeviceDepthClipEnableFeaturesEXT depth_clip_enable_features = {};
VkPhysicalDeviceImageViewMinLodFeaturesEXT image_view_min_lod_features = {};
VkPhysicalDeviceMeshShaderFeaturesEXT mesh_shader_features = {};
@@ -196,6 +123,25 @@ namespace wi::graphics
VkImageView nullImageViewCubeArray = VK_NULL_HANDLE;
VkImageView nullImageView3D = VK_NULL_HANDLE;
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
enum DESCRIPTOR_SET
{
DESCRIPTOR_SET_BINDINGS,
DESCRIPTOR_SET_BINDLESS_STORAGE_BUFFER,
DESCRIPTOR_SET_BINDLESS_UNIFORM_TEXEL_BUFFER,
DESCRIPTOR_SET_BINDLESS_SAMPLER,
DESCRIPTOR_SET_BINDLESS_SAMPLED_IMAGE,
DESCRIPTOR_SET_BINDLESS_STORAGE_IMAGE,
DESCRIPTOR_SET_BINDLESS_STORAGE_TEXEL_BUFFER,
DESCRIPTOR_SET_BINDLESS_ACCELERATION_STRUCTURE,
DESCRIPTOR_SET_COUNT,
};
VkDescriptorSet descriptor_sets[DESCRIPTOR_SET_COUNT] = {};
VkDescriptorSetLayout descriptor_set_layouts[DESCRIPTOR_SET_COUNT] = {};
struct CommandQueue
{
VkQueue queue = VK_NULL_HANDLE;
@@ -262,17 +208,7 @@ namespace wi::graphics
{
DescriptorBindingTable table;
GraphicsDevice_Vulkan* device;
wi::vector<VkWriteDescriptorSet> descriptorWrites;
wi::vector<VkDescriptorBufferInfo> bufferInfos;
wi::vector<VkDescriptorImageInfo> imageInfos;
wi::vector<VkBufferView> texelBufferViews;
wi::vector<VkWriteDescriptorSetAccelerationStructureKHR> accelerationStructureViews;
uint32_t uniform_buffer_dynamic_offsets[DESCRIPTORBINDER_CBV_COUNT] = {};
VkDescriptorSet descriptorSet_graphics = VK_NULL_HANDLE;
VkDescriptorSet descriptorSet_compute = VK_NULL_HANDLE;
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
enum DIRTY_FLAGS
{
@@ -405,8 +341,7 @@ namespace wi::graphics
void predraw(CommandList cmd);
void predispatch(CommandList cmd);
static constexpr uint32_t immutable_sampler_slot_begin = 100;
wi::vector<VkSampler> immutable_samplers;
VkSampler immutable_samplers[10];
void set_fence_name(VkFence fence, const char* name);
void set_semaphore_name(VkSemaphore semaphore, const char* name);
@@ -897,27 +832,6 @@ namespace wi::graphics
};
wi::allocator::shared_ptr<AllocationHandler> allocationhandler;
struct PSOLayout
{
wi::allocator::shared_ptr<AllocationHandler> allocationhandler;
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
wi::vector<VkDescriptorSet> bindlessSets;
uint32_t bindlessFirstSet = 0;
~PSOLayout()
{
if (allocationhandler == nullptr)
return;
allocationhandler->destroylocker.lock();
uint64_t framecount = allocationhandler->framecount;
allocationhandler->destroyer_pipelineLayouts.push_back(std::make_pair(pipelineLayout, framecount));
allocationhandler->destroyer_descriptorSetLayouts.push_back(std::make_pair(descriptorSetLayout, framecount));
allocationhandler->destroylocker.unlock();
}
};
mutable wi::unordered_map<PSOLayoutHash, wi::allocator::shared_ptr<PSOLayout>> pso_layout_cache;
mutable std::mutex pso_layout_cache_mutex;
};
}