From f1d513f3133642afa60df6b5b552dde7d56adde5 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 4 Aug 2022 12:19:40 +0100 Subject: [PATCH] Refactor reserved slots in opaque pointer variables to use helpers --- renderdoc/driver/shaders/spirv/spirv_debug.h | 6 +- .../shaders/spirv/spirv_debug_setup.cpp | 296 +++++++++++++----- 2 files changed, 214 insertions(+), 88 deletions(-) diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.h b/renderdoc/driver/shaders/spirv/spirv_debug.h index 9fd9f0fd2..4a6e3c11b 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.h +++ b/renderdoc/driver/shaders/spirv/spirv_debug.h @@ -361,12 +361,12 @@ public: ShaderVariable GetPointerValue(const ShaderVariable &v) const; uint64_t GetPointerByteOffset(const ShaderVariable &ptr) const; DebugAPIWrapper::TextureType GetTextureType(const ShaderVariable &img) const; - ShaderVariable MakePointerVariable(Id id, const ShaderVariable *v, uint32_t scalar0 = ~0U, - uint32_t scalar1 = ~0U) const; + ShaderVariable MakePointerVariable(Id id, const ShaderVariable *v, uint8_t scalar0 = 0xff, + uint8_t scalar1 = 0xff) const; Id GetPointerBaseId(const ShaderVariable &v) const; bool IsOpaquePointer(const ShaderVariable &v) const; bool ArePointersAndEqual(const ShaderVariable &a, const ShaderVariable &b) const; - void WriteThroughPointer(const ShaderVariable &ptr, const ShaderVariable &val); + void WriteThroughPointer(ShaderVariable &ptr, const ShaderVariable &val); ShaderVariable MakeCompositePointer(const ShaderVariable &base, Id id, rdcarray &indices); DebugAPIWrapper *GetAPIWrapper() { return apiWrapper; } diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp index 6d4de6c55..ff5b87242 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp @@ -37,17 +37,144 @@ RDOC_CONFIG(bool, Vulkan_Hack_AllowNonUniformSubgroups, false, "will only work for a limited set and not with the 'real' subgroup."); // 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 PointerVariableSlot = 0; -static const uint32_t Scalar0VariableSlot = 1; -static const uint32_t Scalar1VariableSlot = 2; -static const uint32_t BaseIdVariableSlot = 3; -static const uint32_t MajorStrideVariableSlot = 4; -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; +// we just reserve value slots that we know won't be used in opaque variables. +// there's significant wasted space to keep things simple with one property = one slot +static const uint32_t OpaquePointerTypeID = 0x0dd0beef; + +enum class PointerFlags +{ + RowMajorMatrix = 0x1, + SSBO = 0x2, + GlobalArrayBinding = 0x4, +}; + +BITMASK_OPERATORS(PointerFlags); + +// slot 0 for the actual pointer. Shares the same slot as the actual pointer value for GPU pointers +ShaderVariable *getPointer(ShaderVariable &var) +{ + return (ShaderVariable *)(uintptr_t)var.value.u64v[0]; +} + +const ShaderVariable *getPointer(const ShaderVariable &var) +{ + return (const ShaderVariable *)(uintptr_t)var.value.u64v[0]; +} + +void setPointer(ShaderVariable &var, const ShaderVariable *ptr) +{ + var.value.u64v[0] = (uint64_t)(uintptr_t)ptr; +} + +// slot 1 is the type ID, for opaque pointers this is OpaquePointerTypeID and for real GPU pointers +// this is the type ID of the pointer. We only display this properly for base pointers - +// dereferenced pointers just show the value behind them (otherwise we'd need a pointer type for +// every child element of any pointer type, which is feasible but probably unnecessary) + +// slot 2 contains the scalar indices that we carry around from dereferences +void setScalars(ShaderVariable &var, uint8_t scalar0, uint8_t scalar1) +{ + var.value.u64v[2] = (scalar0 << 8) | scalar1; +} + +rdcpair getScalars(const ShaderVariable &var) +{ + return {(var.value.u64v[2] >> 8) & 0xff, var.value.u64v[2] & 0xff}; +} + +// slot 3 contains the base ID of the structure, for registering pointer changes +void setBaseId(ShaderVariable &var, rdcspv::Id id) +{ + var.value.u64v[3] = id.value(); +} + +rdcspv::Id getBaseId(const ShaderVariable &var) +{ + return rdcspv::Id::fromWord((uint32_t)var.value.u64v[3]); +} + +// slot 4 has the different flags we keep track of +void setPointerFlags(ShaderVariable &var, PointerFlags flags) +{ + var.value.u64v[4] = uint32_t(flags); +} + +PointerFlags getPointerFlags(const ShaderVariable &var) +{ + return (PointerFlags)var.value.u64v[4]; +} + +void enablePointerFlags(ShaderVariable &var, PointerFlags flags) +{ + var.value.u64v[4] = uint32_t((PointerFlags)var.value.u64v[4] | flags); +} + +void disablePointerFlags(ShaderVariable &var, PointerFlags flags) +{ + var.value.u64v[4] = uint32_t(PointerFlags((PointerFlags)var.value.u64v[4] & ~flags)); +} + +bool checkPointerFlags(const ShaderVariable &var, PointerFlags flags) +{ + return ((PointerFlags)var.value.u64v[4] & flags) == flags; +} + +// slot 5 has the matrix stride +void setMatrixStride(ShaderVariable &var, uint32_t stride) +{ + var.value.u64v[5] = stride; +} + +uint32_t getMatrixStride(const ShaderVariable &var) +{ + return (uint32_t)var.value.u64v[5]; +} + +// slot 6 has the relative byte offset. For plain bindings the global is created with an offset 0 +// and then it's added to for access chains +void setByteOffset(ShaderVariable &var, uint64_t offset) +{ + var.value.u64v[6] = offset; +} + +uint64_t getByteOffset(const ShaderVariable &var) +{ + return var.value.u64v[6]; +} + +// we also use slot 6 for the texture type (because textures and buffers requiring a byte offset are +// disjoint) +void setTextureType(ShaderVariable &var, rdcspv::DebugAPIWrapper::TextureType type) +{ + var.value.u64v[6] = type; +} + +rdcspv::DebugAPIWrapper::TextureType getTextureType(const ShaderVariable &var) +{ + return (rdcspv::DebugAPIWrapper::TextureType)var.value.u64v[6]; +} + +// slot 7 contains the binding array index if we indexed into a global binding array +void setBindArrayIndex(ShaderVariable &var, uint32_t arrayIndex) +{ + var.value.u64v[7] = arrayIndex; +} + +uint32_t getBindArrayIndex(const ShaderVariable &var) +{ + return (uint32_t)var.value.u64v[7]; +} + +// slot 8 contains the ID of the pointer's type, for further buffer type chasing +void setBufferTypeId(ShaderVariable &var, rdcspv::Id id) +{ + var.value.u64v[8] = id.value(); +} + +rdcspv::Id getBufferTypeId(const ShaderVariable &var) +{ + return rdcspv::Id::fromWord((uint32_t)var.value.u64v[8]); +} static ShaderVariable *pointerIfMutable(const ShaderVariable &var) { @@ -59,36 +186,36 @@ static ShaderVariable *pointerIfMutable(ShaderVariable &var) } static void ClampScalars(rdcspv::DebugAPIWrapper *apiWrapper, const ShaderVariable &var, - uint32_t &scalar0) + uint8_t &scalar0) { - if(scalar0 > var.columns && scalar0 != ~0U) + if(scalar0 > var.columns && scalar0 != 0xff) { apiWrapper->AddDebugMessage( MessageCategory::Execution, MessageSeverity::High, MessageSource::RuntimeWarning, StringFormat::Fmt("Invalid scalar index %u at %u-vector %s. Clamping to %u", scalar0, var.columns, var.name.c_str(), var.columns - 1)); - scalar0 = RDCMIN(0U, uint32_t(var.columns - 1)); + scalar0 = RDCMIN((uint8_t)1, var.columns) - 1; } } static void ClampScalars(rdcspv::DebugAPIWrapper *apiWrapper, const ShaderVariable &var, - uint32_t &scalar0, uint32_t &scalar1) + uint8_t &scalar0, uint8_t &scalar1) { - if(scalar0 > var.columns && scalar0 != ~0U) + if(scalar0 > var.columns && scalar0 != 0xff) { apiWrapper->AddDebugMessage( MessageCategory::Execution, MessageSeverity::High, MessageSource::RuntimeWarning, StringFormat::Fmt("Invalid scalar index %u at matrix %s with %u columns. Clamping to %u", scalar0, var.columns, var.name.c_str(), var.columns - 1)); - scalar0 = RDCMIN(0U, uint32_t(var.columns - 1)); + scalar0 = RDCMIN((uint8_t)1, var.columns) - 1; } - if(scalar1 > var.rows && scalar1 != ~0U) + if(scalar1 > var.rows && scalar1 != 0xff) { apiWrapper->AddDebugMessage( MessageCategory::Execution, MessageSeverity::High, MessageSource::RuntimeWarning, StringFormat::Fmt("Invalid scalar index %u at matrix %s with %u rows. Clamping to %u", scalar1, var.rows, var.name.c_str(), var.rows - 1)); - scalar1 = RDCMIN(0U, uint32_t(var.rows - 1)); + scalar1 = RDCMIN((uint8_t)1, var.rows) - 1; } } @@ -921,10 +1048,10 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *api, const ShaderStage s var.SetBinding((int32_t)bindset, (int32_t)bind, 0U); - var.value.u64v[SSBOVariableSlot] = 1; + enablePointerFlags(var, PointerFlags::SSBO); if(isArray) - var.value.u64v[ArrayVariableSlot] = 1; + enablePointerFlags(var, PointerFlags::GlobalArrayBinding); sourceVar.type = VarType::ReadWriteResource; sourceVar.rows = 1; @@ -1084,7 +1211,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *api, const ShaderStage s if(innertype->type == DataType::ArrayType) { - var.value.u64v[ArrayVariableSlot] = 1; + enablePointerFlags(var, PointerFlags::GlobalArrayBinding); innertype = &dataTypes[innertype->InnerType()]; } @@ -1124,7 +1251,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *api, const ShaderStage s texType |= DebugAPIWrapper::UInt_Texture; } - var.value.u64v[TextureTypeVariableSlot] = texType; + setTextureType(var, (DebugAPIWrapper::TextureType)texType); if(imageTypes[imgid].sampled == 2 && imageTypes[imgid].dim != Dim::SubpassData) { @@ -1828,17 +1955,17 @@ rdcarray Debugger::ContinueDebug() return ret; } -ShaderVariable Debugger::MakePointerVariable(Id id, const ShaderVariable *v, uint32_t scalar0, - uint32_t scalar1) const +ShaderVariable Debugger::MakePointerVariable(Id id, const ShaderVariable *v, uint8_t scalar0, + uint8_t scalar1) const { ShaderVariable var; var.rows = var.columns = 1; var.type = VarType::GPUPointer; var.name = GetRawName(id); - var.value.u64v[PointerVariableSlot] = (uint64_t)(uintptr_t)v; - var.value.u64v[Scalar0VariableSlot] = scalar0; - var.value.u64v[Scalar1VariableSlot] = scalar1; - var.value.u64v[BaseIdVariableSlot] = id.value(); + var.SetTypedPointer(0, ResourceId(), OpaquePointerTypeID); + setPointer(var, v); + setScalars(var, scalar0, scalar1); + setBaseId(var, id); return var; } @@ -1850,31 +1977,31 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, // if the base is a plain value, we just start walking down the chain. If the base is a pointer // though, we want to step down the chain in the underlying storage, so dereference first. if(base.type == VarType::GPUPointer) - leaf = (const ShaderVariable *)(uintptr_t)base.value.u64v[PointerVariableSlot]; + leaf = getPointer(base); bool isArray = false; if((leaf->type == VarType::ReadWriteResource || leaf->type == VarType::ReadOnlyResource || leaf->type == VarType::Sampler) && - leaf->value.u64v[ArrayVariableSlot]) + checkPointerFlags(*leaf, PointerFlags::GlobalArrayBinding)) { isArray = true; } - if(leaf->type == VarType::ReadWriteResource && leaf->value.u64v[SSBOVariableSlot]) + if(leaf->type == VarType::ReadWriteResource && checkPointerFlags(*leaf, PointerFlags::SSBO)) { ShaderVariable ret = MakePointerVariable(id, leaf); - uint64_t byteOffset = base.value.u64v[BufferPointerByteOffsetVariableSlot]; - ret.value.u64v[MajorStrideVariableSlot] = base.value.u64v[MajorStrideVariableSlot]; + uint64_t byteOffset = getByteOffset(base); + setMatrixStride(ret, getMatrixStride(base)); + setPointerFlags(ret, getPointerFlags(base)); const DataType *type = &dataTypes[idTypes[id]]; RDCASSERT(type->type == DataType::PointerType); type = &dataTypes[type->InnerType()]; - rdcspv::Id typeId = - rdcspv::Id::fromWord(uint32_t(base.value.u64v[BufferPointerTypeIdVariableSlot])); + rdcspv::Id typeId = getBufferTypeId(base); if(typeId != rdcspv::Id()) type = &dataTypes[typeId]; @@ -1885,7 +2012,7 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, // if it's an array, consume the array index first if(isArray) { - ret.value.u64v[ArrayVariableSlot] = indices[i++]; + setBindArrayIndex(ret, indices[i++]); type = &dataTypes[type->InnerType()]; } @@ -1923,10 +2050,12 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, } if(curDecorations.flags & Decorations::HasMatrixStride) - ret.value.u64v[MajorStrideVariableSlot] = curDecorations.matrixStride; + setMatrixStride(ret, curDecorations.matrixStride); if(curDecorations.flags & Decorations::RowMajor) - ret.value.u64v[MajorStrideVariableSlot] |= 0x80000000U; + enablePointerFlags(ret, PointerFlags::RowMajorMatrix); + else if(curDecorations.flags & Decorations::ColMajor) + disablePointerFlags(ret, PointerFlags::RowMajorMatrix); size_t remaining = indices.size() - i; if(remaining == 2) @@ -1980,8 +2109,8 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, } } - ret.value.u64v[BufferPointerTypeIdVariableSlot] = type->id.value(); - ret.value.u64v[BufferPointerByteOffsetVariableSlot] = byteOffset; + setBufferTypeId(ret, type->id); + setByteOffset(ret, byteOffset); return ret; } @@ -2005,7 +2134,7 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, } // apply any remaining scalar selectors - uint32_t scalar0 = ~0U, scalar1 = ~0U; + uint8_t scalar0 = 0xff, scalar1 = 0xff; size_t remaining = indices.size() - i; @@ -2020,30 +2149,30 @@ ShaderVariable Debugger::MakeCompositePointer(const ShaderVariable &base, Id id, if(remaining == 2) { - scalar0 = indices[i]; - scalar1 = indices[i + 1]; + scalar0 = indices[i] & 0xff; + scalar1 = indices[i + 1] & 0xff; } else if(remaining == 1) { - scalar0 = indices[i]; + scalar0 = indices[i] & 0xff; } ShaderVariable ret = MakePointerVariable(id, leaf, scalar0, scalar1); if(isArray) - ret.value.u64v[ArrayVariableSlot] = indices[0]; + setBindArrayIndex(ret, indices[0]); return ret; } uint64_t Debugger::GetPointerByteOffset(const ShaderVariable &ptr) const { - return ptr.value.u64v[BufferPointerByteOffsetVariableSlot]; + return getByteOffset(ptr); } DebugAPIWrapper::TextureType Debugger::GetTextureType(const ShaderVariable &img) const { - return (DebugAPIWrapper::TextureType)img.value.u64v[TextureTypeVariableSlot]; + return getTextureType(img); } ShaderVariable Debugger::GetPointerValue(const ShaderVariable &ptr) const @@ -2051,13 +2180,12 @@ ShaderVariable Debugger::GetPointerValue(const ShaderVariable &ptr) const // opaque pointers display as their inner value if(IsOpaquePointer(ptr)) { - const ShaderVariable *inner = - (const ShaderVariable *)(uintptr_t)ptr.value.u64v[PointerVariableSlot]; + const ShaderVariable *inner = getPointer(ptr); 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]); + ret.SetBinding(bind.bindset, bind.bind, getBindArrayIndex(ptr)); return ret; } @@ -2070,31 +2198,26 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const if(ptr.type != VarType::GPUPointer) return ptr; - const ShaderVariable *inner = - (const ShaderVariable *)(uintptr_t)ptr.value.u64v[PointerVariableSlot]; + const ShaderVariable *inner = getPointer(ptr); ShaderVariable ret; - if(inner->type == VarType::ReadWriteResource && inner->value.u64v[SSBOVariableSlot]) + if(inner->type == VarType::ReadWriteResource && checkPointerFlags(*inner, PointerFlags::SSBO)) { - rdcspv::Id typeId = - rdcspv::Id::fromWord(uint32_t(ptr.value.u64v[BufferPointerTypeIdVariableSlot])); - uint64_t byteOffset = ptr.value.u64v[BufferPointerByteOffsetVariableSlot]; + rdcspv::Id typeId = getBufferTypeId(ptr); + uint64_t byteOffset = getByteOffset(ptr); BindpointIndex bind = inner->GetBinding(); + bind.arrayIndex = getBindArrayIndex(ptr); - bind.arrayIndex = (uint32_t)ptr.value.u64v[ArrayVariableSlot]; - - uint32_t varMatrixStride = (uint32_t)ptr.value.u64v[MajorStrideVariableSlot]; + uint32_t varMatrixStride = getMatrixStride(ptr); Decorations parentDecorations; - if((varMatrixStride & 0x80000000U) != 0) + if(checkPointerFlags(ptr, PointerFlags::RowMajorMatrix)) parentDecorations.flags = Decorations::RowMajor; else parentDecorations.flags = Decorations::ColMajor; - varMatrixStride &= 0xff; - if(varMatrixStride != 0) { parentDecorations.flags = @@ -2183,13 +2306,13 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const { BindpointIndex bind = ret.GetBinding(); - ret.SetBinding(bind.bindset, bind.bind, (uint32_t)ptr.value.u64v[ArrayVariableSlot]); + ret.SetBinding(bind.bindset, bind.bind, getBindArrayIndex(ptr)); } // 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 = (uint32_t)ptr.value.u64v[Scalar0VariableSlot]; - uint32_t scalar1 = (uint32_t)ptr.value.u64v[Scalar1VariableSlot]; + uint8_t scalar0 = 0, scalar1 = 0; + rdctie(scalar0, scalar1) = getScalars(ptr); ShaderVariable tmp = ret; @@ -2198,7 +2321,7 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const // matrix case ClampScalars(apiWrapper, ret, scalar0, scalar1); - if(scalar0 != ~0U && scalar1 != ~0U) + if(scalar0 != 0xff && scalar1 != 0xff) { // two indices - selecting a scalar. scalar0 is the first index in the chain so it chooses // column @@ -2207,7 +2330,7 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const // it's a scalar now, even if it was a matrix before ret.rows = ret.columns = 1; } - else if(scalar0 != ~0U) + else if(scalar0 != 0xff) { // one index, selecting a column for(uint32_t row = 0; row < ret.rows; row++) @@ -2222,7 +2345,7 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const ClampScalars(apiWrapper, ret, scalar0); // vector case, selecting a scalar (if anything) - if(scalar0 != ~0U) + if(scalar0 != 0xff) { copyComp(ret, 0, tmp, scalar0); @@ -2239,7 +2362,7 @@ Id Debugger::GetPointerBaseId(const ShaderVariable &ptr) const RDCASSERT(ptr.type == VarType::GPUPointer); // we stored the base ID so that it's always available regardless of access chains - return Id::fromWord((uint32_t)ptr.value.u64v[BaseIdVariableSlot]); + return getBaseId(ptr); } bool Debugger::IsOpaquePointer(const ShaderVariable &ptr) const @@ -2247,7 +2370,12 @@ bool Debugger::IsOpaquePointer(const ShaderVariable &ptr) const if(ptr.type != VarType::GPUPointer) return false; - ShaderVariable *inner = (ShaderVariable *)(uintptr_t)ptr.value.u64v[PointerVariableSlot]; + PointerVal val = ptr.GetPointer(); + + if(val.pointerTypeID != OpaquePointerTypeID) + return false; + + const ShaderVariable *inner = getPointer(ptr); return inner->type == VarType::ReadOnlyResource || inner->type == VarType::Sampler || inner->type == VarType::ReadWriteResource; } @@ -2262,22 +2390,20 @@ bool Debugger::ArePointersAndEqual(const ShaderVariable &a, const ShaderVariable return false; } -void Debugger::WriteThroughPointer(const ShaderVariable &ptr, const ShaderVariable &val) +void Debugger::WriteThroughPointer(ShaderVariable &ptr, const ShaderVariable &val) { - ShaderVariable *storage = (ShaderVariable *)(uintptr_t)ptr.value.u64v[PointerVariableSlot]; + ShaderVariable *storage = getPointer(ptr); if(storage->type == VarType::ReadWriteResource) { - rdcspv::Id typeId = - rdcspv::Id::fromWord(uint32_t(ptr.value.u64v[BufferPointerTypeIdVariableSlot])); - uint64_t byteOffset = ptr.value.u64v[BufferPointerByteOffsetVariableSlot]; + rdcspv::Id typeId = getBufferTypeId(ptr); + uint64_t byteOffset = getByteOffset(ptr); BindpointIndex bind = storage->GetBinding(); - bind.arrayIndex = (uint32_t)ptr.value.u64v[ArrayVariableSlot]; - uint32_t matrixStride = (uint32_t)ptr.value.u64v[MajorStrideVariableSlot]; - bool rowMajor = (matrixStride & 0x80000000U) != 0; - matrixStride &= 0xff; + bind.arrayIndex = getBindArrayIndex(ptr); + uint32_t matrixStride = getMatrixStride(ptr); + bool rowMajor = checkPointerFlags(ptr, PointerFlags::RowMajorMatrix); auto writeCallback = [this, bind, matrixStride, rowMajor]( const ShaderVariable &var, const Decorations &, const DataType &type, uint64_t offset, @@ -2346,11 +2472,11 @@ void Debugger::WriteThroughPointer(const ShaderVariable &ptr, const ShaderVariab // 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 = (uint32_t)ptr.value.u64v[Scalar0VariableSlot]; - uint32_t scalar1 = (uint32_t)ptr.value.u64v[Scalar1VariableSlot]; + uint8_t scalar0 = 0, scalar1 = 0; + rdctie(scalar0, scalar1) = getScalars(ptr); // in the common case we don't have scalar selectors. In this case just assign the value - if(scalar0 == ~0U && scalar1 == ~0U) + if(scalar0 == 0xff && scalar1 == 0xff) { AssignValue(*storage, val); } @@ -2363,13 +2489,13 @@ void Debugger::WriteThroughPointer(const ShaderVariable &ptr, const ShaderVariab // matrix case ClampScalars(apiWrapper, *storage, scalar0, scalar1); - if(scalar0 != ~0U && scalar1 != ~0U) + if(scalar0 != 0xff && scalar1 != 0xff) { // two indices - selecting a scalar. scalar0 is the first index in the chain so it chooses // column copyComp(*storage, scalar1 * storage->columns + scalar0, val, 0); } - else if(scalar0 != ~0U) + else if(scalar0 != 0xff) { // one index, selecting a column for(uint32_t row = 0; row < storage->rows; row++)