diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp index e59247cde..69ecc28d0 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp @@ -852,7 +852,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *api, const ShaderStage s // now write it into the appropiate elements in the destination ShaderValue for(uint32_t r = 0; r < var.rows; r++) - copyComp(var, r * var.columns + c, tmp, r, var.type); + copyComp(var, r * var.columns + c, tmp, r); } } else @@ -1577,7 +1577,7 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const // transpose into our row major storage for(uint8_t r = 0; r < var.rows; r++) for(uint8_t c = 0; c < var.columns; c++) - copyComp(var, r * var.columns + c, tmp, c * var.rows + r, var.type); + copyComp(var, r * var.columns + c, tmp, c * var.rows + r); } } else if(type.type == DataType::VectorType) @@ -1736,11 +1736,12 @@ void Debugger::WriteThroughPointer(const ShaderVariable &ptr, const ShaderVariab else { ShaderVariable tmp; + tmp.type = var.type; // transpose from our row major storage for(uint8_t r = 0; r < var.rows; r++) for(uint8_t c = 0; c < var.columns; c++) - copyComp(tmp, c * var.rows + r, var, r * var.columns + c, var.type); + copyComp(tmp, c * var.rows + r, var, r * var.columns + c); // read column-wise for(uint8_t c = 0; c < var.columns; c++) diff --git a/renderdoc/driver/shaders/spirv/var_dispatch_helpers.h b/renderdoc/driver/shaders/spirv/var_dispatch_helpers.h index f27c90915..acc6149e9 100644 --- a/renderdoc/driver/shaders/spirv/var_dispatch_helpers.h +++ b/renderdoc/driver/shaders/spirv/var_dispatch_helpers.h @@ -204,16 +204,120 @@ inline void set0001(ShaderVariable &result) } inline void copyComp(ShaderVariable &dst, uint32_t dstComp, const ShaderVariable &src, - uint32_t srcComp, VarType type = VarType::Unknown) + uint32_t srcComp) { - if(type == VarType::Unknown) + // fast path for same-sized inputs, which is common (e.g. float declared variables with float + // inputs) + if(dst.type == src.type) { - RDCASSERTEQUAL(dst.type, src.type); - type = src.type; + const uint32_t sz = VarTypeByteSize(src.type); + memcpy(((byte *)dst.value.u8v.data()) + sz * dstComp, + ((byte *)src.value.u8v.data()) + sz * srcComp, sz); + return; + } + else + { + // otherwise we convert the component here + const uint32_t srcSz = VarTypeByteSize(src.type); + const uint32_t dstSz = VarTypeByteSize(dst.type); + + if(srcSz <= 4 && dstSz <= 4) + { + // if the types are no more than 4-byte, we can use the helpers above without truncation + if(VarTypeCompType(src.type) == CompType::Float) + setFloatComp(dst, dstComp, floatComp(src, srcComp)); + else if(VarTypeCompType(src.type) == CompType::SInt) + setIntComp(dst, dstComp, intComp(src, srcComp)); + else + setUintComp(dst, dstComp, uintComp(src, srcComp)); + } + else + { + // if there's a 64-bit type somewhere we need to go through double/int64 + double d = 0.0; + uint64_t u = 0; + int64_t i = 0; + + switch(src.type) + { + case VarType::Float: + case VarType::Half: + { + d = floatComp(src, srcComp); + break; + } + case VarType::Double: + { + d = src.value.f64v[srcComp]; + break; + } + case VarType::SInt: + case VarType::SShort: + case VarType::SByte: + { + i = intComp(src, srcComp); + break; + } + case VarType::SLong: + { + i = src.value.s64v[srcComp]; + break; + } + case VarType::ULong: + { + u = src.value.u64v[srcComp]; + break; + } + default: + { + // all other case are uints or invalid types + u = uintComp(src, srcComp); + break; + } + } + + // valid SPIR-V should match the base type in any case where we're copying components, + // conversions between are done separately. So we just assume that d/u/i was filled above and + // read from it to the output + switch(src.type) + { + case VarType::Float: + case VarType::Half: + { + setFloatComp(dst, dstComp, float(d)); + break; + } + case VarType::Double: + { + dst.value.f64v[dstComp] = d; + break; + } + case VarType::SInt: + case VarType::SShort: + case VarType::SByte: + { + setIntComp(dst, dstComp, int32_t(i)); + break; + } + case VarType::SLong: + { + dst.value.s64v[dstComp] = i; + break; + } + case VarType::ULong: + { + dst.value.u64v[dstComp] = u; + break; + } + default: + { + // all other case are uints or invalid types + setUintComp(dst, dstComp, uint32_t(u)); + break; + } + } + } } - const uint32_t sz = VarTypeByteSize(type); - memcpy(((byte *)dst.value.u8v.data()) + sz * dstComp, - ((byte *)src.value.u8v.data()) + sz * srcComp, sz); } #define IMPL_FOR_FLOAT_TYPES_FOR_TYPE(impl, type) \ diff --git a/renderdoc/driver/vulkan/vk_shaderdebug.cpp b/renderdoc/driver/vulkan/vk_shaderdebug.cpp index 5e1074a6d..5030377d5 100644 --- a/renderdoc/driver/vulkan/vk_shaderdebug.cpp +++ b/renderdoc/driver/vulkan/vk_shaderdebug.cpp @@ -444,21 +444,20 @@ public: if(location < location_inputs.size()) { - const uint32_t typeSize = VarTypeByteSize(var.type); if(var.rows == 1) { if(component + var.columns > 4) RDCERR("Unexpected component %u for column count %u", component, var.columns); for(uint8_t c = 0; c < var.columns; c++) - copyComp(var, c, location_inputs[location], component + c, var.type); + copyComp(var, c, location_inputs[location], component + c); } else { RDCASSERTEQUAL(component, 0); for(uint8_t r = 0; r < var.rows; r++) for(uint8_t c = 0; c < var.columns; c++) - copyComp(var, r * var.columns + c, location_inputs[location + c], r, var.type); + copyComp(var, r * var.columns + c, location_inputs[location + c], r); } return; } @@ -486,16 +485,21 @@ public: DerivativeDeltas ret; + ret.ddxcoarse.type = type; + ret.ddxfine.type = type; + ret.ddycoarse.type = type; + ret.ddyfine.type = type; + RDCASSERT(component < 4, component); // rebase from component into [0].. for(uint32_t src = component, dst = 0; src < 4; src++, dst++) { - copyComp(ret.ddxcoarse, dst, deriv.ddxcoarse, src, type); - copyComp(ret.ddxfine, dst, deriv.ddxfine, src, type); - copyComp(ret.ddycoarse, dst, deriv.ddycoarse, src, type); - copyComp(ret.ddyfine, dst, deriv.ddyfine, src, type); + copyComp(ret.ddxcoarse, dst, deriv.ddxcoarse, src); + copyComp(ret.ddxfine, dst, deriv.ddxfine, src); + copyComp(ret.ddycoarse, dst, deriv.ddycoarse, src); + copyComp(ret.ddyfine, dst, deriv.ddyfine, src); } return ret; @@ -3871,7 +3875,30 @@ ShaderDebugTrace *VulkanReplay::DebugVertex(uint32_t eventId, uint32_t vertid, u } else { - var.type = VarType::Float; + var.type = VarType::UInt; + + if(fmt.compType == CompType::UInt) + { + if(fmt.compByteWidth == 1) + var.type = VarType::UByte; + else if(fmt.compByteWidth == 2) + var.type = VarType::UShort; + else if(fmt.compByteWidth == 4) + var.type = VarType::UInt; + else if(fmt.compByteWidth == 8) + var.type = VarType::ULong; + } + else if(fmt.compType == CompType::SInt) + { + if(fmt.compByteWidth == 1) + var.type = VarType::SByte; + else if(fmt.compByteWidth == 2) + var.type = VarType::SShort; + else if(fmt.compByteWidth == 4) + var.type = VarType::SInt; + else if(fmt.compByteWidth == 8) + var.type = VarType::SLong; + } RDCASSERTEQUAL(fmt.compByteWidth, VarTypeByteSize(var.type)); memcpy(var.value.u8v.data(), data.data(), fmt.compByteWidth * fmt.compCount); @@ -4533,6 +4560,10 @@ ShaderDebugTrace *VulkanReplay::DebugPixel(uint32_t eventId, uint32_t x, uint32_ builtin ? apiWrapper->builtin_derivatives[param.systemValue] : apiWrapper->location_derivatives[param.regIndex]; + var.rows = 1; + var.columns = param.compCount & 0xff; + var.type = param.varType; + const uint32_t comp = Bits::CountTrailingZeroes(uint32_t(param.regChannelMask)); const uint32_t elemSize = VarTypeByteSize(param.varType);