diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.cpp b/renderdoc/driver/shaders/spirv/spirv_debug.cpp index dfcb926b8..bfef35e10 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug.cpp @@ -4882,6 +4882,192 @@ void ThreadState::StepNext(bool useDebugState, const uint32_t steps, case Op::SDotAccSat: case Op::UDotAccSat: case Op::SUDotAccSat: + { + Id vector1; + Id vector2; + Id result; + ShaderVariable acc; + bool leftSigned = true; + bool rightSigned = true; + switch(opdata.op) + { + case Op::SDot: + { + OpSDot dot(it); + vector1 = dot.vector1; + vector2 = dot.vector2; + result = dot.result; + break; + } + case Op::SDotAccSat: + { + OpSDotAccSat dot(it); + vector1 = dot.vector1; + vector2 = dot.vector2; + acc = GetSrc(dot.accumulator); + result = dot.result; + break; + } + case Op::UDot: + { + OpUDot dot(it); + vector1 = dot.vector1; + vector2 = dot.vector2; + result = dot.result; + leftSigned = false; + rightSigned = false; + break; + } + case Op::UDotAccSat: + { + OpUDotAccSat dot(it); + vector1 = dot.vector1; + vector2 = dot.vector2; + acc = GetSrc(dot.accumulator); + result = dot.result; + leftSigned = false; + rightSigned = false; + break; + } + case Op::SUDot: + { + OpSUDot dot(it); + vector1 = dot.vector1; + vector2 = dot.vector2; + result = dot.result; + rightSigned = false; + break; + } + case Op::SUDotAccSat: + { + OpSUDotAccSat dot(it); + vector1 = dot.vector1; + vector2 = dot.vector2; + acc = GetSrc(dot.accumulator); + result = dot.result; + rightSigned = false; + break; + } + default: RDCERR("Unexpected opcode %s", ToStr(opdata.op).c_str()); break; + } + + ShaderVariable lhs = GetSrc(vector1); + ShaderVariable rhs = GetSrc(vector2); + + RDCASSERTEQUAL(lhs.columns, rhs.columns); + // 1x32-bit is a 4x-8bit packed vector + bool packed = false; + if((lhs.columns == 1) && (lhs.type == VarType::SInt || lhs.type == VarType::UInt)) + { + lhs.columns = 4; + rhs.columns = 4; + lhs.type = (lhs.type == VarType::SInt) ? VarType::SByte : VarType::UByte; + rhs.type = (rhs.type == VarType::SInt) ? VarType::SByte : VarType::UByte; + packed = true; + } + const DataType &resultType = debugger.GetType(opdata.resultType); + ShaderVariable var; + var.type = resultType.scalar().Type(); + var.rows = 1; + var.columns = 1; + int64_t sMinValue = int64_t(INT64_MIN); + int64_t sMaxValue = int64_t(INT64_MAX); + if(var.type == VarType::SInt) + { + sMinValue = int64_t(INT32_MIN); + sMaxValue = int64_t(INT32_MAX); + } + else if(var.type == VarType::SShort) + { + sMinValue = int64_t(INT16_MIN); + sMaxValue = int64_t(INT16_MAX); + } + else if(var.type == VarType::SByte) + { + sMinValue = int64_t(INT8_MIN); + sMaxValue = int64_t(INT8_MAX); + } + uint64_t uMaxValue = uint64_t(UINT64_MAX); + if(var.type == VarType::UInt) + { + uMaxValue = uint64_t(UINT32_MAX); + } + else if(var.type == VarType::UShort) + { + uMaxValue = uint64_t(UINT16_MAX); + } + else if(var.type == VarType::UByte) + { + uMaxValue = uint64_t(UINT8_MAX); + } + + if(leftSigned && rightSigned) + { +#undef _IMPL +#define _IMPL(I, S, U) \ + int64_t ret(0); \ + if(!packed) \ + { \ + for(uint8_t c = 0; c < lhs.columns; c++) \ + ret += comp(lhs, c) * comp(rhs, c); \ + } \ + else \ + { \ + for(uint8_t c = 0; c < lhs.columns; c++) \ + ret += (S)lhs.value.s8v[c] * (S)rhs.value.s8v[c]; \ + } \ + ret += comp(acc, 0); \ + ret = RDCCLAMP(ret, sMinValue, sMaxValue); \ + comp(var, 0) = (S)ret; + + IMPL_FOR_INT_TYPES(_IMPL); + } + else if(!leftSigned && !rightSigned) + { +#undef _IMPL +#define _IMPL(I, S, U) \ + uint64_t ret(0); \ + if(!packed) \ + { \ + for(uint8_t c = 0; c < lhs.columns; c++) \ + ret += comp(lhs, c) * comp(rhs, c); \ + } \ + else \ + { \ + for(uint8_t c = 0; c < lhs.columns; c++) \ + ret += (U)lhs.value.u8v[c] * (U)rhs.value.u8v[c]; \ + } \ + ret += comp(acc, 0); \ + ret = RDCMIN(ret, uMaxValue); \ + comp(var, 0) = (U)ret; + + IMPL_FOR_INT_TYPES(_IMPL); + } + else if(leftSigned && !rightSigned) + { +#undef _IMPL +#define _IMPL(I, S, U) \ + int64_t ret(0); \ + if(!packed) \ + { \ + for(uint8_t c = 0; c < lhs.columns; c++) \ + ret += comp(lhs, c) * comp(rhs, c); \ + } \ + else \ + { \ + for(uint8_t c = 0; c < lhs.columns; c++) \ + ret += (S)lhs.value.s8v[c] * (U)rhs.value.u8v[c]; \ + } \ + ret += comp(acc, 0); \ + ret = RDCCLAMP(ret, sMinValue, sMaxValue); \ + comp(var, 0) = (S)ret; + + IMPL_FOR_INT_TYPES(_IMPL); + } + + SetDst(result, var); + break; + } // legacy/OpenCL/AMD group operations case Op::GroupAll: diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp index a5744caa2..c27098867 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp @@ -465,6 +465,7 @@ void Reflector::CheckDebuggable(bool &debuggable, rdcstr &debugStatus) const "SPV_KHR_terminate_invocation", "SPV_KHR_vulkan_memory_model", "SPV_KHR_compute_shader_derivatives", + "SPV_KHR_integer_dot_product", // EXT extensions "SPV_EXT_demote_to_helper_invocation", @@ -617,6 +618,11 @@ void Reflector::CheckDebuggable(bool &debuggable, rdcstr &debugStatus) const case Capability::SubgroupVoteKHR: case Capability::ComputeDerivativeGroupQuadsKHR: case Capability::ComputeDerivativeGroupLinearKHR: + // SPIR-V 1.6 / SPV_KHR_integer_dot_product + case Capability::DotProduct: + case Capability::DotProductInput4x8Bit: + case Capability::DotProductInput4x8BitPacked: + case Capability::DotProductInputAll: { supported = true; break; @@ -648,16 +654,6 @@ void Reflector::CheckDebuggable(bool &debuggable, rdcstr &debugStatus) const break; } - // SPIR-V 1.6 / SPV_KHR_integer_dot_product - case Capability::DotProduct: - case Capability::DotProductInput4x8Bit: - case Capability::DotProductInput4x8BitPacked: - case Capability::DotProductInputAll: - { - supported = false; - break; - } - // SPV_KHR_bfloat16 case Capability::BFloat16TypeKHR: case Capability::BFloat16DotProductKHR: