diff --git a/qrenderdoc/Code/BufferFormatter.cpp b/qrenderdoc/Code/BufferFormatter.cpp index 6ced9a0d4..c845bfd1e 100644 --- a/qrenderdoc/Code/BufferFormatter.cpp +++ b/qrenderdoc/Code/BufferFormatter.cpp @@ -1044,22 +1044,40 @@ static void FillShaderVarData(ShaderVariable &var, const ShaderConstant &elem, c src++; - if(var.type == VarType::Double) - var.value.f64v[dst] = o.toDouble(); - if(var.type == VarType::Float || var.type == VarType::Half) - var.value.f32v[dst] = o.toFloat(); - else if(var.type == VarType::ULong) - var.value.u64v[dst] = o.toULongLong(); - else if(var.type == VarType::SLong) - var.value.s64v[dst] = o.toLongLong(); - else if(var.type == VarType::Bool) - var.value.u32v[dst] = o.toBool() ? 1 : 0; - else if(var.type == VarType::UInt || var.type == VarType::UShort || var.type == VarType::UByte) - var.value.u32v[dst] = o.toUInt(); - else if(var.type == VarType::SInt || var.type == VarType::SShort || var.type == VarType::SByte) - var.value.s32v[dst] = o.toInt(); - else - var.value.f32v[dst] = o.toFloat(); + switch(var.type) + { + case VarType::Float: var.value.f32v[dst] = o.toFloat(); break; + case VarType::Double: var.value.f64v[dst] = o.toDouble(); break; + case VarType::Half: var.value.f16v[dst] = rdhalf::make(o.toFloat()); break; + case VarType::Bool: var.value.u32v[dst] = o.toBool() ? 1 : 0; break; + case VarType::ULong: var.value.u64v[dst] = o.toULongLong(); break; + case VarType::UInt: var.value.u32v[dst] = o.toUInt(); break; + case VarType::UShort: var.value.u16v[dst] = o.toUInt() & 0xffff; break; + case VarType::UByte: var.value.u8v[dst] = o.toUInt() & 0xff; break; + case VarType::SLong: var.value.s64v[dst] = o.toLongLong(); break; + case VarType::SInt: + var.value.s32v[dst] = o.toInt(); + break; + break; + case VarType::SShort: + var.value.u16v[dst] = (int16_t)qBound((int)INT16_MIN, o.toInt(), (int)INT16_MAX); + break; + case VarType::SByte: + var.value.u8v[dst] = (int8_t)qBound((int)INT8_MIN, o.toInt(), (int)INT8_MAX); + break; + case VarType::GPUPointer: + // treat this as a 64-bit unsigned integer + var.value.u64v[dst] = o.toULongLong(); + break; + case VarType::ConstantBlock: + case VarType::ReadOnlyResource: + case VarType::ReadWriteResource: + case VarType::Sampler: + case VarType::Unknown: + qCritical() << "Unexpected variable type" << ToQStr(var.type) << "in variable" + << (QString)var.name; + break; + } } } } @@ -1469,7 +1487,7 @@ QVariantList GetVariants(ResourceFormat format, const ShaderConstantDescriptor & else if(format.compByteWidth == 4) ret.push_back(readObj(data, end, ok)); else if(format.compByteWidth == 2) - ret.push_back(RENDERDOC_HalfToFloat(readObj(data, end, ok))); + ret.push_back((float)rdhalf::make(readObj(data, end, ok))); } else if(format.compType == CompType::SInt) { @@ -1638,36 +1656,67 @@ QString RowString(const ShaderVariable &v, uint32_t row, VarType type) if(v.type == VarType::GPUPointer) return ToQStr(v.GetPointer()); - if(type == VarType::Double) - return RowValuesToString((int)v.columns, v.displayAsHex, v.value.f64v[row * v.columns + 0], - v.value.f64v[row * v.columns + 1], v.value.f64v[row * v.columns + 2], - v.value.f64v[row * v.columns + 3]); - else if(type == VarType::SLong) - return RowValuesToString((int)v.columns, v.displayAsHex, v.value.s64v[row * v.columns + 0], - v.value.s64v[row * v.columns + 1], v.value.s64v[row * v.columns + 2], - v.value.s64v[row * v.columns + 3]); - else if(type == VarType::ULong) - return RowValuesToString((int)v.columns, v.displayAsHex, v.value.u64v[row * v.columns + 0], - v.value.u64v[row * v.columns + 1], v.value.u64v[row * v.columns + 2], - v.value.u64v[row * v.columns + 3]); - else if(type == VarType::SInt || type == VarType::SShort || type == VarType::SByte) - return RowValuesToString((int)v.columns, v.displayAsHex, v.value.s32v[row * v.columns + 0], - v.value.s32v[row * v.columns + 1], v.value.s32v[row * v.columns + 2], - v.value.s32v[row * v.columns + 3]); - else if(type == VarType::UInt || type == VarType::UShort || type == VarType::UByte) - return RowValuesToString((int)v.columns, v.displayAsHex, v.value.u32v[row * v.columns + 0], - v.value.u32v[row * v.columns + 1], v.value.u32v[row * v.columns + 2], - v.value.u32v[row * v.columns + 3]); - else if(type == VarType::Bool) - return RowValuesToString((int)v.columns, v.displayAsHex, - v.value.u32v[row * v.columns + 0] ? true : false, - v.value.u32v[row * v.columns + 1] ? true : false, - v.value.u32v[row * v.columns + 2] ? true : false, - v.value.u32v[row * v.columns + 3] ? true : false); - else - return RowValuesToString((int)v.columns, v.displayAsHex, v.value.f32v[row * v.columns + 0], - v.value.f32v[row * v.columns + 1], v.value.f32v[row * v.columns + 2], - v.value.f32v[row * v.columns + 3]); + switch(type) + { + case VarType::Float: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.f32v[row * v.columns + 0], + v.value.f32v[row * v.columns + 1], v.value.f32v[row * v.columns + 2], + v.value.f32v[row * v.columns + 3]); + case VarType::Double: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.f64v[row * v.columns + 0], + v.value.f64v[row * v.columns + 1], v.value.f64v[row * v.columns + 2], + v.value.f64v[row * v.columns + 3]); + case VarType::Half: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.f16v[row * v.columns + 0], + v.value.f16v[row * v.columns + 1], v.value.f16v[row * v.columns + 2], + v.value.f16v[row * v.columns + 3]); + case VarType::Bool: + return RowValuesToString((int)v.columns, v.displayAsHex, + v.value.u32v[row * v.columns + 0] ? true : false, + v.value.u32v[row * v.columns + 1] ? true : false, + v.value.u32v[row * v.columns + 2] ? true : false, + v.value.u32v[row * v.columns + 3] ? true : false); + case VarType::ULong: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.u64v[row * v.columns + 0], + v.value.u64v[row * v.columns + 1], v.value.u64v[row * v.columns + 2], + v.value.u64v[row * v.columns + 3]); + case VarType::UInt: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.u32v[row * v.columns + 0], + v.value.u32v[row * v.columns + 1], v.value.u32v[row * v.columns + 2], + v.value.u32v[row * v.columns + 3]); + case VarType::UShort: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.u16v[row * v.columns + 0], + v.value.u16v[row * v.columns + 1], v.value.u16v[row * v.columns + 2], + v.value.u16v[row * v.columns + 3]); + case VarType::UByte: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.u8v[row * v.columns + 0], + v.value.u8v[row * v.columns + 1], v.value.u8v[row * v.columns + 2], + v.value.u8v[row * v.columns + 3]); + case VarType::SLong: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.s64v[row * v.columns + 0], + v.value.s64v[row * v.columns + 1], v.value.s64v[row * v.columns + 2], + v.value.s64v[row * v.columns + 3]); + case VarType::SInt: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.s32v[row * v.columns + 0], + v.value.s32v[row * v.columns + 1], v.value.s32v[row * v.columns + 2], + v.value.s32v[row * v.columns + 3]); + case VarType::SShort: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.s16v[row * v.columns + 0], + v.value.s16v[row * v.columns + 1], v.value.s16v[row * v.columns + 2], + v.value.s16v[row * v.columns + 3]); + case VarType::SByte: + return RowValuesToString((int)v.columns, v.displayAsHex, v.value.s8v[row * v.columns + 0], + v.value.s8v[row * v.columns + 1], v.value.s8v[row * v.columns + 2], + v.value.s8v[row * v.columns + 3]); + case VarType::GPUPointer: return ToQStr(v.GetPointer()); + case VarType::ConstantBlock: + case VarType::ReadOnlyResource: + case VarType::ReadWriteResource: + case VarType::Sampler: + case VarType::Unknown: break; + } + + return lit("???"); } QString VarString(const ShaderVariable &v) diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h index 0036284ab..b9b281708 100644 --- a/qrenderdoc/Code/QRDUtils.h +++ b/qrenderdoc/Code/QRDUtils.h @@ -228,6 +228,7 @@ struct Formatter static void shutdown(); static QString Format(double f, bool hex = false); + static QString Format(rdhalf f, bool hex = false) { return Format((float)f, hex); } static QString HumanFormat(uint64_t u); static QString Format(uint64_t u, bool hex = false) { diff --git a/qrenderdoc/Code/pyrenderdoc/pyconversion.h b/qrenderdoc/Code/pyrenderdoc/pyconversion.h index 0bd5e1540..4f8e6a96b 100644 --- a/qrenderdoc/Code/pyrenderdoc/pyconversion.h +++ b/qrenderdoc/Code/pyrenderdoc/pyconversion.h @@ -364,6 +364,25 @@ struct TypeConversion static PyObject *ConvertToPy(const double &in) { return PyFloat_FromDouble(in); } }; +template <> +struct TypeConversion +{ + static int ConvertFromPy(PyObject *in, rdhalf &out) + { + if(!PyFloat_Check(in)) + return SWIG_TypeError; + + out.set(float(PyFloat_AsDouble(in))); + + if(PyErr_Occurred()) + return SWIG_OverflowError; + + return SWIG_OK; + } + + static PyObject *ConvertToPy(const rdhalf &in) { return PyFloat_FromDouble((float)in); } +}; + // partial specialisation for enums, we just convert as their underlying type, // whatever integer size that happens to be template diff --git a/qrenderdoc/Code/pyrenderdoc/renderdoc.i b/qrenderdoc/Code/pyrenderdoc/renderdoc.i index ac1a4c274..78353135d 100644 --- a/qrenderdoc/Code/pyrenderdoc/renderdoc.i +++ b/qrenderdoc/Code/pyrenderdoc/renderdoc.i @@ -100,6 +100,7 @@ VA_IGNORE_REST_OF_FILE %ignore rdcfixedarray::operator[]; %ignore rdcliteral; %ignore rdcpair; +%ignore rdhalf; %ignore bytebuf; // special handling for RENDERDOC_GetDefaultCaptureOptions to transform output parameter to a return value @@ -331,6 +332,7 @@ TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, ResourceId, 8) TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, bool, 4) TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, bool, 8) TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, float, 16) +TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, rdhalf, 16) TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, int32_t, 16) TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, uint32_t, 16) TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, double, 16) diff --git a/qrenderdoc/Windows/ShaderViewer.cpp b/qrenderdoc/Windows/ShaderViewer.cpp index 1e71044a6..32fe4e210 100644 --- a/qrenderdoc/Windows/ShaderViewer.cpp +++ b/qrenderdoc/Windows/ShaderViewer.cpp @@ -2593,6 +2593,10 @@ bool ShaderViewer::getVar(RDTreeWidgetItem *item, ShaderVariable *var, QString * const QString xyzw = lit("xyzw"); + size_t dataSize = VarTypeByteSize(ret.type); + if(dataSize == 0) + dataSize = 4; + for(uint32_t i = 0; i < mapping.variables.size(); i++) { const DebugVariableReference &r = mapping.variables[i]; @@ -2628,10 +2632,14 @@ bool ShaderViewer::getVar(RDTreeWidgetItem *item, ShaderVariable *var, QString * } } - if(mapping.type == VarType::Double || mapping.type == VarType::ULong) + if(dataSize == 8) ret.value.u64v[i] = reg->value.u64v[r.component]; - else + else if(dataSize == 4) ret.value.u32v[i] = reg->value.u32v[r.component]; + else if(dataSize == 2) + ret.value.u16v[i] = reg->value.u16v[r.component]; + else + ret.value.u8v[i] = reg->value.u8v[r.component]; } else { @@ -3393,7 +3401,7 @@ void ShaderViewer::updateWatchVariables() "(\\[[0-9]+\\])?" // a literal-indexed array expression "\\.?" // optional struct dot ")+)" // 1 or more chained identifiers - "(,[xfiudb])?" // optional typecast + "(,[iduxbof])?" // optional typecast "$")); // end of the line QRegularExpression identifierSliceRE( @@ -3404,7 +3412,7 @@ void ShaderViewer::updateWatchVariables() "(\\[[0-9]+\\])" // or a literal-indexed array expression ")")); // end capture - QRegularExpression swizzleRE(lit("^\\.[xyzwrgba]+$")); + QRegularExpression swizzleRE(lit("^\\.?[xyzwrgba]+$")); QRegularExpressionMatch match = exprRE.match(expr); @@ -3475,7 +3483,9 @@ void ShaderViewer::updateWatchVariables() // member if(swizzleRE.match(identifier).hasMatch() && identifiers.isEmpty()) { - swizzle = identifier.mid(1); + swizzle = identifier; + if(swizzle[0] == QLatin1Char('.')) + swizzle = swizzle.mid(1); break; } @@ -3500,21 +3510,40 @@ void ShaderViewer::updateWatchVariables() if(swizzle.isEmpty()) swizzle = lit("xyzw").left((int)var.columns); + size_t dataSize = VarTypeByteSize(var.type); + if(regcast == QLatin1Char(' ')) { - if(var.type == VarType::Double) - regcast = QLatin1Char('d'); - else if(var.type == VarType::Float || var.type == VarType::Half) - regcast = QLatin1Char('f'); - else if(var.type == VarType::ULong || var.type == VarType::UInt || - var.type == VarType::UShort || var.type == VarType::UByte) - regcast = QLatin1Char('u'); - else if(var.type == VarType::SLong || var.type == VarType::SInt || - var.type == VarType::SShort || var.type == VarType::SByte || - var.type == VarType::Bool) - regcast = QLatin1Char('i'); - else if(var.type == VarType::Unknown) - regcast = ui->intView->isChecked() ? QLatin1Char('i') : QLatin1Char('f'); + switch(var.type) + { + case VarType::Float: + case VarType::Double: + case VarType::Half: regcast = QLatin1Char('f'); break; + case VarType::Bool: + case VarType::ULong: + case VarType::UInt: + case VarType::UShort: + case VarType::UByte: regcast = QLatin1Char('u'); break; + case VarType::SLong: + case VarType::SInt: + case VarType::SShort: + case VarType::SByte: regcast = QLatin1Char('i'); break; + case VarType::GPUPointer: + regcast = QLatin1Char('#'); + dataSize = 8; + break; + case VarType::ConstantBlock: + case VarType::ReadOnlyResource: + case VarType::ReadWriteResource: + case VarType::Sampler: + regcast = QLatin1Char('#'); + dataSize = 4; + break; + case VarType::Unknown: + regcast = ui->intView->isChecked() ? QLatin1Char('i') : QLatin1Char('f'); + dataSize = 4; + break; + } } QString val; @@ -3533,29 +3562,58 @@ void ShaderViewer::updateWatchVariables() if(swiz == QLatin1Char('w') || swiz == QLatin1Char('a')) elindex = 3; - if(regcast == QLatin1Char('i')) + ShaderValue value = {}; + memcpy(&value, var.value.u8v.data() + elindex * dataSize, dataSize); + + if(regcast == QLatin1Char('#')) { - val += Formatter::Format(var.value.s32v[elindex]); + if(var.type == VarType::GPUPointer) + val += ToQStr(var.GetPointer()); + else + val += stringRep(var, 0); + } + else if(regcast == QLatin1Char('i') || regcast == QLatin1Char('d')) + { + if(dataSize == 8) + val += Formatter::Format(value.s64v[0]); + else if(dataSize == 4) + val += Formatter::Format(value.s32v[0]); + else if(dataSize == 2) + val += Formatter::Format(value.s16v[0]); + else + val += Formatter::Format(value.s8v[0]); } else if(regcast == QLatin1Char('f')) { - val += Formatter::Format(var.value.f32v[elindex]); + if(dataSize == 8) + val += Formatter::Format(value.f64v[0]); + else if(dataSize == 4) + val += Formatter::Format(value.f32v[0]); + else + val += Formatter::Format(value.f16v[0]); } else if(regcast == QLatin1Char('u')) { - val += Formatter::Format(var.value.u32v[elindex]); + val += Formatter::Format(value.u64v[0]); } else if(regcast == QLatin1Char('x')) { - val += Formatter::Format(var.value.u32v[elindex], true); + if(dataSize == 8) + val += Formatter::Format(value.u64v[0], true); + else if(dataSize == 4) + val += Formatter::Format(value.u32v[0], true); + else if(dataSize == 2) + val += Formatter::Format(value.u16v[0], true); + else + val += Formatter::Format(value.u8v[0], true); } else if(regcast == QLatin1Char('b')) { - val += QFormatStr("%1").arg(var.value.u32v[elindex], 32, 2, QLatin1Char('0')); + val += QFormatStr("%1").arg(value.u64v[0], (int)dataSize * 8, 2, QLatin1Char('0')); } - else if(regcast == QLatin1Char('d')) + else if(regcast == QLatin1Char('o')) { - val += Formatter::Format(var.value.f64v[elindex]); + val += QFormatStr("0%1").arg(value.u64v[0], 0, 8, QLatin1Char('0')); } if(s < swizzle.count() - 1) @@ -3610,16 +3668,7 @@ RDTreeWidgetItem *ShaderViewer::makeSourceVariableNode(const ShaderVariable &var { QString typeName; - if(var.type == VarType::UInt) - typeName = lit("uint"); - else if(var.type == VarType::SInt) - typeName = lit("int"); - else if(var.type == VarType::Float) - typeName = lit("float"); - else if(var.type == VarType::Double) - typeName = lit("double"); - else if(var.type == VarType::Bool) - typeName = lit("bool"); + typeName = ToQStr(var.type); QString rowTypeName = typeName; @@ -3673,16 +3722,7 @@ RDTreeWidgetItem *ShaderViewer::makeSourceVariableNode(const SourceVariableMappi QString regNames, typeName; QString value; - if(l.type == VarType::UInt) - typeName = lit("uint"); - else if(l.type == VarType::SInt) - typeName = lit("int"); - else if(l.type == VarType::Float) - typeName = lit("float"); - else if(l.type == VarType::Double) - typeName = lit("double"); - else if(l.type == VarType::Bool) - typeName = lit("bool"); + typeName = ToQStr(l.type); QList children; @@ -3852,16 +3892,29 @@ RDTreeWidgetItem *ShaderViewer::makeSourceVariableNode(const SourceVariableMappi regNames += QFormatStr("%1.%2").arg(r.name).arg(xyzw[r.component % 4]); } - if(l.type == VarType::UInt) - value += Formatter::Format(reg->value.u32v[r.component]); - else if(l.type == VarType::SInt) - value += Formatter::Format(reg->value.s32v[r.component]); - else if(l.type == VarType::Bool) - value += Formatter::Format(reg->value.u32v[r.component] ? true : false); - else if(l.type == VarType::Float) - value += Formatter::Format(reg->value.f32v[r.component]); - else if(l.type == VarType::Double) - value += Formatter::Format(reg->value.f64v[r.component]); + switch(l.type) + { + case VarType::Float: value += Formatter::Format(reg->value.f32v[r.component]); break; + case VarType::Double: value += Formatter::Format(reg->value.f64v[r.component]); break; + case VarType::Half: value += Formatter::Format(reg->value.f16v[r.component]); break; + case VarType::Bool: Formatter::Format(reg->value.u32v[r.component] ? true : false); + case VarType::ULong: value += Formatter::Format(reg->value.u64v[r.component]); break; + case VarType::UInt: value += Formatter::Format(reg->value.u32v[r.component]); break; + case VarType::UShort: value += Formatter::Format(reg->value.u16v[r.component]); break; + case VarType::UByte: value += Formatter::Format(reg->value.u8v[r.component]); break; + case VarType::SLong: value += Formatter::Format(reg->value.s64v[r.component]); break; + case VarType::SInt: value += Formatter::Format(reg->value.s32v[r.component]); break; + case VarType::SShort: value += Formatter::Format(reg->value.s16v[r.component]); break; + case VarType::SByte: value += Formatter::Format(reg->value.s8v[r.component]); break; + case VarType::GPUPointer: value += ToQStr(reg->GetPointer()); break; + case VarType::ConstantBlock: + case VarType::ReadOnlyResource: + case VarType::ReadWriteResource: + case VarType::Sampler: value += stringRep(*reg, 0); break; + case VarType::Unknown: + qCritical() << "Unexpected unknown variable" << (QString)l.name; + break; + } } else { diff --git a/renderdoc/api/replay/pipestate.inl b/renderdoc/api/replay/pipestate.inl index 8d145a3de..af834db36 100644 --- a/renderdoc/api/replay/pipestate.inl +++ b/renderdoc/api/replay/pipestate.inl @@ -820,9 +820,9 @@ rdcarray PipeState::GetVertexInputs() const for(uint32_t c = 0; c < compCount; c++) { - if(varType == VarType::Float) + if(varType == VarType::Float || varType == VarType::Double) ret[a].genericValue.floatValue[c] = attrs[i].genericValue.floatValue[c]; - else if(varType == VarType::UInt) + else if(varType == VarType::UInt || varType == VarType::Bool) ret[a].genericValue.uintValue[c] = attrs[i].genericValue.uintValue[c]; else if(varType == VarType::SInt) ret[a].genericValue.intValue[c] = attrs[i].genericValue.intValue[c]; diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index fa3177bc9..8be3bb377 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -47,6 +47,10 @@ typedef void(RENDERDOC_CC *pRENDERDOC_FreeArrayMem)(void *mem); extern "C" RENDERDOC_API void *RENDERDOC_CC RENDERDOC_AllocArrayMem(uint64_t sz); typedef void *(RENDERDOC_CC *pRENDERDOC_AllocArrayMem)(uint64_t sz); + +// similarly these need to be pre-declared for use in rdhalf +extern "C" RENDERDOC_API float RENDERDOC_CC RENDERDOC_HalfToFloat(uint16_t half); +extern "C" RENDERDOC_API uint16_t RENDERDOC_CC RENDERDOC_FloatToHalf(float flt); #endif // declare base types and stringise interface diff --git a/renderdoc/api/replay/shader_types.h b/renderdoc/api/replay/shader_types.h index 08d373e48..8a9a7f323 100644 --- a/renderdoc/api/replay/shader_types.h +++ b/renderdoc/api/replay/shader_types.h @@ -109,6 +109,31 @@ struct BindpointIndex DECLARE_REFLECTION_STRUCT(BindpointIndex); +struct rdhalf +{ +#if !defined(SWIG) + static rdhalf make(const uint16_t &u) + { + rdhalf ret; + ret.storage = u; + return ret; + } + static rdhalf make(const float &f) + { + rdhalf ret; + ret.storage = RENDERDOC_FloatToHalf(f); + return ret; + } + void set(const uint16_t &u) { storage = u; } + void set(const float &f) { storage = RENDERDOC_FloatToHalf(f); } +#endif + explicit operator float() const { return RENDERDOC_HalfToFloat(storage); } + explicit operator uint16_t() const { return storage; } +private: + uint16_t storage; +}; +DECLARE_STRINGISE_TYPE(rdhalf); + DOCUMENT("A C union that holds 16 values, with each different basic variable type."); union ShaderValue { @@ -136,6 +161,12 @@ union ShaderValue )"); rdcfixedarray f64v; + DOCUMENT(R"(16-tuple of 16-bit half-precision float values. + +:type: Tuple[int,...] +)"); + rdcfixedarray f16v; + DOCUMENT(R"(16-tuple of 64-bit unsigned integer values. :type: Tuple[int,...] diff --git a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp index b34e7c6da..33fca9226 100644 --- a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp @@ -1736,7 +1736,7 @@ static void floatAppendToString(const Type *t, const ShaderValue &val, uint32_t // dxc/llvm always prints half floats as their 16-bit hex representation. if(t->bitWidth == 16) { - ret += StringFormat::Fmt("0xH%04X", val.u64v[i]); + ret += StringFormat::Fmt("0xH%04X", val.u32v[i]); return; } #endif diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_glsl450.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_glsl450.cpp index bd39d4829..ea9bd3fe0 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_glsl450.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_glsl450.cpp @@ -295,7 +295,7 @@ ShaderVariable Determinant(ThreadState &state, uint32_t, const rdcarray &par if(!warned) { warned = true; - RDCLOG("Calculating determinant in floats instead of %s", ToStr(m.type).c_str()); + RDCLOG("Calculating determinant at float precision instead of %s", ToStr(m.type).c_str()); } for(uint8_t c = 0; c < m.rows * m.columns; c++) @@ -346,7 +346,7 @@ ShaderVariable MatrixInverse(ThreadState &state, uint32_t, const rdcarray &p if(!warned) { warned = true; - RDCLOG("Calculating determinant in floats instead of %s", ToStr(m.type).c_str()); + RDCLOG("Calculating matrix inverse at float precision instead of %s", ToStr(m.type).c_str()); } for(uint8_t c = 0; c < m.rows * m.columns; c++) diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp index 3e21d9c28..902caee9f 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp @@ -2366,7 +2366,7 @@ uint32_t Debugger::ApplyDerivatives(uint32_t quadIndex, const Decorations &curDe ApplyDerivative(activeLaneIndex, quadIndex, outVar.value.f32v.data(), derivs); else if(outVar.type == VarType::Half) ApplyDerivative(activeLaneIndex, quadIndex, - (half_float::half *)outVar.value.u16v.data(), derivs); + (half_float::half *)outVar.value.f16v.data(), derivs); else if(outVar.type == VarType::Double) ApplyDerivative(activeLaneIndex, quadIndex, outVar.value.f64v.data(), derivs); } diff --git a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp index 06469512a..0ead3f723 100644 --- a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include "common/formatting.h" +#include "maths/half_convert.h" #include "spirv_op_helpers.h" #include "spirv_reflect.h" @@ -434,16 +435,16 @@ rdcstr Reflector::Disassemble(const rdcstr &entryPoint, switch(type.scalar().Type()) { - case VarType::Float: - case VarType::Half: ret += ToStr(value.f32v[0]); break; + case VarType::Half: ret += ToStr(value.f16v[0]); break; + case VarType::Float: ret += ToStr(value.f32v[0]); break; case VarType::Double: ret += ToStr(value.f64v[0]); break; - case VarType::SInt: - case VarType::SShort: - case VarType::SByte: ret += ToStr(value.s32v[0]); break; + case VarType::SInt: ret += ToStr(value.s32v[0]); break; + case VarType::SShort: ret += ToStr(value.s16v[0]); break; + case VarType::SByte: ret += ToStr(value.s8v[0]); break; case VarType::Bool: ret += value.u32v[0] ? "true" : "false"; break; - case VarType::UInt: - case VarType::UShort: - case VarType::UByte: ret += ToStr(value.u32v[0]); break; + case VarType::UInt: ret += ToStr(value.u32v[0]); break; + case VarType::UShort: ret += ToStr(value.u16v[0]); break; + case VarType::UByte: ret += ToStr(value.u8v[0]); break; case VarType::SLong: ret += ToStr(value.s64v[0]); break; case VarType::Unknown: case VarType::GPUPointer: @@ -1632,24 +1633,24 @@ rdcstr Reflector::StringiseConstant(rdcspv::Id id) const switch(value.type) { - case VarType::Float: - case VarType::Half: return ToStr(value.value.f32v[0]); + case VarType::Half: return ToStr(value.value.f16v[0]); break; + case VarType::Float: return ToStr(value.value.f32v[0]); case VarType::Double: return ToStr(value.value.f64v[0]); - case VarType::SInt: - case VarType::SShort: - case VarType::SByte: return ToStr(value.value.s32v[0]); + case VarType::SInt: return ToStr(value.value.s32v[0]); + case VarType::SShort: return ToStr(value.value.s16v[0]); + case VarType::SByte: return ToStr(value.value.s8v[0]); case VarType::Bool: return value.value.u32v[0] ? "true" : "false"; - case VarType::UInt: - case VarType::UShort: - case VarType::UByte: return ToStr(value.value.u32v[0]); + case VarType::UInt: return ToStr(value.value.u32v[0]); + case VarType::UShort: return ToStr(value.value.u16v[0]); + case VarType::UByte: return ToStr(value.value.u8v[0]); case VarType::SLong: return ToStr(value.value.s64v[0]); + case VarType::ULong: return ToStr(value.value.u64v[0]); case VarType::Unknown: case VarType::GPUPointer: case VarType::ConstantBlock: case VarType::ReadOnlyResource: case VarType::ReadWriteResource: - case VarType::Sampler: - case VarType::ULong: return ToStr(value.value.u64v[0]); + case VarType::Sampler: return "???"; } } else if(type.type == DataType::VectorType) @@ -1659,24 +1660,24 @@ rdcstr Reflector::StringiseConstant(rdcspv::Id id) const { switch(value.type) { - case VarType::Float: - case VarType::Half: ret += ToStr(value.value.f32v[i]); break; + case VarType::Half: ret += ToStr(value.value.f16v[i]); break; + case VarType::Float: ret += ToStr(value.value.f32v[i]); break; case VarType::Double: ret += ToStr(value.value.f64v[i]); break; - case VarType::SInt: - case VarType::SShort: - case VarType::SByte: ret += ToStr(value.value.s32v[i]); break; - case VarType::UInt: - case VarType::UShort: - case VarType::UByte: ret += ToStr(value.value.u32v[i]); break; + case VarType::SInt: ret += ToStr(value.value.s32v[i]); break; + case VarType::SShort: ret += ToStr(value.value.s16v[i]); break; + case VarType::SByte: ret += ToStr(value.value.s8v[i]); break; + case VarType::Bool: ret += value.value.u32v[i] ? "true" : "false"; break; + case VarType::UInt: ret += ToStr(value.value.u32v[i]); break; + case VarType::UShort: ret += ToStr(value.value.u16v[i]); break; + case VarType::UByte: ret += ToStr(value.value.u8v[i]); break; case VarType::SLong: ret += ToStr(value.value.s64v[i]); break; - case VarType::Bool: return value.value.u32v[0] ? "true" : "false"; + case VarType::ULong: ret += ToStr(value.value.u64v[i]); break; case VarType::Unknown: case VarType::GPUPointer: case VarType::ConstantBlock: case VarType::ReadOnlyResource: case VarType::ReadWriteResource: - case VarType::Sampler: - case VarType::ULong: ret += ToStr(value.value.u64v[i]); break; + case VarType::Sampler: ret += "???"; break; } if(i + 1 < value.columns) ret += ", "; diff --git a/renderdoc/driver/shaders/spirv/spirv_processor.cpp b/renderdoc/driver/shaders/spirv/spirv_processor.cpp index db79d76c0..c3e394aa9 100644 --- a/renderdoc/driver/shaders/spirv/spirv_processor.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_processor.cpp @@ -26,6 +26,7 @@ #include "common/formatting.h" #include "maths/half_convert.h" #include "spirv_op_helpers.h" +#include "var_dispatch_helpers.h" namespace rdcspv { @@ -39,15 +40,20 @@ static void ConstructCompositeConstant(ShaderVariable &v, const rdcarray(); case VarType::Double: return scalar(); - case VarType::Half: return Scalar(Op::TypeFloat, 16, false); + case VarType::Half: return scalar(); case VarType::SInt: return scalar(); case VarType::UInt: return scalar(); case VarType::SShort: return scalar(); @@ -667,7 +673,7 @@ void Processor::RegisterOp(Iter it) else { // if it's signed, sign extend - if(type.scalar().signedness && type.scalar().width < 16) + if(type.scalar().signedness && type.scalar().width <= 16) { // is the top bit set? if(v.value.u32v[0] & (1 << (type.scalar().width - 1))) @@ -1009,6 +1015,8 @@ ShaderVariable Processor::EvaluateConstant(Id constID, const rdcarray(param, i); + IMPL_FOR_INT_TYPES_FOR_TYPE(_IMPL, param.type); + +#undef _IMPL +#define _IMPL(I, S, U) comp(ret, i) = (U)x; + IMPL_FOR_INT_TYPES_FOR_TYPE(_IMPL, ret.type); } - else if(paramType.scalar().width == 32) + else if(specop.op == Op::SConvert) { - if(retType.scalar().width == 64) - ret.value.f64v[0] = param.value.f32v[0]; - else - ret.value.f32v[0] = param.value.f32v[0]; + int64_t x = 0; + +#undef _IMPL +#define _IMPL(I, S, U) x = comp(param, i); + IMPL_FOR_INT_TYPES_FOR_TYPE(_IMPL, param.type); + +#undef _IMPL +#define _IMPL(I, S, U) comp(ret, i) = (S)x; + IMPL_FOR_INT_TYPES_FOR_TYPE(_IMPL, ret.type); } - else + else if(specop.op == Op::FConvert) { - if(retType.scalar().width == 64) - ret.value.f64v[0] = param.value.f64v[0]; - else - ret.value.f32v[0] = (float)param.value.f64v[0]; + double x = 0.0; + +#undef _IMPL +#define _IMPL(T) x = comp(param, i); + IMPL_FOR_FLOAT_TYPES_FOR_TYPE(_IMPL, param.type); + +#undef _IMPL +#define _IMPL(T) comp(ret, i) = (T)x; + // IMPL_FOR_FLOAT_TYPES_FOR_TYPE(_IMPL, ret.type); + + if(ret.type == VarType::Float) + comp(ret, i) = (float)x; + else if(ret.type == VarType::Half) + comp(ret, i) = (float)x; + else if(ret.type == VarType::Double) + comp(ret, i) = (double)x; } } @@ -1379,8 +1422,10 @@ ShaderVariable Processor::EvaluateConstant(Id constID, const rdcarray inline half_float::half &comp(ShaderVariable &var, uint32_t c) { half_float::half *ret; - uint16_t *comp = &var.value.u16v[c]; + rdhalf *comp = &var.value.f16v[c]; memcpy(&ret, &comp, sizeof(ret)); return *ret; } @@ -72,7 +72,7 @@ template <> inline half_float::half comp(const ShaderVariable &var, uint32_t c) { half_float::half ret; - uint16_t comp = var.value.u16v[c]; + rdhalf comp = var.value.f16v[c]; memcpy(&ret, &comp, sizeof(ret)); return ret; } @@ -116,7 +116,7 @@ inline float floatComp(const ShaderVariable &var, uint32_t c) if(var.type == VarType::Float) return var.value.f32v[c]; else if(var.type == VarType::Half) - return ConvertFromHalf(var.value.u16v[c]); + return (float)var.value.f16v[c]; else if(var.type == VarType::Double) return (float)var.value.f64v[c]; else @@ -158,7 +158,7 @@ inline void setFloatComp(ShaderVariable &var, uint32_t c, float f) if(var.type == VarType::Float) var.value.f32v[c] = f; else if(var.type == VarType::Half) - var.value.u16v[c] = ConvertToHalf(f); + var.value.f16v[c].set(f); else if(var.type == VarType::Double) var.value.f64v[c] = f; } @@ -196,7 +196,7 @@ inline void set0001(ShaderVariable &result) if(result.type == VarType::Float) result.value.f32v[3] = 1.0f; else if(result.type == VarType::Half) - result.value.u16v[3] = ConvertToHalf(1.0f); + result.value.f16v[3].set(1.0f); else if(result.type == VarType::Double) result.value.f64v[3] = 1.0; else diff --git a/renderdoc/driver/vulkan/vk_shaderdebug.cpp b/renderdoc/driver/vulkan/vk_shaderdebug.cpp index 5f2a4ab9e..99c0e9392 100644 --- a/renderdoc/driver/vulkan/vk_shaderdebug.cpp +++ b/renderdoc/driver/vulkan/vk_shaderdebug.cpp @@ -831,12 +831,8 @@ public: { const ShaderVariable &biasVar = lane.GetSrc(operands.bias); - float bias = biasVar.value.f32v[0]; // silently cast parameters to 32-bit floats - if(biasVar.type == VarType::Half) - bias = ConvertFromHalf(biasVar.value.u16v[0]); - else if(biasVar.type == VarType::Double) - bias = (float)biasVar.value.f64v[0]; + float bias = floatComp(biasVar, 0); if(bias != 0.0f) { @@ -1001,24 +997,11 @@ public: case rdcspv::Op::ImageDrefGather: { // silently cast parameters to 32-bit floats - if(uv.type == VarType::Float) - { - for(int i = 0; i < coords; i++) - uniformParams.uvwa[i] = uv.value.f32v[i]; - } - else if(uv.type == VarType::Half) - { - for(int i = 0; i < coords; i++) - uniformParams.uvwa[i] = ConvertFromHalf(uv.value.u16v[i]); - } - else if(uv.type == VarType::Double) - { - for(int i = 0; i < coords; i++) - uniformParams.uvwa[i] = (float)uv.value.f64v[i]; - } + for(int i = 0; i < coords; i++) + uniformParams.uvwa[i] = floatComp(uv, i); if(useCompare) - uniformParams.compare = compare.value.f32v[0]; + uniformParams.compare = floatComp(compare, 0); constParams.gatherChannel = gatherChannel; @@ -1108,21 +1091,8 @@ public: case rdcspv::Op::ImageSampleProjDrefImplicitLod: { // silently cast parameters to 32-bit floats - if(uv.type == VarType::Float) - { - for(int i = 0; i < coords; i++) - uniformParams.uvwa[i] = uv.value.f32v[i]; - } - else if(uv.type == VarType::Half) - { - for(int i = 0; i < coords; i++) - uniformParams.uvwa[i] = ConvertFromHalf(uv.value.u16v[i]); - } - else if(uv.type == VarType::Double) - { - for(int i = 0; i < coords; i++) - uniformParams.uvwa[i] = (float)uv.value.f64v[i]; - } + for(int i = 0; i < coords; i++) + uniformParams.uvwa[i] = floatComp(uv, i); if(proj) { @@ -1132,11 +1102,7 @@ public: // do the divide ourselves rather than severely complicating the sample shader (as proj // variants need non-arrayed textures) - float q = uv.value.f32v[coords]; - if(uv.type == VarType::Half) - q = ConvertFromHalf(uv.value.u16v[coords]); - else if(uv.type == VarType::Double) - q = (float)uv.value.f64v[coords]; + float q = floatComp(uv, coords); uniformParams.uvwa[0] /= q; uniformParams.uvwa[1] /= q; @@ -1147,34 +1113,22 @@ public: { const ShaderVariable &minLodVar = lane.GetSrc(operands.minLod); - uniformParams.minlod = minLodVar.value.f32v[0]; // silently cast parameters to 32-bit floats - if(minLodVar.type == VarType::Half) - uniformParams.minlod = ConvertFromHalf(minLodVar.value.u16v[0]); - else if(minLodVar.type == VarType::Double) - uniformParams.minlod = (float)minLodVar.value.f64v[0]; + uniformParams.minlod = floatComp(minLodVar, 0); } if(useCompare) { - uniformParams.compare = compare.value.f32v[0]; // silently cast parameters to 32-bit floats - if(compare.type == VarType::Half) - uniformParams.compare = ConvertFromHalf(compare.value.u16v[0]); - else if(compare.type == VarType::Double) - uniformParams.compare = (float)compare.value.f64v[0]; + uniformParams.compare = floatComp(compare, 0); } if(operands.flags & rdcspv::ImageOperands::Lod) { const ShaderVariable &lodVar = lane.GetSrc(operands.lod); - uniformParams.lod = lodVar.value.f32v[0]; // silently cast parameters to 32-bit floats - if(lodVar.type == VarType::Half) - uniformParams.lod = ConvertFromHalf(lodVar.value.u16v[0]); - else if(lodVar.type == VarType::Double) - uniformParams.lod = (float)lodVar.value.f64v[0]; + uniformParams.lod = floatComp(lodVar, 0); constParams.useGradOrGatherOffsets = VK_FALSE; } else if(operands.flags & rdcspv::ImageOperands::Grad) @@ -1186,29 +1140,10 @@ public: // silently cast parameters to 32-bit floats RDCASSERTEQUAL(ddx.type, ddy.type); - if(ddx.type == VarType::Float) + for(int i = 0; i < gradCoords; i++) { - for(int i = 0; i < gradCoords; i++) - { - uniformParams.ddx[i] = ddx.value.f32v[i]; - uniformParams.ddy[i] = ddy.value.f32v[i]; - } - } - else if(ddx.type == VarType::Half) - { - for(int i = 0; i < gradCoords; i++) - { - uniformParams.ddx[i] = ConvertFromHalf(ddx.value.u16v[i]); - uniformParams.ddy[i] = ConvertFromHalf(ddy.value.u16v[i]); - } - } - else if(ddx.type == VarType::Double) - { - for(int i = 0; i < gradCoords; i++) - { - uniformParams.ddx[i] = (float)ddx.value.f64v[i]; - uniformParams.ddy[i] = (float)ddy.value.f64v[i]; - } + uniformParams.ddx[i] = floatComp(ddx, i); + uniformParams.ddy[i] = floatComp(ddy, i); } } @@ -1220,29 +1155,10 @@ public: // silently cast parameters to 32-bit floats RDCASSERTEQUAL(ddxCalc.type, ddyCalc.type); - if(ddxCalc.type == VarType::Float) + for(int i = 0; i < gradCoords; i++) { - for(int i = 0; i < gradCoords; i++) - { - uniformParams.ddx[i] = ddxCalc.value.f32v[i]; - uniformParams.ddy[i] = ddyCalc.value.f32v[i]; - } - } - else if(ddxCalc.type == VarType::Half) - { - for(int i = 0; i < gradCoords; i++) - { - uniformParams.ddx[i] = ConvertFromHalf(ddxCalc.value.u16v[i]); - uniformParams.ddy[i] = ConvertFromHalf(ddyCalc.value.u16v[i]); - } - } - else if(ddxCalc.type == VarType::Double) - { - for(int i = 0; i < gradCoords; i++) - { - uniformParams.ddx[i] = (float)ddxCalc.value.f64v[i]; - uniformParams.ddy[i] = (float)ddyCalc.value.f64v[i]; - } + uniformParams.ddx[i] = floatComp(ddxCalc, i); + uniformParams.ddy[i] = floatComp(ddyCalc, i); } } @@ -1446,20 +1362,8 @@ public: return false; // convert float results, we did all sampling at 32-bit precision - if(output.type == VarType::Half) - { - for(uint8_t c = 0; c < 4; c++) - output.value.u16v[c] = ConvertToHalf(ret[c]); - } - else if(output.type == VarType::Double) - { - for(uint8_t c = 0; c < 4; c++) - output.value.f64v[c] = ret[c]; - } - else - { - memcpy(output.value.u32v.data(), ret, sizeof(Vec4f)); - } + for(uint8_t c = 0; c < 4; c++) + setFloatComp(output, c, ret[c]); m_DebugData.ReadbackBuffer.Unmap(); diff --git a/renderdoc/replay/replay_driver.cpp b/renderdoc/replay/replay_driver.cpp index 4167c612a..87b6cd04a 100644 --- a/renderdoc/replay/replay_driver.cpp +++ b/renderdoc/replay/replay_driver.cpp @@ -373,7 +373,6 @@ void StandardFillCBufferVariable(ResourceId shader, const ShaderConstantDescript const size_t avail = data.size() - dataOffset; byte *dstData = outvar.value.u8v.data(); - const size_t dstStride = elemByteSize == 8 ? 8 : 4; // each secondaryDim element (row or column) is stored in a primaryDim-vector. // We copy each vector member individually to account for smaller than uint32 sized types. @@ -382,7 +381,7 @@ void StandardFillCBufferVariable(ResourceId shader, const ShaderConstantDescript for(uint32_t p = 0; p < primaryDim; p++) { const size_t srcOffset = matStride * s + p * elemByteSize; - const size_t dstOffset = (primaryDim * s + p) * dstStride; + const size_t dstOffset = (primaryDim * s + p) * elemByteSize; if(srcOffset + elemByteSize <= avail) memcpy(dstData + dstOffset, srcData + srcOffset, elemByteSize); @@ -400,40 +399,23 @@ void StandardFillCBufferVariable(ResourceId shader, const ShaderConstantDescript for(size_t ci = 0; ci < cols; ci++) outvar.value.u64v[ri * cols + ci] = tmp.value.u64v[ci * rows + ri]; } - else + else if(elemByteSize == 4) { for(size_t ri = 0; ri < rows; ri++) for(size_t ci = 0; ci < cols; ci++) outvar.value.u32v[ri * cols + ci] = tmp.value.u32v[ci * rows + ri]; } - } - - // special case - decode halfs in-place, sign extend signed < 4 byte integers - if(type == VarType::Half) - { - for(size_t ri = 0; ri < rows; ri++) + else if(elemByteSize == 2) { - for(size_t ci = 0; ci < cols; ci++) - { - outvar.value.f32v[ri * cols + ci] = - ConvertFromHalf((uint16_t)outvar.value.u32v[ri * cols + ci]); - } + for(size_t ri = 0; ri < rows; ri++) + for(size_t ci = 0; ci < cols; ci++) + outvar.value.u16v[ri * cols + ci] = tmp.value.u16v[ci * rows + ri]; } - } - else if(type == VarType::SShort || type == VarType::SByte) - { - const uint32_t testMask = (type == VarType::SShort ? 0x8000 : 0x80); - const uint32_t extendMask = (type == VarType::SShort ? 0xffff0000 : 0xffffff00); - - for(size_t ri = 0; ri < rows; ri++) + else if(elemByteSize == 1) { - for(size_t ci = 0; ci < cols; ci++) - { - uint32_t &u = outvar.value.u32v[ri * cols + ci]; - - if(u & testMask) - u |= extendMask; - } + for(size_t ri = 0; ri < rows; ri++) + for(size_t ci = 0; ci < cols; ci++) + outvar.value.u8v[ri * cols + ci] = tmp.value.u8v[ci * rows + ri]; } } } @@ -483,6 +465,8 @@ static void StandardFillCBufferVariables(ResourceId shader, const rdcarray +rdcstr DoStringise(const int8_t &el) +{ + return StringFormat::Fmt("%hhd", el); +} + template <> rdcstr DoStringise(const uint16_t &el) { @@ -984,6 +990,12 @@ rdcstr DoStringise(const float &el) return StringFormat::Fmt("%0.4f", el); } +template <> +rdcstr DoStringise(const rdhalf &el) +{ + return StringFormat::Fmt("%0.4f", (float)el); +} + template <> rdcstr DoStringise(const double &el) { diff --git a/util/test/rdtest/testcase.py b/util/test/rdtest/testcase.py index 09a22c5ce..f8ca829a9 100644 --- a/util/test/rdtest/testcase.py +++ b/util/test/rdtest/testcase.py @@ -42,15 +42,39 @@ class ShaderVariableCheck: def value(self, value_: list): count = len(value_) if isinstance(value_[0], float): - if list(self.var.value.f32v[0:count]) != list(value_): + vals = [] + if self.var.type == rd.VarType.Float: + vals = list(self.var.value.f32v[0:count]) + elif self.var.type == rd.VarType.Double: + vals = list(self.var.value.f64v[0:count]) + elif self.var.type == rd.VarType.Half: + vals = list(self.var.value.f16v[0:count]) + + if vals != list(value_): raise TestFailureException("Float variable {} value mismatch, expected {} but got {}" .format(self.var.name, value_, self.var.value.f32v[0:count])) else: - # hack - check signed and unsigned values - if list(self.var.value.s32v[0:count] ) != list(value_) and list(self.var.value.u32v[0:count]) != list(value_): - raise TestFailureException("Int variable {} value mismatch, expected {} but got {} / {}" - .format(self.var.name, value_, self.var.value.s32v[0:count], - self.var.value.u32v[0:count])) + vals = [] + if self.var.type == rd.VarType.UInt or self.var.type == rd.VarType.Bool: + vals = list(self.var.value.u32v[0:count]) + elif self.var.type == rd.VarType.ULong: + vals = list(self.var.value.u64v[0:count]) + elif self.var.type == rd.VarType.UShort: + vals = list(self.var.value.u16v[0:count]) + elif self.var.type == rd.VarType.UByte: + vals = list(self.var.value.u8v[0:count]) + elif self.var.type == rd.VarType.SInt: + vals = list(self.var.value.s32v[0:count]) + elif self.var.type == rd.VarType.SLong: + vals = list(self.var.value.s64v[0:count]) + elif self.var.type == rd.VarType.SShort: + vals = list(self.var.value.s16v[0:count]) + elif self.var.type == rd.VarType.SByte: + vals = list(self.var.value.s8v[0:count]) + + if vals != list(value_): + raise TestFailureException("Int variable {} value mismatch, expected {} but got {}" + .format(self.var.name, value_, vals)) return self