diff --git a/qrenderdoc/Code/BufferFormatter.cpp b/qrenderdoc/Code/BufferFormatter.cpp index 68dd06cce..f8c2f9157 100644 --- a/qrenderdoc/Code/BufferFormatter.cpp +++ b/qrenderdoc/Code/BufferFormatter.cpp @@ -439,6 +439,15 @@ void BufferFormatter::EstimatePackingRules(Packing::Rules &pack, ResourceId shad Packing::Rules BufferFormatter::EstimatePackingRules(ResourceId shader, const rdcarray &members) +{ + ShaderConstantType base; + base.members = members; + + return EstimatePackingRules(shader, base); +} + +Packing::Rules BufferFormatter::EstimatePackingRules(ResourceId shader, + const ShaderConstantType &baseType) { Packing::Rules pack; @@ -455,7 +464,9 @@ Packing::Rules BufferFormatter::EstimatePackingRules(ResourceId shader, // without more information we must assume all vectors are naturally aligned QSet pointerTypesProcessed; - EstimatePackingRules(pack, shader, members, pointerTypesProcessed, 16); + ShaderConstant base; + base.type = baseType; + EstimatePackingRules(pack, shader, base, pointerTypesProcessed, 16); // only return a 'real' ruleset. Don't revert to individually setting rules if we can help it // since that's a mess. The worst case is if someone is really using a custom packing format then diff --git a/qrenderdoc/Code/QRDUtils.cpp b/qrenderdoc/Code/QRDUtils.cpp index a270e674f..c3b3f5cab 100644 --- a/qrenderdoc/Code/QRDUtils.cpp +++ b/qrenderdoc/Code/QRDUtils.cpp @@ -1147,8 +1147,7 @@ bool RichResourceTextMouseEvent(const QWidget *owner, const QVariant &var, QRect if(!ptrType.members.isEmpty()) { - Packing::Rules pack = - BufferFormatter::EstimatePackingRules(ResourceId(), ptrType.members); + Packing::Rules pack = BufferFormatter::EstimatePackingRules(ResourceId(), ptrType); // for scalar-wrapped structs (generated by 'float *foo' type declarations) use scalar // packing by default as that's probably what people will want most often and if we diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h index a9350a63d..e3e880242 100644 --- a/qrenderdoc/Code/QRDUtils.h +++ b/qrenderdoc/Code/QRDUtils.h @@ -240,6 +240,7 @@ public: static ParsedFormat ParseFormatString(const QString &formatString, uint64_t maxLen, bool cbuffer); static uint32_t GetVarAdvance(const Packing::Rules &pack, const ShaderConstant &var); + static Packing::Rules EstimatePackingRules(ResourceId shader, const ShaderConstantType &baseType); static Packing::Rules EstimatePackingRules(ResourceId shader, const rdcarray &members); diff --git a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp index 715acc3e3..6d1b3f3bc 100644 --- a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp @@ -1197,7 +1197,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st rdcarray samplers; rdcarray roresources, rwresources; - // for pointer types, mapping of inner type ID to index in list (assigned sequentially) + // for pointer types, mapping of pointer type ID to index in list (assigned sequentially) SparseIdMap pointerTypes; // $Globals gathering - for GL global values @@ -1216,7 +1216,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st if(it->second.type == DataType::PointerType && it->second.pointerType.storage == rdcspv::StorageClass::PhysicalStorageBuffer) { - pointerTypes.insert(std::make_pair(it->second.InnerType(), (uint16_t)pointerTypes.size())); + pointerTypes.insert(std::make_pair(it->first, (uint16_t)pointerTypes.size())); } } @@ -1938,24 +1938,39 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st { ShaderConstant dummy; MakeConstantBlockVariable(dummy, pointerTypes, dataTypes[id].pointerType.storage, - dataTypes[id], rdcstr(), Decorations(), false, specInfo); + dataTypes[dataTypes[id].InnerType()], rdcstr(), Decorations(), + false, specInfo); } // continue if we generated some more } while(pointerTypes.size() != numPointerTypes); + // see if we have different pointer types to the same struct, to give them unique names + SparseIdMap dupeInners; + + for(auto it = pointerTypes.begin(); it != pointerTypes.end(); ++it) + { + dupeInners[dataTypes[it->first].InnerType()]++; + } + // populate the pointer types reflection.pointerTypes.reserve(pointerTypes.size()); for(auto it = pointerTypes.begin(); it != pointerTypes.end(); ++it) { ShaderConstant dummy; + const DataType &innerType = dataTypes[dataTypes[it->first].InnerType()]; MakeConstantBlockVariable(dummy, pointerTypes, dataTypes[it->first].pointerType.storage, - dataTypes[it->first], rdcstr(), Decorations(), false, specInfo); + innerType, rdcstr(), decorations[it->first], false, specInfo); if(it->second >= reflection.pointerTypes.size()) reflection.pointerTypes.resize(it->second + 1); + // use the pointer type to disambiguate if there's multiple pointers to the same struct - since + // it could e.g. have different strides + if(innerType.type == DataType::StructType && dupeInners[innerType.id] > 1) + dummy.type.name += StringFormat::Fmt("_%u", it->first.value()); + reflection.pointerTypes[it->second] = dummy.type; } @@ -2129,6 +2144,10 @@ void Reflector::MakeConstantBlockVariable(ShaderConstant &outConst, const DataType *curType = &type; + // for pointers to structs, the pointer itself has an array stride which we should pay attention to + if(curType->type == DataType::StructType && varDecorations.arrayStride != ~0U) + outConst.type.arrayByteStride = varDecorations.arrayStride; + // if the type is an array, set array size and strides then unpeel the array if(curType->type == DataType::ArrayType) { @@ -2192,8 +2211,7 @@ void Reflector::MakeConstantBlockVariable(ShaderConstant &outConst, // try to insert the inner type ID into the map. If it succeeds, it gets the next available // pointer type index (size of the map), if not then we just get the previously added index - auto it = - pointerTypes.insert(std::make_pair(curType->InnerType(), (uint16_t)pointerTypes.size())); + auto it = pointerTypes.insert(std::make_pair(curType->id, (uint16_t)pointerTypes.size())); outConst.type.pointerTypeID = it.first->second; return;