Last active
April 28, 2025 00:05
-
-
Save gkaerts/526bc6134499599132323f4a185e997d to your computer and use it in GitHub Desktop.
Vulkan and D3D12 typed bindless resources in one shader-side API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This file should be compiled with DXC against shader model 6.6 | |
// Change the TARGET_API define here to either D3D or VK and switch compiler output formats (DXIL or SPIR-V) to match | |
#define D3D 1 | |
#define VK 2 | |
#define TARGET_API D3D | |
// Begin macro magic | |
#if TARGET_API == D3D | |
// No special root signature needed! | |
#define BINDLESS_RESOURCE_RANGE(type, vkBinding, rangeName, accessor) \ | |
type accessor(uint handle) { return ResourceDescriptorHeap[handle]; } | |
#define BINDLESS_UNIFORM_BUFFER_RANGE(type, rangeName, accessor) \ | |
type accessor(uint handle) { ConstantBuffer<type> data = ResourceDescriptorHeap[handle]; return data; } | |
#define BINDLESS_SAMPLER_RANGE(type, vkBinding, rangeName, accessor) \ | |
type accessor(uint handle) { return SamplerDescriptorHeap[handle]; } | |
#elif TARGET_API == VK | |
// These need to match with the C++ Vulkan pipeline layout code | |
#define VK_RESOURCE_DESCRIPTOR_SET_INDEX 0 | |
#define VK_SAMPLER_DESCRIPTOR_SET_INDEX 1 | |
#define VK_BINDING_UNIFORM_BUFFER 0 | |
#define VK_BINDING_SAMPLED_IMAGE 1 | |
#define VK_BINDING_STORAGE_IMAGE 2 | |
#define VK_BINDING_STORAGE_BUFFER 3 | |
#define VK_BINDING_SAMPLER 0 | |
#define BINDLESS_RESOURCE_RANGE(type, vkBinding, rangeName, accessor) [[vk::binding(vkBinding, VK_RESOURCE_DESCRIPTOR_SET_INDEX)]] type rangeName[]; \ | |
type accessor(uint handle) { return rangeName[handle]; } | |
#define BINDLESS_UNIFORM_BUFFER_RANGE(type, rangeName, accessor) [[vk::binding(VK_BINDING_UNIFORM_BUFFER, VK_RESOURCE_DESCRIPTOR_SET_INDEX)]] ConstantBuffer<type> rangeName[]; \ | |
type accessor(uint handle) { type data = rangeName[handle]; return data; } | |
#define BINDLESS_SAMPLER_RANGE(type, vkBinding, rangeName, accessor) [[vk::binding(vkBinding, VK_SAMPLER_DESCRIPTOR_SET_INDEX)]] type rangeName[]; \ | |
type accessor(uint handle) { return rangeName[handle]; } | |
#endif | |
// End macro magic | |
// Begin shader code | |
struct MyConstants | |
{ | |
float4 foo; | |
}; | |
struct Vertex | |
{ | |
float4 position; | |
float2 uv; | |
}; | |
// This should technically work, but it currently crashes the SPIR-V codegen path at the time of writing (04/29/2022) | |
// BINDLESS_RESOURCE_RANGE(ConstantBuffer<MyConstants>, VK_BINDING_UNIFORM_BUFFER, bindless_my_constant_buffers, get_my_constants) | |
BINDLESS_UNIFORM_BUFFER_RANGE(MyConstants, bindless_my_constants, get_my_constants) | |
BINDLESS_RESOURCE_RANGE(Texture2D<float4>, VK_BINDING_SAMPLED_IMAGE, bindless_2d_textures, get_2d_texture) | |
BINDLESS_RESOURCE_RANGE(Texture3D<float4>, VK_BINDING_SAMPLED_IMAGE, bindless_3d_textures, get_3d_texture) | |
BINDLESS_RESOURCE_RANGE(ByteAddressBuffer, VK_BINDING_STORAGE_BUFFER, bindless_raw_buffers, get_raw_buffer) | |
BINDLESS_RESOURCE_RANGE(StructuredBuffer<Vertex>, VK_BINDING_STORAGE_BUFFER, bindless_vertex_buffers, get_vertex_buffer) | |
BINDLESS_SAMPLER_RANGE(SamplerState, VK_BINDING_SAMPLER, bindless_samplers, get_sampler) | |
struct PSInput | |
{ | |
float2 uv : TEXCOORD0; | |
}; | |
float4 PSMain(PSInput input) : SV_TARGET | |
{ | |
// See above as to why this is currently broken | |
// ConstantBuffer<MyConstants> constants = get_my_constants(0) | |
MyConstants constants = get_my_constants(0); | |
SamplerState sampler = get_sampler(0); | |
Texture2D<float4> texture = get_2d_texture(0); | |
return constants.foo * texture.SampleLevel(sampler, input.uv, 0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment