From 67c3f4fe25e8fcfaabff552c0677f23fd3e10a4c Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 27 Apr 2020 15:41:12 +0100 Subject: [PATCH] Add support for accessing arrays of resources --- .../driver/shaders/spirv/spirv_debug.cpp | 2 +- renderdoc/driver/shaders/spirv/spirv_debug.h | 9 +- .../shaders/spirv/spirv_debug_setup.cpp | 102 ++++-- util/test/demos/vk/vk_shader_debug_zoo.cpp | 295 +++++++++++++++++- 4 files changed, 374 insertions(+), 34 deletions(-) diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.cpp b/renderdoc/driver/shaders/spirv/spirv_debug.cpp index 96048863e..c64c1075d 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug.cpp @@ -2179,7 +2179,7 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray // at setup time we stored the texture type for easy access here DebugAPIWrapper::TextureType texType = - (DebugAPIWrapper::TextureType)img.value.uv[TextureTypeVariableSlot]; + (DebugAPIWrapper::TextureType)img.value.u64v[TextureTypeVariableSlot]; ShaderVariable result; diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.h b/renderdoc/driver/shaders/spirv/spirv_debug.h index 8df30c69d..b84e8c972 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.h +++ b/renderdoc/driver/shaders/spirv/spirv_debug.h @@ -101,10 +101,11 @@ public: // this could be cleaner if ShaderVariable wasn't a very public struct, but it's not worth it so // we just reserve value slots that we know won't be used in opaque variables -static const uint32_t TextureTypeVariableSlot = 8; -static const uint32_t BufferPointerByteOffsetVariableSlot = 8; -static const uint32_t BufferPointerTypeIdVariableSlot = 9; -static const uint32_t SSBOVariableSlot = 10; +static const uint32_t ArrayVariableSlot = 8; +static const uint32_t TextureTypeVariableSlot = 9; +static const uint32_t BufferPointerByteOffsetVariableSlot = 9; +static const uint32_t BufferPointerTypeIdVariableSlot = 10; +static const uint32_t SSBOVariableSlot = 11; typedef ShaderVariable (*ExtInstImpl)(ThreadState &, uint32_t, const rdcarray &); diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp index 0cbb7bdd9..c05405e10 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp @@ -406,7 +406,8 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader for(const rdcstr &e : extensions) { - if(e == "SPV_GOOGLE_decorate_string" || e == "SPV_GOOGLE_hlsl_functionality1") + if(e == "SPV_GOOGLE_decorate_string" || e == "SPV_GOOGLE_hlsl_functionality1" || + e == "SPV_EXT_descriptor_indexing") { // supported extensions } @@ -514,19 +515,22 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader // global variables should all be pointers into opaque storage RDCASSERT(type.type == DataType::PointerType); - const DataType &innertype = dataTypes[type.InnerType()]; + const DataType *innertype = &dataTypes[type.InnerType()]; if(sourceName == var.name) - sourceName = GetHumanName(innertype.id); + sourceName = GetHumanName(innertype->id); + + bool isArray = false; + if(innertype->type == DataType::ArrayType) + { + isArray = true; + innertype = &dataTypes[innertype->InnerType()]; + } const bool ssbo = (v.storage == StorageClass::StorageBuffer) || - (decorations[innertype.id].flags & Decorations::BufferBlock); + (decorations[innertype->id].flags & Decorations::BufferBlock); - if(innertype.type == DataType::ArrayType) - { - RDCERR("uniform Arrays not supported yet"); - } - else if(innertype.type == DataType::StructType) + if(innertype->type == DataType::StructType) { // if we don't have a good human name, generate a better one using the interface information // we have @@ -566,11 +570,13 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader if(decorations[v.id].flags & Decorations::HasBinding) bind = decorations[v.id].binding; - // TODO handle arrays var.SetBinding((int32_t)set, (int32_t)bind, 0U); var.value.u64v[SSBOVariableSlot] = 1; + if(isArray) + var.value.u64v[ArrayVariableSlot] = 1; + sourceVar.type = VarType::ReadWriteResource; sourceVar.rows = 1; sourceVar.columns = 1; @@ -583,7 +589,10 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader else { uint32_t offset = 0; - AllocateVariable(d, d, DebugVariableType::Constant, sourceName, 0, innertype, var); + AllocateVariable(d, d, DebugVariableType::Constant, sourceName, 0, *innertype, var); + + if(isArray) + RDCERR("Uniform buffer arrays not supported yet"); sourceVar.type = VarType::ConstantBlock; sourceVar.rows = 0; @@ -598,7 +607,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader } else { - RDCERR("Unhandled type of uniform: %u", innertype.type); + RDCERR("Unhandled type of uniform: %u", innertype->type); } } else if(v.storage == StorageClass::UniformConstant) @@ -616,18 +625,18 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader // global variables should all be pointers into opaque storage RDCASSERT(type.type == DataType::PointerType); - const DataType &innertype = dataTypes[type.InnerType()]; + const DataType *innertype = &dataTypes[type.InnerType()]; // if we don't have a good human name, generate a better one using the interface information // we have if(sourceName == var.name) { rdcstr innerName; - if(innertype.type == DataType::SamplerType) + if(innertype->type == DataType::SamplerType) innerName = "sampler"; - else if(innertype.type == DataType::SampledImageType) + else if(innertype->type == DataType::SampledImageType) innerName = "sampledImage"; - else if(innertype.type == DataType::ImageType) + else if(innertype->type == DataType::ImageType) innerName = "image"; sourceName = StringFormat::Fmt("_%s_set%u_bind%u", innerName.c_str(), decorations[v.id].set, decorations[v.id].binding); @@ -641,10 +650,15 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader if(decorations[v.id].flags & Decorations::HasBinding) bind = decorations[v.id].binding; - // TODO handle arrays var.SetBinding((int32_t)set, (int32_t)bind, 0U); - if(innertype.type == DataType::SamplerType) + if(innertype->type == DataType::ArrayType) + { + var.value.u64v[ArrayVariableSlot] = 1; + innertype = &dataTypes[innertype->InnerType()]; + } + + if(innertype->type == DataType::SamplerType) { var.type = VarType::Sampler; debugType = DebugVariableType::Sampler; @@ -652,7 +666,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader global.samplers.push_back(var); samplerIDs.push_back(v.id); } - else if(innertype.type == DataType::SampledImageType || innertype.type == DataType::ImageType) + else if(innertype->type == DataType::SampledImageType || innertype->type == DataType::ImageType) { var.type = VarType::ReadOnlyResource; debugType = DebugVariableType::ReadOnlyResource; @@ -663,7 +677,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader Id imgid = type.InnerType(); - if(innertype.type == DataType::SampledImageType) + if(innertype->type == DataType::SampledImageType) imgid = sampledImageTypes[imgid].baseId; if(imageTypes[imgid].dim == Dim::Buffer) @@ -677,7 +691,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader texType |= DebugAPIWrapper::UInt_Texture; } - var.value.uv[TextureTypeVariableSlot] = texType; + var.value.u64v[TextureTypeVariableSlot] = texType; if(imageTypes[imgid].sampled == 2) { @@ -695,7 +709,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader } else { - RDCERR("Unhandled type of uniform: %u", innertype.type); + RDCERR("Unhandled type of uniform: %u", innertype->type); } SourceVariableMapping sourceVar; @@ -998,6 +1012,15 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, if(base.type == VarType::GPUPointer) leaf = (const ShaderVariable *)(uintptr_t)base.value.u64v[0]; + bool isArray = false; + + if((leaf->type == VarType::ReadWriteResource || leaf->type == VarType::ReadOnlyResource || + leaf->type == VarType::Sampler) && + leaf->value.u64v[ArrayVariableSlot]) + { + isArray = true; + } + if(leaf->type == VarType::ReadWriteResource && leaf->value.u64v[SSBOVariableSlot]) { ShaderVariable ret = MakePointerVariable(id, leaf); @@ -1011,6 +1034,14 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, // first walk any aggregate types size_t i = 0; + + // if it's an array, consume the array index first + if(isArray) + { + ret.value.u64v[ArrayVariableSlot] = indices[i++]; + type = &dataTypes[type->InnerType()]; + } + while(i < indices.size() && (type->type == DataType::ArrayType || type->type == DataType::StructType)) { @@ -1105,6 +1136,8 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, // first walk any struct member/array indices size_t i = 0; + if(isArray) + i++; while(i < indices.size() && !leaf->members.empty()) { leaf = &leaf->members[indices[i++]]; @@ -1124,7 +1157,12 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, scalar0 = indices[i]; } - return MakePointerVariable(id, leaf, scalar0, scalar1); + ShaderVariable ret = MakePointerVariable(id, leaf, scalar0, scalar1); + + if(isArray) + ret.value.u64v[ArrayVariableSlot] = indices[0]; + + return ret; } ShaderVariable Debugger::GetPointerValue(const ShaderVariable &ptr) const @@ -1135,6 +1173,9 @@ ShaderVariable Debugger::GetPointerValue(const ShaderVariable &ptr) const const ShaderVariable *inner = (const ShaderVariable *)(uintptr_t)ptr.value.u64v[0]; ShaderVariable ret = *inner; ret.name = ptr.name; + // inherit any array index from the pointer + BindpointIndex bind = ret.GetBinding(); + ret.SetBinding(bind.bindset, bind.bind, (uint32_t)ptr.value.u64v[ArrayVariableSlot]); return ret; } @@ -1159,6 +1200,8 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const BindpointIndex bind = inner->GetBinding(); + bind.arrayIndex = (uint32_t)ptr.value.u64v[ArrayVariableSlot]; + WalkVariable(dataTypes[typeId], byteOffset, ret, true, [this, bind](ShaderVariable &var, const DataType &type, uint64_t offset) { @@ -1217,6 +1260,14 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const ret = *inner; ret.name = ptr.name; + if(inner->type == VarType::ReadOnlyResource || inner->type == VarType::ReadWriteResource || + inner->type == VarType::Sampler) + { + BindpointIndex bind = ret.GetBinding(); + + ret.SetBinding(bind.bindset, bind.bind, (uint32_t)ptr.value.u64v[ArrayVariableSlot]); + } + // we don't support pointers to scalars since our 'unit' of pointer is a ShaderVariable, so check // if we have scalar indices to apply: uint32_t scalar0 = ptr.value.uv[2]; @@ -1290,7 +1341,8 @@ bool Debugger::IsOpaquePointer(const ShaderVariable &ptr) const return false; ShaderVariable *inner = (ShaderVariable *)(uintptr_t)ptr.value.u64v[0]; - return inner->type == VarType::ReadOnlyResource || inner->type == VarType::ReadWriteResource; + return inner->type == VarType::ReadOnlyResource || inner->type == VarType::Sampler || + inner->type == VarType::ReadWriteResource; } bool Debugger::ArePointersAndEqual(const ShaderVariable &a, const ShaderVariable &b) const @@ -1317,6 +1369,8 @@ void Debugger::WriteThroughPointer(const ShaderVariable &ptr, const ShaderVariab BindpointIndex bind = storage->GetBinding(); + bind.arrayIndex = (uint32_t)ptr.value.u64v[ArrayVariableSlot]; + WalkVariable(dataTypes[typeId], byteOffset, (ShaderVariable &)val, false, [this, bind](ShaderVariable &var, const DataType &type, uint64_t offset) { if(type.type == DataType::MatrixType) diff --git a/util/test/demos/vk/vk_shader_debug_zoo.cpp b/util/test/demos/vk/vk_shader_debug_zoo.cpp index 9e95b2f02..4293bf9da 100644 --- a/util/test/demos/vk/vk_shader_debug_zoo.cpp +++ b/util/test/demos/vk/vk_shader_debug_zoo.cpp @@ -101,11 +101,12 @@ void main() #version 460 core #extension GL_EXT_samplerless_texture_functions : require +#extension GL_EXT_nonuniform_qualifier : require layout(set = 0, binding = 0, std140) uniform constsbuf { vec4 first; - vec4 pad1; + uint uniformIndex; vec4 second; vec4 pad2; vec4 third; @@ -152,6 +153,30 @@ layout(set = 0, binding = 9) uniform sampler shadowSampler; layout(set = 0, binding = 20) uniform sampler2DArray queryTest; layout(set = 0, binding = 21) uniform sampler2DMSArray queryTestMS; +layout(set = 1, binding = 1) uniform sampler pointSamplers[14]; +layout(set = 1, binding = 2) uniform sampler linearSamplers[14]; + +layout(set = 1, binding = 3) uniform texture2D sampledImages[14]; + +layout(set = 1, binding = 4) uniform sampler2D linearSampledImages[14]; + +layout(set = 1, binding = 5, std430) buffer storebufstype +{ + vec4 x; + dummy y; + vec4 arr[]; +} storebufs[14]; + +layout(set = 1, binding = 6, rgba32f) uniform coherent image2D storeImages[14]; + +layout(set = 1, binding = 7) uniform samplerBuffer texBuffers[14]; +layout(set = 1, binding = 8, rgba32f) uniform coherent imageBuffer storeTexBuffers[14]; + +layout(set = 1, binding = 9) uniform sampler shadowSamplers[14]; + +layout(set = 1, binding = 20) uniform sampler2DArray queryTests[14]; +layout(set = 1, binding = 21) uniform sampler2DMSArray queryTestsMS[14]; + layout(push_constant) uniform PushData { layout(offset = 16) ivec4 data; } push; @@ -355,7 +380,7 @@ void main() case 30: { Color = cbuf.first + cbuf.second + cbuf.third + cbuf.fourth + - cbuf.pad1 + cbuf.pad2 + cbuf.pad3; + cbuf.pad2 + cbuf.pad3; break; } case 31: @@ -1097,6 +1122,130 @@ void main() Color = imageLoad(storeImage, ivec2(zeroi+1,zeroi+3)); break; } + case 134: + { + ivec2 coord = ivec2(zeroi + 20, zeroi + 20); + + Color = texelFetch(sampledImages[1], coord, 0); + break; + } + case 135: + { + vec2 coord = vec2(zerof + 0.5, zerof + 0.145); + + Color = textureLod(sampler2D(sampledImages[2], pointSamplers[3]), coord, 0.0); + break; + } + case 136: + { + vec2 coord = vec2(zerof + 0.5, zerof + 0.145); + + Color = textureLod(sampler2D(sampledImages[2], linearSamplers[3]), coord, 0.0); + break; + } + case 137: + { + Color = texture(linearSampledImages[4], inpos.xy); + break; + } + case 138: + { + ivec2 coord = ivec2(zeroi + 20, zeroi + 20); + + Color = texelFetch(sampledImages[cbuf.uniformIndex+1], coord, 0); + break; + } + case 139: + { + vec2 coord = vec2(zerof + 0.5, zerof + 0.145); + + Color = textureLod(sampler2D(sampledImages[cbuf.uniformIndex+2], pointSamplers[cbuf.uniformIndex+3]), coord, 0.0); + break; + } + case 140: + { + vec2 coord = vec2(zerof + 0.5, zerof + 0.145); + + Color = textureLod(sampler2D(sampledImages[cbuf.uniformIndex+2], linearSamplers[cbuf.uniformIndex+3]), coord, 0.0); + break; + } + case 141: + { + Color = texture(linearSampledImages[cbuf.uniformIndex+4], inpos.xy); + break; + } + case 142: + { + ivec2 coord = ivec2(zeroi + 20, zeroi + 20); + + Color = texelFetch(sampledImages[nonuniformEXT(zeroi)+9], coord, 0); + break; + } + case 143: + { + vec2 coord = vec2(zerof + 0.5, zerof + 0.145); + + Color = textureLod(sampler2D(sampledImages[nonuniformEXT(zeroi)+10], pointSamplers[nonuniformEXT(zeroi)+11]), coord, 0.0); + break; + } + case 144: + { + vec2 coord = vec2(zerof + 0.5, zerof + 0.145); + + Color = textureLod(sampler2D(sampledImages[nonuniformEXT(zeroi)+10], linearSamplers[nonuniformEXT(zeroi)+11]), coord, 0.0); + break; + } + case 145: + { + Color = texture(linearSampledImages[nonuniformEXT(zeroi)+12], inpos.xy); + break; + } + case 146: + { + Color = vec4(float(textureQueryLevels(queryTests[0])), float(textureSamples(queryTestsMS[0])), 0.0f, 1.0f); + break; + } + case 147: + { + Color = vec4(float(textureQueryLevels(queryTests[zeroi+3])), float(textureSamples(queryTestsMS[zeroi+3])), 0.0f, 1.0f); + break; + } + case 148: + { + Color = vec4(float(textureQueryLevels(queryTests[nonuniformEXT(zeroi)+5])), float(textureSamples(queryTestsMS[nonuniformEXT(zeroi)+5])), 0.0f, 1.0f); + break; + } + case 149: + { + uint len = storebufs[zeroi+7].arr.length(); + Color = vec4(float(len), float(len), float(len), float(len)); + break; + } + case 150: + { + // test storage buffer write here, we'll read from it in GLSL test 2 + storebufs[zeroi+7].x = vec4(3.1f, 4.1f, 5.9f, 2.6f); + storebufs[zeroi+7].y.val = uvec4(31, 41, 59, 26); + storebufs[zeroi+7].arr[flatData.intval - flatData.test] = vec4(inpos, inposIncreased); + + Color = storebufs[zeroi+7].x; + break; + } + case 151: + { + imageStore(storeImages[zeroi+7], ivec2(zeroi+1,zeroi+3), vec4(3.1f, 4.1f, 5.9f, 2.6f)); + Color = imageLoad(storeImages[zeroi+7], ivec2(zeroi+1,zeroi+3)); + break; + } + case 152: + { + float x = texture(sampler2DShadow(sampledImages[zeroi+5], shadowSamplers[zeroi+8]), vec3(inpos, 0.1f)); + float y = texture(sampler2DShadow(sampledImages[zeroi+5], shadowSamplers[zeroi+8]), vec3(inpos, 0.3f)); + float z = texture(sampler2DShadow(sampledImages[zeroi+5], shadowSamplers[zeroi+8]), vec3(inpos, 0.7f)); + float w = texture(sampler2DShadow(sampledImages[zeroi+5], shadowSamplers[zeroi+8]), vec3(inpos, 0.9f)); + Color = vec4(x, y, z, w); + break; + } default: break; } } @@ -1197,6 +1346,7 @@ layout(location = 0) out vec4 Color; void main() { + float zerof = float(zeroi); Color = vec4(0,0,0,0); switch(test) { @@ -1296,6 +1446,29 @@ void main() Color = dFdxFine(val).xyxy; break; } + case 15: + { + // test loading from the storage buffer (after a nice big barrier) + Color = storebufs[zeroi+7].x; + break; + } + case 16: + { + // test loading from the storage buffer (after a nice big barrier) + Color = vec4(storebufs[zeroi+7].y.val); + break; + } + case 17: + { + // test loading from the storage buffer (after a nice big barrier) + Color = storebufs[zeroi+7].arr[intval - test]; + break; + } + case 18: + { + Color = imageLoad(storeImages[zeroi+7], ivec2(zeroi+1,zeroi+3)); + break; + } default: break; } } @@ -2548,7 +2721,11 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource void Prepare(int argc, char **argv) { - optDevExts.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); + // require descriptor indexing + devExts.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); + + // dependencies of VK_EXT_descriptor_indexing + devExts.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); // we require this to pixel shader debug anyway, so we might as well require it for all tests. features.fragmentStoresAndAtomics = VK_TRUE; @@ -2570,6 +2747,47 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource // Disabled until we support these in debugging // if(supported.shaderFloat64) // features.shaderFloat64 = VK_TRUE; + + static VkPhysicalDeviceDescriptorIndexingFeaturesEXT descIndexing = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT, + }; + + getPhysFeatures2(&descIndexing); + + // enable descriptor indexing on arrays of all types + + if(!descIndexing.runtimeDescriptorArray) + Avail = "Descriptor indexing feature 'runtimeDescriptorArray' not available"; + else if(!descIndexing.shaderUniformTexelBufferArrayDynamicIndexing) + Avail = + "Descriptor indexing feature 'shaderUniformTexelBufferArrayDynamicIndexing' not " + "available"; + else if(!descIndexing.shaderStorageTexelBufferArrayDynamicIndexing) + Avail = + "Descriptor indexing feature 'shaderStorageTexelBufferArrayDynamicIndexing' not " + "available"; + else if(!descIndexing.shaderUniformBufferArrayNonUniformIndexing) + Avail = + "Descriptor indexing feature 'shaderUniformBufferArrayNonUniformIndexing' not available"; + else if(!descIndexing.shaderSampledImageArrayNonUniformIndexing) + Avail = + "Descriptor indexing feature 'shaderSampledImageArrayNonUniformIndexing' not available"; + else if(!descIndexing.shaderStorageBufferArrayNonUniformIndexing) + Avail = + "Descriptor indexing feature 'shaderStorageBufferArrayNonUniformIndexing' not available"; + else if(!descIndexing.shaderStorageImageArrayNonUniformIndexing) + Avail = + "Descriptor indexing feature 'shaderStorageImageArrayNonUniformIndexing' not available"; + else if(!descIndexing.shaderUniformTexelBufferArrayNonUniformIndexing) + Avail = + "Descriptor indexing feature 'shaderUniformTexelBufferArrayNonUniformIndexing' not " + "available"; + else if(!descIndexing.shaderStorageTexelBufferArrayNonUniformIndexing) + Avail = + "Descriptor indexing feature 'shaderStorageTexelBufferArrayNonUniformIndexing' not " + "available"; + + devInfoNext = &descIndexing; } int main() @@ -2607,8 +2825,29 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource {21, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, })); + // this set layout has arrays of each type. We'll uniformly, dynamic-uniformly, and + // non-uniformly access each of these + VkDescriptorSetLayout setlayout2 = createDescriptorSetLayout(vkh::DescriptorSetLayoutCreateInfo({ + {1, VK_DESCRIPTOR_TYPE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {2, VK_DESCRIPTOR_TYPE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {7, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {8, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {9, VK_DESCRIPTOR_TYPE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + {21, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT}, + })); + VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo( - {setlayout}, {vkh::PushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 16, sizeof(Vec4i))})); + { + setlayout, setlayout2, + }, + { + vkh::PushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 16, sizeof(Vec4i)), + })); // calculate number of tests, wrapping each row at 256 uint32_t texWidth = AlignUp(std::max(std::max(numGLSL1Tests, numGLSL2Tests), numASMTests), 256U); @@ -2793,6 +3032,7 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource vkCreateSampler(device, &sampInfo, NULL, &shadowsampler); VkDescriptorSet descset = allocateDescriptorSet(setlayout); + VkDescriptorSet descset2 = allocateDescriptorSet(setlayout2); Vec4f cbufferdata[16] = {}; @@ -2817,6 +3057,9 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource // halfPackSource - we pick exact half values to avoid rounding problems cbufferdata[11] = Vec4f(98.125f, 76.375f, 54.5625f, 32.78125f); + uint32_t index = 4; + memcpy(&cbufferdata[1], &index, sizeof(index)); + Vec4u unpack = {}; // unormUnpackSource @@ -2914,6 +3157,47 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource {vkh::DescriptorImageInfo(queryTestMSView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}), }); + for(uint32_t i = 0; i < 14; i++) + { + vkh::updateDescriptorSets( + device, + { + vkh::WriteDescriptorSet(descset2, 1, i, VK_DESCRIPTOR_TYPE_SAMPLER, + {vkh::DescriptorImageInfo( + VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED, pointsampler)}), + vkh::WriteDescriptorSet(descset2, 2, i, VK_DESCRIPTOR_TYPE_SAMPLER, + {vkh::DescriptorImageInfo( + VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED, linearsampler)}), + vkh::WriteDescriptorSet( + descset2, 3, i, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + {vkh::DescriptorImageInfo(smileyview, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_NULL_HANDLE)}), + vkh::WriteDescriptorSet( + descset2, 4, i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + {vkh::DescriptorImageInfo(smileyview, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + linearsampler)}), + vkh::WriteDescriptorSet(descset2, 5, i, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + {vkh::DescriptorBufferInfo(store_buffer.buffer)}), + vkh::WriteDescriptorSet( + descset2, 6, i, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + {vkh::DescriptorImageInfo(store_view, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE)}), + vkh::WriteDescriptorSet(descset2, 7, i, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + {bufview}), + vkh::WriteDescriptorSet(descset2, 8, i, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + {store_bufview}), + vkh::WriteDescriptorSet(descset2, 9, i, VK_DESCRIPTOR_TYPE_SAMPLER, + {vkh::DescriptorImageInfo( + VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED, shadowsampler)}), + + vkh::WriteDescriptorSet( + descset2, 20, i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + {vkh::DescriptorImageInfo(queryTestView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}), + vkh::WriteDescriptorSet( + descset2, 21, i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + {vkh::DescriptorImageInfo(queryTestMSView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}), + }); + } + while(Running()) { VkCommandBuffer cmd = GetCommandBuffer(); @@ -2978,7 +3262,8 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource Vec4i push = Vec4i(101, 103, 107, 109); - vkh::cmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, {descset}, {}); + vkh::cmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, + {descset, descset2}, {}); vkCmdPushConstants(cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, 16, sizeof(Vec4i), &push); vkCmdBeginRenderPass(cmd, vkh::RenderPassBeginInfo(renderPass, framebuffer, s,