diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index 3182cd32c..d217b9625 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -1451,7 +1451,7 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI if(rtView != NULL) uavslot = 1; - extractHlsl += "struct PSInitialData { uint hit; float3 pos; uint prim; uint fface; uint sample; uint covge; float derivValid; PSInput IN; PSInput INddx; PSInput INddy; };\n\n"; + extractHlsl += "struct PSInitialData { uint hit; float3 pos; uint prim; uint fface; uint sample; uint covge; float derivValid; PSInput IN; PSInput INddx; PSInput INddy; PSInput INddxfine; PSInput INddyfine; };\n\n"; extractHlsl += "RWStructuredBuffer PSInitialBuffer : register(u" + ToStr::Get(uavslot) + ");\n\n"; extractHlsl += "void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim : SV_PrimitiveID, uint sample : SV_SampleIndex, uint covge : SV_Coverage, bool fface : SV_IsFrontFace)\n{\n"; extractHlsl += " uint idx = " + ToStr::Get(overdrawLevels) + ";\n"; @@ -1467,11 +1467,16 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI extractHlsl += " PSInitialBuffer[idx].derivValid = ddx(debug_pixelPos.x);\n"; extractHlsl += " PSInitialBuffer[idx].INddx = (PSInput)0;\n"; extractHlsl += " PSInitialBuffer[idx].INddy = (PSInput)0;\n"; + extractHlsl += " PSInitialBuffer[idx].INddxfine = (PSInput)0;\n"; + extractHlsl += " PSInitialBuffer[idx].INddyfine = (PSInput)0;\n"; + for(size_t i=0; i < floatInputs.size(); i++) { const string &name = floatInputs[i]; extractHlsl += " PSInitialBuffer[idx].INddx." + name + " = ddx(IN." + name + ");\n"; extractHlsl += " PSInitialBuffer[idx].INddy." + name + " = ddy(IN." + name + ");\n"; + extractHlsl += " PSInitialBuffer[idx].INddxfine." + name + " = ddx_fine(IN." + name + ");\n"; + extractHlsl += " PSInitialBuffer[idx].INddyfine." + name + " = ddy_fine(IN." + name + ");\n"; } extractHlsl += "\n}"; @@ -1484,7 +1489,7 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI + sizeof(uint32_t) // uint sample; + sizeof(uint32_t) // uint covge; + sizeof(float) // float derivValid; - + structureStride*3; // PSInput IN, INddx, INddy; + + structureStride*5; // PSInput IN, INddx, INddy, INddxfine, INddyfine; HRESULT hr = S_OK; @@ -1588,6 +1593,7 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI State quad[4]; // figure out the TL pixel's coords. Assume even top left (towards 0,0) + // this isn't spec'd but is a reasonable assumption. int xTL = x&(~1); int yTL = y&(~1); @@ -1734,6 +1740,32 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI quad[i].SetHelper(); } + // We make the assumption that the coarse derivatives are + // generated from (0,0) in the quad, and fine derivatives + // are generated from the destination index and its + // neighbours in X and Y. + // This isn't spec'd but we must assume something and this + // will hopefully get us closest to reproducing actual + // results. + // + // For debugging, we need members of the quad to be able + // to generate coarse and fine derivatives. + // + // For (0,0) we only need the coarse derivatives to get + // our neighbours (1,0) and (0,1) which will give us + // coarse and fine derivatives being identical. + // + // For the others we will need to use a combination of + // coarse and fine derivatives to get the diagonal element + // in the quad. E.g. for (1,1): + // + // (1,0) = (1,1) - ddx_fine + // (0,1) = (1,1) - ddy_fine + // (0,0) = (1,1) - ddy_fine - ddx_coarse + // + // This only works if coarse and fine are calculated as we + // are assuming. + ddx = (float *)data; for(size_t i=0; i < initialValues.size(); i++) @@ -1742,8 +1774,7 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI if(initialValues[i].reg >= 0) { - // left - if(destIdx == 0 || destIdx == 2) + if(destIdx == 0) { for(int w=0; w < initialValues[i].numwords; w++) { @@ -1751,7 +1782,7 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI traces[3].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] += ddx[w]; } } - else + else if(destIdx == 1) { for(int w=0; w < initialValues[i].numwords; w++) { @@ -1759,6 +1790,20 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI traces[2].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] -= ddx[w]; } } + else if(destIdx == 2) + { + for(int w=0; w < initialValues[i].numwords; w++) + { + traces[1].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] += ddx[w]; + } + } + else if(destIdx == 3) + { + for(int w=0; w < initialValues[i].numwords; w++) + { + traces[0].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] -= ddx[w]; + } + } } ddx += initialValues[i].numwords; @@ -1772,8 +1817,7 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI if(initialValues[i].reg >= 0) { - // top - if(destIdx == 0 || destIdx == 1) + if(destIdx == 0) { for(int w=0; w < initialValues[i].numwords; w++) { @@ -1781,7 +1825,14 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI traces[3].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] += ddy[w]; } } - else + else if(destIdx == 1) + { + for(int w=0; w < initialValues[i].numwords; w++) + { + traces[2].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] += ddy[w]; + } + } + else if(destIdx == 2) { for(int w=0; w < initialValues[i].numwords; w++) { @@ -1793,6 +1844,61 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI ddy += initialValues[i].numwords; } + + float *ddxfine = ddy; + + for(size_t i=0; i < initialValues.size(); i++) + { + if(!initialValues[i].included) continue; + + if(initialValues[i].reg >= 0) + { + if(destIdx == 2) + { + for(int w=0; w < initialValues[i].numwords; w++) + { + traces[3].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] += ddxfine[w]; + } + } + else if(destIdx == 3) + { + for(int w=0; w < initialValues[i].numwords; w++) + { + traces[2].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] -= ddxfine[w]; + } + } + } + + ddxfine += initialValues[i].numwords; + } + + float *ddyfine = ddxfine; + + for(size_t i=0; i < initialValues.size(); i++) + { + if(!initialValues[i].included) continue; + + if(initialValues[i].reg >= 0) + { + if(destIdx == 1) + { + for(int w=0; w < initialValues[i].numwords; w++) + { + traces[3].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] += ddyfine[w]; + } + } + else if(destIdx == 3) + { + for(int w=0; w < initialValues[i].numwords; w++) + { + traces[1].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] -= ddyfine[w]; + traces[0].inputs[initialValues[i].reg].value.fv[initialValues[i].elem+w] -= ddyfine[w]; + } + } + } + + ddyfine += initialValues[i].numwords; + } } vector states; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index 1c3229a88..6b13a1305 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -703,14 +703,20 @@ void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const Shad } } -ShaderVariable State::DDX(State quad[4], const DXBC::ASMOperand &oper, const DXBC::ASMOperation &op) const +ShaderVariable State::DDX(bool fine, State quad[4], const DXBC::ASMOperand &oper, const DXBC::ASMOperation &op) const { ShaderVariable ret; VarType optype = OperationType(op.operation); - // left pixel in the quad - if(quadIndex % 2 == 0) + if(!fine) + { + // use top-left pixel's neighbours + ret = + sub(quad[1].GetSrc(oper, op), quad[0].GetSrc(oper, op), optype); + } + // find direct neighbours - left pixel in the quad + else if(quadIndex % 2 == 0) { ret = sub(quad[quadIndex+1].GetSrc(oper, op), quad[quadIndex].GetSrc(oper, op), optype); @@ -724,14 +730,20 @@ ShaderVariable State::DDX(State quad[4], const DXBC::ASMOperand &oper, const DXB return ret; } -ShaderVariable State::DDY(State quad[4], const DXBC::ASMOperand &oper, const DXBC::ASMOperation &op) const +ShaderVariable State::DDY(bool fine, State quad[4], const DXBC::ASMOperand &oper, const DXBC::ASMOperation &op) const { ShaderVariable ret; VarType optype = OperationType(op.operation); - - // top pixel in the quad - if(quadIndex / 2 == 0) + + if(!fine) + { + // use top-left pixel's neighbours + ret = + sub(quad[2].GetSrc(oper, op), quad[0].GetSrc(oper, op), optype); + } + // find direct neighbours - top pixel in the quad + else if(quadIndex / 2 == 0) { ret = sub(quad[quadIndex+2].GetSrc(oper, op), quad[quadIndex].GetSrc(oper, op), optype); @@ -1861,7 +1873,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const if(quad == NULL) RDCERR("Attempt to use derivative instruction not in pixel shader. Undefined results will occur!"); else - s.SetDst(op.operands[0], op, s.DDX(quad, op.operands[1], op)); + s.SetDst(op.operands[0], op, s.DDX(op.operation == OPCODE_DERIV_RTX_FINE, quad, op.operands[1], op)); break; case OPCODE_DERIV_RTY: case OPCODE_DERIV_RTY_COARSE: @@ -1869,7 +1881,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const if(quad == NULL) RDCERR("Attempt to use derivative instruction not in pixel shader. Undefined results will occur!"); else - s.SetDst(op.operands[0], op, s.DDY(quad, op.operands[1], op)); + s.SetDst(op.operands[0], op, s.DDY(op.operation == OPCODE_DERIV_RTY_FINE, quad, op.operands[1], op)); break; ///////////////////////////////////////////////////////////////////////////////////////////////////// @@ -3539,8 +3551,9 @@ State State::GetNext(GlobalState &global, State quad[4]) const } else { - ddxCalc = s.DDX(quad, op.operands[1], op); - ddyCalc = s.DDY(quad, op.operands[1], op); + // texture samples use coarse derivatives + ddxCalc = s.DDX(false, quad, op.operands[1], op); + ddyCalc = s.DDY(false, quad, op.operands[1], op); } } else if(op.operation == OPCODE_SAMPLE_D) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.h b/renderdoc/driver/shaders/dxbc/dxbc_debug.h index 9c0284486..891c44ca2 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.h @@ -163,8 +163,8 @@ class State : public ShaderDebugState // negation/abs functions ShaderVariable GetSrc(const DXBC::ASMOperand &oper, const DXBC::ASMOperation &op) const; - ShaderVariable DDX(State quad[4], const DXBC::ASMOperand &oper, const DXBC::ASMOperation &op) const; - ShaderVariable DDY(State quad[4], const DXBC::ASMOperand &oper, const DXBC::ASMOperation &op) const; + ShaderVariable DDX(bool fine, State quad[4], const DXBC::ASMOperand &oper, const DXBC::ASMOperation &op) const; + ShaderVariable DDY(bool fine, State quad[4], const DXBC::ASMOperand &oper, const DXBC::ASMOperation &op) const; VarType OperationType(const DXBC::OpcodeType &op) const;