diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 1b53a7fa0..66200925d 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -537,7 +537,7 @@ void Serialiser::Serialise(const char *name, PixelModification &el) Serialise("", el.depthClipped); Serialise("", el.viewClipped); Serialise("", el.scissorClipped); - Serialise("", el.shaderDiscared); + Serialise("", el.shaderDiscarded); Serialise("", el.depthTestFailed); Serialise("", el.stencilTestFailed); } diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index 24cef7a72..425b93c9f 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -3066,6 +3066,11 @@ vector D3D11DebugManager::PixelHistory(uint32_t frameID, vect m_pImmediateContext->Map(pixstore, 0, D3D11_MAP_READ, 0, &mapped); byte *pixstoreData = (byte *)mapped.pData; + + bool depthStencilTex = details.texType == eTexType_Depth || + details.texType == eTexType_DepthMS || + details.texType == eTexType_Stencil || + details.texType == eTexType_StencilMS; for(size_t i=0; i < occl.size(); i++) { @@ -3075,9 +3080,11 @@ vector D3D11DebugManager::PixelHistory(uint32_t frameID, vect } while(hr == S_FALSE); RDCASSERT(hr == S_OK); - // todo determine if an event is a clear, and unconditionally include it if it clears the current - // target - if(occlData > 0) + const FetchDrawcall *draw = m_WrappedDevice->GetDrawcall(frameID, events[i]); + + bool clear = (draw->flags & eDraw_Clear); + + if(occlData > 0 || clear) { PixelModification mod; RDCEraseEl(mod); @@ -3174,11 +3181,18 @@ vector D3D11DebugManager::PixelHistory(uint32_t frameID, vect { RDCASSERT(fmt.compByteWidth == 1); - for(uint32_t c=0; c < fmt.compCount; c++) + for(uint32_t c=0; c < RDCMIN(fmt.compCount, 3U); c++) { mod.preMod.value_f[c] = ConvertFromSRGB8(mod.preMod.value_u[c]&0xff); mod.postMod.value_f[c] = ConvertFromSRGB8(mod.postMod.value_u[c]&0xff); } + + // alpha is not SRGB'd + if(fmt.compCount == 4) + { + mod.preMod.value_f[3] = float(mod.preMod.value_u[3]&0xff)/255.0f; + mod.postMod.value_f[3] = float(mod.postMod.value_u[3]&0xff)/255.0f; + } } else if(fmt.compType == eCompType_SNorm && fmt.compByteWidth == 2) { @@ -3236,391 +3250,394 @@ vector D3D11DebugManager::PixelHistory(uint32_t frameID, vect if(flags[i] & Blending_Enabled) { } - - if(flags[i] & TestMustFail_DepthTesting) - mod.depthTestFailed = true; - if(flags[i] & TestMustFail_StencilTesting) - mod.stencilTestFailed = true; - if(flags[i] & TestMustFail_Scissor) - mod.scissorClipped = true; - - bool dirty = false; - - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); - - curNumScissors = curNumViews = 16; - m_pImmediateContext->RSGetViewports(&curNumViews, curViewports); - m_pImmediateContext->RSGetScissorRects(&curNumScissors, curScissors); - m_pImmediateContext->RSGetState(&curRS); - m_pImmediateContext->OMGetDepthStencilState(&curDS, &stencilRef); - blendFactor[0] = blendFactor[1] = blendFactor[2] = blendFactor[3] = 1.0f; - curSample = ~0U; - - D3D11_RASTERIZER_DESC rdesc = { - /*FillMode =*/ D3D11_FILL_SOLID, - /*CullMode =*/ D3D11_CULL_BACK, - /*FrontCounterClockwise =*/ FALSE, - /*DepthBias =*/ D3D11_DEFAULT_DEPTH_BIAS, - /*DepthBiasClamp =*/ D3D11_DEFAULT_DEPTH_BIAS_CLAMP, - /*SlopeScaledDepthBias =*/ D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS, - /*DepthClipEnable =*/ TRUE, - /*ScissorEnable =*/ FALSE, - /*MultisampleEnable =*/ FALSE, - /*AntialiasedLineEnable =*/ FALSE, - }; - if(curRS) - curRS->GetDesc(&rdesc); - - D3D11_DEPTH_STENCIL_DESC dsdesc = { - /*DepthEnable =*/ TRUE, - /*DepthWriteMask =*/ D3D11_DEPTH_WRITE_MASK_ALL, - /*DepthFunc =*/ D3D11_COMPARISON_LESS, - /*StencilEnable =*/ FALSE, - /*StencilReadMask =*/ D3D11_DEFAULT_STENCIL_READ_MASK, - /*StencilWriteMask =*/ D3D11_DEFAULT_STENCIL_WRITE_MASK, - /*FrontFace =*/ { D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_COMPARISON_ALWAYS }, - /*BackFace =*/ { D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_COMPARISON_ALWAYS }, - }; - if(curDS) - curDS->GetDesc(&dsdesc); - - for(UINT v=0; v < curNumViews; v++) - { - // calculate scissor, relative to this viewport, that encloses only (x,y) pixel - - // if (x,y) pixel isn't in viewport, make empty rect) - if(xf < curViewports[v].TopLeftX || - yf < curViewports[v].TopLeftY || - xf >= curViewports[v].TopLeftX + curViewports[v].Width || - yf >= curViewports[v].TopLeftY + curViewports[v].Height) - { - newScissors[v].left = newScissors[v].top = newScissors[v].bottom = newScissors[v].right = 0; - } - else - { - newScissors[v].left = LONG(xf - curViewports[v].TopLeftX); - newScissors[v].top = LONG(yf - curViewports[v].TopLeftY); - newScissors[v].right = newScissors[v].left+1; - newScissors[v].bottom = newScissors[v].top+1; - } - } - - // for each test we only disable pipeline rejection tests that fall *after* it. - // e.g. to get an idea if a pixel failed backface culling or not, we enable only backface - // culling and disable everything else (since it happens first). - // For depth testing, we leave all tests enabled up to then - as we only want to know which - // pixels were rejected by the depth test, not pixels that might have passed the depth test - // had they not been discarded earlier by backface culling or depth clipping. - - if(flags[i] & TestEnabled_BackfaceCulling) - { - D3D11_RASTERIZER_DESC rd = rdesc; - - rd.ScissorEnable = TRUE; - rd.DepthClipEnable = FALSE; - // leave backface culling mode as normal - - m_pDevice->CreateRasterizerState(&rd, &newRS); - - if(dirty) - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); - - m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); - m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); - m_pImmediateContext->OMSetDepthStencilState(nopDSState, stencilRef); - m_pImmediateContext->RSSetState(newRS); - m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); - - m_pImmediateContext->Begin(testQueries[0]); - - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); - dirty = true; - - m_pImmediateContext->End(testQueries[0]); - - SAFE_RELEASE(newRS); - } - - if(flags[i] & TestEnabled_DepthClip) - { - D3D11_RASTERIZER_DESC rd = rdesc; - - rd.ScissorEnable = TRUE; - // leave depth clip mode as normal - // leave backface culling mode as normal - - m_pDevice->CreateRasterizerState(&rd, &newRS); - - if(dirty) - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); - - m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); - m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); - m_pImmediateContext->OMSetDepthStencilState(nopDSState, stencilRef); - m_pImmediateContext->RSSetState(newRS); - m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); - - m_pImmediateContext->Begin(testQueries[1]); - - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); - dirty = true; - - m_pImmediateContext->End(testQueries[1]); - - SAFE_RELEASE(newRS); - } - - // only check scissor if test is enabled and we don't know if it's pass or fail yet - if((flags[i] & (TestEnabled_Scissor|TestMustPass_Scissor|TestMustFail_Scissor)) == TestEnabled_Scissor) - { - D3D11_RASTERIZER_DESC rd = rdesc; - - rd.ScissorEnable = TRUE; - // leave depth clip mode as normal - // leave backface culling mode as normal - - // newScissors has scissor regions calculated to hit our target pixel on every viewport, but we must - // intersect that with the original scissors regions for correct testing behaviour. - // This amounts to making any scissor region that doesn't overlap with the target pixel empty. - // - // Note that in the case of only one scissor region we can trivially detect pass/fail of the test against - // our pixel on the CPU so we won't come in here (see check above against MustFail/MustPass). So we will - // only do this in the case where we have multiple scissor regions/viewports, some intersecting the pixel - // and some not. So we make the not intersecting scissor regions empty so our occlusion query tests to see - // if any pixels were written to the "passing" viewports - D3D11_RECT intersectScissors[16] = {0}; - memcpy(intersectScissors, newScissors, sizeof(intersectScissors)); - - for(UINT s=0; s < curNumScissors; s++) - { - if(curScissors[i].left > newScissors[i].left || - curScissors[i].right < newScissors[i].right || - curScissors[i].top > newScissors[i].top || - curScissors[i].bottom < newScissors[i].bottom) - { - // scissor region from the log doesn't touch our target pixel, make empty. - intersectScissors[i].left = intersectScissors[i].right = intersectScissors[i].top = intersectScissors[i].bottom = 0; - } - } - - m_pDevice->CreateRasterizerState(&rd, &newRS); - - if(dirty) - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); - - m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); - m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); - m_pImmediateContext->OMSetDepthStencilState(nopDSState, stencilRef); - m_pImmediateContext->RSSetState(newRS); - m_pImmediateContext->RSSetScissorRects(curNumScissors, intersectScissors); - - m_pImmediateContext->Begin(testQueries[2]); - - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); - dirty = true; - - m_pImmediateContext->End(testQueries[2]); - - SAFE_RELEASE(newRS); - } - - // test shader discard - { - D3D11_RASTERIZER_DESC rd = rdesc; - - rd.ScissorEnable = TRUE; - // leave depth clip mode as normal - // leave backface culling mode as normal - - m_pDevice->CreateRasterizerState(&rd, &newRS); - - if(dirty) - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); - - m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); - m_pImmediateContext->OMSetDepthStencilState(nopDSState, stencilRef); - m_pImmediateContext->RSSetState(newRS); - m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); - - m_pImmediateContext->Begin(testQueries[3]); - - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); - dirty = true; - - m_pImmediateContext->End(testQueries[3]); - - SAFE_RELEASE(newRS); - } - - if(flags[i] & TestEnabled_DepthTesting) - { - D3D11_RASTERIZER_DESC rd = rdesc; - - rd.ScissorEnable = TRUE; - // leave depth clip mode as normal - // leave backface culling mode as normal - - m_pDevice->CreateRasterizerState(&rd, &newRS); - - D3D11_DEPTH_STENCIL_DESC dsd = dsdesc; - - dsd.StencilEnable = FALSE; - dsd.StencilReadMask = 0; - dsd.StencilWriteMask = 0; - - m_pDevice->CreateDepthStencilState(&dsd, &newDS); - - if(dirty) - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); - - m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); - m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); - m_pImmediateContext->OMSetDepthStencilState(newDS, stencilRef); - m_pImmediateContext->RSSetState(newRS); - m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); - - m_pImmediateContext->Begin(testQueries[4]); - - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); - dirty = true; - - m_pImmediateContext->End(testQueries[4]); - - SAFE_RELEASE(newRS); - SAFE_RELEASE(newDS); - } - - if(flags[i] & TestEnabled_StencilTesting) - { - D3D11_RASTERIZER_DESC rd = rdesc; - - rd.ScissorEnable = TRUE; - rd.DepthClipEnable = FALSE; - rd.CullMode = D3D11_CULL_NONE; - - m_pDevice->CreateRasterizerState(&rd, &newRS); - - // leave depthstencil testing exactly as is, because a depth-fail means - // stencil isn't run - m_pDevice->CreateDepthStencilState(&dsdesc, &newDS); - - if(dirty) - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); - - m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); - m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); - m_pImmediateContext->OMSetDepthStencilState(newDS, stencilRef); - m_pImmediateContext->RSSetState(newRS); - m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); - - m_pImmediateContext->Begin(testQueries[5]); - - m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); - dirty = true; - - m_pImmediateContext->End(testQueries[5]); - - SAFE_RELEASE(newRS); - SAFE_RELEASE(newDS); - } - - SAFE_RELEASE(curRS); - mod.shaderOut.value_f[0] = mod.postMod.value_f[0]; mod.shaderOut.value_f[1] = mod.postMod.value_f[1]; mod.shaderOut.value_f[2] = mod.postMod.value_f[2]; mod.shaderOut.value_f[3] = mod.postMod.value_f[3]; - // we check these in the order defined, as a positive from the backface cull test - // will invalidate tests later (as they will also be backface culled) - - do + if((draw->flags & eDraw_Clear) == 0) { + if(flags[i] & TestMustFail_DepthTesting) + mod.depthTestFailed = true; + if(flags[i] & TestMustFail_StencilTesting) + mod.stencilTestFailed = true; + if(flags[i] & TestMustFail_Scissor) + mod.scissorClipped = true; + + bool dirty = false; + + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); + + curNumScissors = curNumViews = 16; + m_pImmediateContext->RSGetViewports(&curNumViews, curViewports); + m_pImmediateContext->RSGetScissorRects(&curNumScissors, curScissors); + m_pImmediateContext->RSGetState(&curRS); + m_pImmediateContext->OMGetDepthStencilState(&curDS, &stencilRef); + blendFactor[0] = blendFactor[1] = blendFactor[2] = blendFactor[3] = 1.0f; + curSample = ~0U; + + D3D11_RASTERIZER_DESC rdesc = { + /*FillMode =*/ D3D11_FILL_SOLID, + /*CullMode =*/ D3D11_CULL_BACK, + /*FrontCounterClockwise =*/ FALSE, + /*DepthBias =*/ D3D11_DEFAULT_DEPTH_BIAS, + /*DepthBiasClamp =*/ D3D11_DEFAULT_DEPTH_BIAS_CLAMP, + /*SlopeScaledDepthBias =*/ D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS, + /*DepthClipEnable =*/ TRUE, + /*ScissorEnable =*/ FALSE, + /*MultisampleEnable =*/ FALSE, + /*AntialiasedLineEnable =*/ FALSE, + }; + if(curRS) + curRS->GetDesc(&rdesc); + + D3D11_DEPTH_STENCIL_DESC dsdesc = { + /*DepthEnable =*/ TRUE, + /*DepthWriteMask =*/ D3D11_DEPTH_WRITE_MASK_ALL, + /*DepthFunc =*/ D3D11_COMPARISON_LESS, + /*StencilEnable =*/ FALSE, + /*StencilReadMask =*/ D3D11_DEFAULT_STENCIL_READ_MASK, + /*StencilWriteMask =*/ D3D11_DEFAULT_STENCIL_WRITE_MASK, + /*FrontFace =*/ { D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_COMPARISON_ALWAYS }, + /*BackFace =*/ { D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_COMPARISON_ALWAYS }, + }; + + if(curDS) + curDS->GetDesc(&dsdesc); + + for(UINT v=0; v < curNumViews; v++) + { + // calculate scissor, relative to this viewport, that encloses only (x,y) pixel + + // if (x,y) pixel isn't in viewport, make empty rect) + if(xf < curViewports[v].TopLeftX || + yf < curViewports[v].TopLeftY || + xf >= curViewports[v].TopLeftX + curViewports[v].Width || + yf >= curViewports[v].TopLeftY + curViewports[v].Height) + { + newScissors[v].left = newScissors[v].top = newScissors[v].bottom = newScissors[v].right = 0; + } + else + { + newScissors[v].left = LONG(xf - curViewports[v].TopLeftX); + newScissors[v].top = LONG(yf - curViewports[v].TopLeftY); + newScissors[v].right = newScissors[v].left+1; + newScissors[v].bottom = newScissors[v].top+1; + } + } + + // for each test we only disable pipeline rejection tests that fall *after* it. + // e.g. to get an idea if a pixel failed backface culling or not, we enable only backface + // culling and disable everything else (since it happens first). + // For depth testing, we leave all tests enabled up to then - as we only want to know which + // pixels were rejected by the depth test, not pixels that might have passed the depth test + // had they not been discarded earlier by backface culling or depth clipping. if(flags[i] & TestEnabled_BackfaceCulling) { - do - { - hr = m_pImmediateContext->GetData(testQueries[0], &occlData, sizeof(occlData), 0); - } while(hr == S_FALSE); - RDCASSERT(hr == S_OK); + D3D11_RASTERIZER_DESC rd = rdesc; - mod.backfaceCulled = (occlData == 0); + rd.ScissorEnable = TRUE; + rd.DepthClipEnable = FALSE; + // leave backface culling mode as normal - if(mod.backfaceCulled) - break; + m_pDevice->CreateRasterizerState(&rd, &newRS); + + if(dirty) + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); + + m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); + m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); + m_pImmediateContext->OMSetDepthStencilState(nopDSState, stencilRef); + m_pImmediateContext->RSSetState(newRS); + m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); + + m_pImmediateContext->Begin(testQueries[0]); + + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); + dirty = true; + + m_pImmediateContext->End(testQueries[0]); + + SAFE_RELEASE(newRS); } if(flags[i] & TestEnabled_DepthClip) { - do - { - hr = m_pImmediateContext->GetData(testQueries[1], &occlData, sizeof(occlData), 0); - } while(hr == S_FALSE); - RDCASSERT(hr == S_OK); + D3D11_RASTERIZER_DESC rd = rdesc; - mod.depthClipped = (occlData == 0); + rd.ScissorEnable = TRUE; + // leave depth clip mode as normal + // leave backface culling mode as normal - if(mod.depthClipped) - break; + m_pDevice->CreateRasterizerState(&rd, &newRS); + + if(dirty) + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); + + m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); + m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); + m_pImmediateContext->OMSetDepthStencilState(nopDSState, stencilRef); + m_pImmediateContext->RSSetState(newRS); + m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); + + m_pImmediateContext->Begin(testQueries[1]); + + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); + dirty = true; + + m_pImmediateContext->End(testQueries[1]); + + SAFE_RELEASE(newRS); } - if(!mod.backfaceCulled && (flags[i] & (TestEnabled_Scissor|TestMustPass_Scissor|TestMustFail_Scissor)) == TestEnabled_Scissor) + // only check scissor if test is enabled and we don't know if it's pass or fail yet + if((flags[i] & (TestEnabled_Scissor|TestMustPass_Scissor|TestMustFail_Scissor)) == TestEnabled_Scissor) { - do + D3D11_RASTERIZER_DESC rd = rdesc; + + rd.ScissorEnable = TRUE; + // leave depth clip mode as normal + // leave backface culling mode as normal + + // newScissors has scissor regions calculated to hit our target pixel on every viewport, but we must + // intersect that with the original scissors regions for correct testing behaviour. + // This amounts to making any scissor region that doesn't overlap with the target pixel empty. + // + // Note that in the case of only one scissor region we can trivially detect pass/fail of the test against + // our pixel on the CPU so we won't come in here (see check above against MustFail/MustPass). So we will + // only do this in the case where we have multiple scissor regions/viewports, some intersecting the pixel + // and some not. So we make the not intersecting scissor regions empty so our occlusion query tests to see + // if any pixels were written to the "passing" viewports + D3D11_RECT intersectScissors[16] = {0}; + memcpy(intersectScissors, newScissors, sizeof(intersectScissors)); + + for(UINT s=0; s < curNumScissors; s++) { - hr = m_pImmediateContext->GetData(testQueries[2], &occlData, sizeof(occlData), 0); - } while(hr == S_FALSE); - RDCASSERT(hr == S_OK); + if(curScissors[i].left > newScissors[i].left || + curScissors[i].right < newScissors[i].right || + curScissors[i].top > newScissors[i].top || + curScissors[i].bottom < newScissors[i].bottom) + { + // scissor region from the log doesn't touch our target pixel, make empty. + intersectScissors[i].left = intersectScissors[i].right = intersectScissors[i].top = intersectScissors[i].bottom = 0; + } + } - mod.scissorClipped = (occlData == 0); + m_pDevice->CreateRasterizerState(&rd, &newRS); - if(mod.scissorClipped) - break; + if(dirty) + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); + + m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); + m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); + m_pImmediateContext->OMSetDepthStencilState(nopDSState, stencilRef); + m_pImmediateContext->RSSetState(newRS); + m_pImmediateContext->RSSetScissorRects(curNumScissors, intersectScissors); + + m_pImmediateContext->Begin(testQueries[2]); + + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); + dirty = true; + + m_pImmediateContext->End(testQueries[2]); + + SAFE_RELEASE(newRS); } + // test shader discard { - do - { - hr = m_pImmediateContext->GetData(testQueries[3], &occlData, sizeof(occlData), 0); - } while(hr == S_FALSE); - RDCASSERT(hr == S_OK); + D3D11_RASTERIZER_DESC rd = rdesc; - mod.shaderDiscarded = (occlData == 0); + rd.ScissorEnable = TRUE; + // leave depth clip mode as normal + // leave backface culling mode as normal - if(mod.shaderDiscarded) - break; + m_pDevice->CreateRasterizerState(&rd, &newRS); + + if(dirty) + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); + + m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); + m_pImmediateContext->OMSetDepthStencilState(nopDSState, stencilRef); + m_pImmediateContext->RSSetState(newRS); + m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); + + m_pImmediateContext->Begin(testQueries[3]); + + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); + dirty = true; + + m_pImmediateContext->End(testQueries[3]); + + SAFE_RELEASE(newRS); } if(flags[i] & TestEnabled_DepthTesting) { - do - { - hr = m_pImmediateContext->GetData(testQueries[4], &occlData, sizeof(occlData), 0); - } while(hr == S_FALSE); - RDCASSERT(hr == S_OK); + D3D11_RASTERIZER_DESC rd = rdesc; - mod.depthTestFailed = (occlData == 0); + rd.ScissorEnable = TRUE; + // leave depth clip mode as normal + // leave backface culling mode as normal - if(mod.depthTestFailed) - break; + m_pDevice->CreateRasterizerState(&rd, &newRS); + + D3D11_DEPTH_STENCIL_DESC dsd = dsdesc; + + dsd.StencilEnable = FALSE; + dsd.StencilReadMask = 0; + dsd.StencilWriteMask = 0; + + m_pDevice->CreateDepthStencilState(&dsd, &newDS); + + if(dirty) + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); + + m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); + m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); + m_pImmediateContext->OMSetDepthStencilState(newDS, stencilRef); + m_pImmediateContext->RSSetState(newRS); + m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); + + m_pImmediateContext->Begin(testQueries[4]); + + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); + dirty = true; + + m_pImmediateContext->End(testQueries[4]); + + SAFE_RELEASE(newRS); + SAFE_RELEASE(newDS); } if(flags[i] & TestEnabled_StencilTesting) { - do - { - hr = m_pImmediateContext->GetData(testQueries[5], &occlData, sizeof(occlData), 0); - } while(hr == S_FALSE); - RDCASSERT(hr == S_OK); + D3D11_RASTERIZER_DESC rd = rdesc; - mod.stencilTestFailed = (occlData == 0); + rd.ScissorEnable = TRUE; + rd.DepthClipEnable = FALSE; + rd.CullMode = D3D11_CULL_NONE; - if(mod.stencilTestFailed) - break; + m_pDevice->CreateRasterizerState(&rd, &newRS); + + // leave depthstencil testing exactly as is, because a depth-fail means + // stencil isn't run + m_pDevice->CreateDepthStencilState(&dsdesc, &newDS); + + if(dirty) + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_WithoutDraw); + + m_pImmediateContext->PSSetShader(m_DebugRender.OverlayPS, NULL, 0); + m_pImmediateContext->OMSetBlendState(nopBlendState, blendFactor, curSample); + m_pImmediateContext->OMSetDepthStencilState(newDS, stencilRef); + m_pImmediateContext->RSSetState(newRS); + m_pImmediateContext->RSSetScissorRects(curNumViews, newScissors); + + m_pImmediateContext->Begin(testQueries[5]); + + m_WrappedDevice->ReplayLog(frameID, 0, events[i], eReplay_OnlyDraw); + dirty = true; + + m_pImmediateContext->End(testQueries[5]); + + SAFE_RELEASE(newRS); + SAFE_RELEASE(newDS); } - } while (0); + + SAFE_RELEASE(curRS); + + // we check these in the order defined, as a positive from the backface cull test + // will invalidate tests later (as they will also be backface culled) + + do + { + + if(flags[i] & TestEnabled_BackfaceCulling) + { + do + { + hr = m_pImmediateContext->GetData(testQueries[0], &occlData, sizeof(occlData), 0); + } while(hr == S_FALSE); + RDCASSERT(hr == S_OK); + + mod.backfaceCulled = (occlData == 0); + + if(mod.backfaceCulled) + break; + } + + if(flags[i] & TestEnabled_DepthClip) + { + do + { + hr = m_pImmediateContext->GetData(testQueries[1], &occlData, sizeof(occlData), 0); + } while(hr == S_FALSE); + RDCASSERT(hr == S_OK); + + mod.depthClipped = (occlData == 0); + + if(mod.depthClipped) + break; + } + + if(!mod.backfaceCulled && (flags[i] & (TestEnabled_Scissor|TestMustPass_Scissor|TestMustFail_Scissor)) == TestEnabled_Scissor) + { + do + { + hr = m_pImmediateContext->GetData(testQueries[2], &occlData, sizeof(occlData), 0); + } while(hr == S_FALSE); + RDCASSERT(hr == S_OK); + + mod.scissorClipped = (occlData == 0); + + if(mod.scissorClipped) + break; + } + + { + do + { + hr = m_pImmediateContext->GetData(testQueries[3], &occlData, sizeof(occlData), 0); + } while(hr == S_FALSE); + RDCASSERT(hr == S_OK); + + mod.shaderDiscarded = (occlData == 0); + + if(mod.shaderDiscarded) + break; + } + + if(flags[i] & TestEnabled_DepthTesting) + { + do + { + hr = m_pImmediateContext->GetData(testQueries[4], &occlData, sizeof(occlData), 0); + } while(hr == S_FALSE); + RDCASSERT(hr == S_OK); + + mod.depthTestFailed = (occlData == 0); + + if(mod.depthTestFailed) + break; + } + + if(flags[i] & TestEnabled_StencilTesting) + { + do + { + hr = m_pImmediateContext->GetData(testQueries[5], &occlData, sizeof(occlData), 0); + } while(hr == S_FALSE); + RDCASSERT(hr == S_OK); + + mod.stencilTestFailed = (occlData == 0); + + if(mod.stencilTestFailed) + break; + } + } while (0); + } history.push_back(mod); diff --git a/renderdocui/Windows/PixelHistoryView.Designer.cs b/renderdocui/Windows/PixelHistoryView.Designer.cs new file mode 100644 index 000000000..cfa83639d --- /dev/null +++ b/renderdocui/Windows/PixelHistoryView.Designer.cs @@ -0,0 +1,100 @@ +namespace renderdocui.Windows +{ + partial class PixelHistoryView + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + TreelistView.TreeListColumn treeListColumn1 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("EID", "EID"))); + TreelistView.TreeListColumn treeListColumn2 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("Event", "Event"))); + TreelistView.TreeListColumn treeListColumn3 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("Before", "Before"))); + TreelistView.TreeListColumn treeListColumn4 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("BeforeCol", ""))); + TreelistView.TreeListColumn treeListColumn5 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("After", "After"))); + TreelistView.TreeListColumn treeListColumn6 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("AfterCol", ""))); + this.events = new TreelistView.TreeListView(); + ((System.ComponentModel.ISupportInitialize)(this.events)).BeginInit(); + this.SuspendLayout(); + // + // events + // + treeListColumn1.AutoSizeMinSize = 10; + treeListColumn1.CellFormat.Padding = new System.Windows.Forms.Padding(4); + treeListColumn1.CellFormat.TextAlignment = System.Drawing.ContentAlignment.TopLeft; + treeListColumn1.Width = 50; + treeListColumn2.AutoSize = true; + treeListColumn2.AutoSizeMinSize = 20; + treeListColumn2.CellFormat.Padding = new System.Windows.Forms.Padding(4); + treeListColumn2.CellFormat.TextAlignment = System.Drawing.ContentAlignment.TopLeft; + treeListColumn2.Width = 100; + treeListColumn3.AutoSizeMinSize = 10; + treeListColumn3.Width = 50; + treeListColumn4.AutoSizeMinSize = 20; + treeListColumn4.Width = 40; + treeListColumn5.AutoSizeMinSize = 20; + treeListColumn5.Width = 60; + treeListColumn6.AutoSizeMinSize = 20; + treeListColumn6.Width = 40; + this.events.Columns.AddRange(new TreelistView.TreeListColumn[] { + treeListColumn1, + treeListColumn2, + treeListColumn3, + treeListColumn4, + treeListColumn5, + treeListColumn6}); + this.events.Cursor = System.Windows.Forms.Cursors.Arrow; + this.events.Dock = System.Windows.Forms.DockStyle.Fill; + this.events.Location = new System.Drawing.Point(0, 0); + this.events.MultiSelect = false; + this.events.Name = "events"; + this.events.RowOptions.ItemHeight = 64; + this.events.RowOptions.ShowHeader = false; + this.events.Size = new System.Drawing.Size(386, 478); + this.events.TabIndex = 1; + this.events.Text = "History Events"; + this.events.ViewOptions.ShowLine = false; + this.events.ViewOptions.ShowPlusMinus = false; + this.events.NodeDoubleClicked += new TreelistView.TreeListView.NodeDoubleClickedHandler(this.events_NodeDoubleClicked); + // + // PixelHistoryView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(386, 478); + this.Controls.Add(this.events); + this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.Name = "PixelHistoryView"; + this.ShowHint = WeifenLuo.WinFormsUI.Docking.DockState.DockRight; + this.Text = "Pixel History"; + ((System.ComponentModel.ISupportInitialize)(this.events)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private TreelistView.TreeListView events; + } +} \ No newline at end of file diff --git a/renderdocui/Windows/PixelHistoryView.cs b/renderdocui/Windows/PixelHistoryView.cs new file mode 100644 index 000000000..1ec57752a --- /dev/null +++ b/renderdocui/Windows/PixelHistoryView.cs @@ -0,0 +1,204 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2014 Crytek + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using WeifenLuo.WinFormsUI.Docking; +using renderdocui.Code; +using renderdoc; + +namespace renderdocui.Windows +{ + public partial class PixelHistoryView : DockContent, ILogViewerForm + { + Core m_Core; + + public PixelHistoryView(Core core, FetchTexture tex, Point pt, PixelModification[] history) + { + InitializeComponent(); + + Icon = global::renderdocui.Properties.Resources.icon; + + events.BeginInit(); + events.BeginUpdate(); + + m_Core = core; + + Text += String.Format(" on {0} for ({1}, {2})", tex.name, pt.X, pt.Y); + + bool uintTex = (tex.format.compType == FormatComponentType.UInt); + bool sintTex = (tex.format.compType == FormatComponentType.SInt); + bool srgbTex = tex.format.srgbCorrected || + (tex.creationFlags & TextureCreationFlags.SwapBuffer) > 0; + bool floatTex = (!uintTex && !sintTex); + + foreach (PixelModification mod in history) + { + string name = "name"; + + var drawcall = core.GetDrawcall(core.CurFrame, mod.eventID); + + if (drawcall == null) continue; + + name = drawcall.name; + + bool passed = true; + + if (mod.backfaceCulled) + { + name += "\nBackface culled"; + passed = false; + } + if (mod.depthClipped) + { + name += "\nDepth Clipped"; + passed = false; + } + if (mod.scissorClipped) + { + name += "\nScissor Clipped"; + passed = false; + } + if (mod.shaderDiscarded) + { + name += "\nShader executed a discard"; + passed = false; + } + if (mod.depthTestFailed) + { + name += "\nDepth test failed"; + passed = false; + } + if (mod.stencilTestFailed) + { + name += "\nStencil test failed"; + passed = false; + } + + string preModVal = ""; + string postModVal = ""; + + if (uintTex) + { + preModVal = mod.preMod.value.u[0].ToString() + "\n" + + mod.preMod.value.u[1].ToString() + "\n" + + mod.preMod.value.u[2].ToString() + "\n" + + mod.preMod.value.u[3].ToString(); + postModVal = mod.postMod.value.u[0].ToString() + "\n" + + mod.postMod.value.u[1].ToString() + "\n" + + mod.postMod.value.u[2].ToString() + "\n" + + mod.postMod.value.u[3].ToString(); + } + else if (sintTex) + { + preModVal = mod.preMod.value.i[0].ToString() + "\n" + + mod.preMod.value.i[1].ToString() + "\n" + + mod.preMod.value.i[2].ToString() + "\n" + + mod.preMod.value.i[3].ToString(); + postModVal = mod.postMod.value.i[0].ToString() + "\n" + + mod.postMod.value.i[1].ToString() + "\n" + + mod.postMod.value.i[2].ToString() + "\n" + + mod.postMod.value.i[3].ToString(); + } + else + { + preModVal = Formatter.Format(mod.preMod.value.f[0]) + "\n" + + Formatter.Format(mod.preMod.value.f[1]) + "\n" + + Formatter.Format(mod.preMod.value.f[2]) + "\n" + + Formatter.Format(mod.preMod.value.f[3]); + postModVal = Formatter.Format(mod.postMod.value.f[0]) + "\n" + + Formatter.Format(mod.postMod.value.f[1]) + "\n" + + Formatter.Format(mod.postMod.value.f[2]) + "\n" + + Formatter.Format(mod.postMod.value.f[3]); + } + + var node = events.Nodes.Add(new object[] { mod.eventID, name, preModVal, "", postModVal, "" }); + + node.BackColor = passed ? Color.FromArgb(235, 255, 235) : Color.FromArgb(255, 235, 235); + + if (floatTex) + { + float r = Helpers.Clamp(mod.preMod.value.f[0], 0.0f, 1.0f); + float g = Helpers.Clamp(mod.preMod.value.f[1], 0.0f, 1.0f); + float b = Helpers.Clamp(mod.preMod.value.f[2], 0.0f, 1.0f); + + if (srgbTex) + { + r = (float)Math.Pow(r, 1.0f / 2.2f); + g = (float)Math.Pow(g, 1.0f / 2.2f); + b = (float)Math.Pow(b, 1.0f / 2.2f); + } + + node.IndexedBackColor[3] = Color.FromArgb((int)(255.0f * r), (int)(255.0f * g), (int)(255.0f * b)); + + r = Helpers.Clamp(mod.postMod.value.f[0], 0.0f, 1.0f); + g = Helpers.Clamp(mod.postMod.value.f[1], 0.0f, 1.0f); + b = Helpers.Clamp(mod.postMod.value.f[2], 0.0f, 1.0f); + + if (srgbTex) + { + r = (float)Math.Pow(r, 1.0f / 2.2f); + g = (float)Math.Pow(g, 1.0f / 2.2f); + b = (float)Math.Pow(b, 1.0f / 2.2f); + } + + node.IndexedBackColor[5] = Color.FromArgb((int)(255.0f * r), (int)(255.0f * g), (int)(255.0f * b)); + } + + node.Tag = mod.eventID; + } + + events.EndUpdate(); + events.EndInit(); + } + + public void OnLogfileClosed() + { + Close(); + } + + public void OnLogfileLoaded() + { + } + + public void OnEventSelected(UInt32 frameID, UInt32 eventID) + { + } + + private void events_NodeDoubleClicked(TreelistView.Node node) + { + if (node.Tag is uint) + { + m_Core.SetEventID(this, m_Core.CurFrame, (uint)node.Tag); + } + } + } +} diff --git a/renderdocui/Windows/PixelHistoryView.resx b/renderdocui/Windows/PixelHistoryView.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/renderdocui/Windows/PixelHistoryView.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/renderdocui/Windows/TextureViewer.Designer.cs b/renderdocui/Windows/TextureViewer.Designer.cs index 08bc46de9..1e8d74501 100644 --- a/renderdocui/Windows/TextureViewer.Designer.cs +++ b/renderdocui/Windows/TextureViewer.Designer.cs @@ -110,6 +110,8 @@ this.customDelete = new System.Windows.Forms.ToolStripButton(); this.backcolorPick = new System.Windows.Forms.ToolStripButton(); this.checkerBack = new System.Windows.Forms.ToolStripButton(); + this.gammaSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.gammaDisplay = new System.Windows.Forms.ToolStripButton(); this.statusbar = new System.Windows.Forms.StatusStrip(); this.texStatusDim = new System.Windows.Forms.ToolStripStatusLabel(); this.hoverSwatch = new System.Windows.Forms.ToolStripStatusLabel(); @@ -120,28 +122,28 @@ this.debugPixel = new System.Windows.Forms.ToolStripButton(); this.texListShow = new System.Windows.Forms.ToolStripButton(); this.texlistContainer = new System.Windows.Forms.TableLayoutPanel(); + this.textureList = new renderdocui.Controls.TextureListBox(); this.texturefilter = new System.Windows.Forms.ComboBox(); this.label1 = new System.Windows.Forms.Label(); this.clearTexFilter = new System.Windows.Forms.Button(); this.renderToolstripContainer = new System.Windows.Forms.ToolStripContainer(); this.renderScrollTable = new System.Windows.Forms.TableLayoutPanel(); + this.renderContainer = new renderdocui.Controls.NoScrollPanel(); + this.render = new renderdocui.Controls.NoScrollPanel(); this.renderVScroll = new System.Windows.Forms.VScrollBar(); this.renderHScroll = new System.Windows.Forms.HScrollBar(); this.pixelContextPanel = new System.Windows.Forms.TableLayoutPanel(); + this.pixelContext = new renderdocui.Controls.NoScrollPanel(); this.debugPixelContext = new System.Windows.Forms.Button(); + this.pixelHistory = new System.Windows.Forms.Button(); this.tabContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.closeTab = new System.Windows.Forms.ToolStripMenuItem(); this.closeOtherTabs = new System.Windows.Forms.ToolStripMenuItem(); this.closeTabsToRight = new System.Windows.Forms.ToolStripMenuItem(); - this.gammaDisplay = new System.Windows.Forms.ToolStripButton(); - this.gammaSeparator = new System.Windows.Forms.ToolStripSeparator(); - this.textureList = new renderdocui.Controls.TextureListBox(); this.texPanel = new renderdocui.Controls.ThumbnailStrip(); this.rtPanel = new renderdocui.Controls.ThumbnailStrip(); - this.pixelContext = new renderdocui.Controls.NoScrollPanel(); - this.renderContainer = new renderdocui.Controls.NoScrollPanel(); - this.render = new renderdocui.Controls.NoScrollPanel(); this.rangeHistogram = new renderdocui.Controls.RangeHistogram(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); subSep = new System.Windows.Forms.ToolStripSeparator(); toolStripLabel2 = new System.Windows.Forms.ToolStripLabel(); toolStripLabel3 = new System.Windows.Forms.ToolStripLabel(); @@ -163,9 +165,9 @@ this.renderToolstripContainer.ContentPanel.SuspendLayout(); this.renderToolstripContainer.SuspendLayout(); this.renderScrollTable.SuspendLayout(); + this.renderContainer.SuspendLayout(); this.pixelContextPanel.SuspendLayout(); this.tabContextMenu.SuspendLayout(); - this.renderContainer.SuspendLayout(); this.SuspendLayout(); // // subSep @@ -861,6 +863,26 @@ this.checkerBack.ToolTipText = "Alpha: Show Checkerboard Background"; this.checkerBack.Click += new System.EventHandler(this.checkerBack_Click); // + // gammaSeparator + // + this.gammaSeparator.Name = "gammaSeparator"; + this.gammaSeparator.Size = new System.Drawing.Size(6, 25); + // + // gammaDisplay + // + this.gammaDisplay.Checked = true; + this.gammaDisplay.CheckOnClick = true; + this.gammaDisplay.CheckState = System.Windows.Forms.CheckState.Checked; + this.gammaDisplay.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.gammaDisplay.Image = ((System.Drawing.Image)(resources.GetObject("gammaDisplay.Image"))); + this.gammaDisplay.ImageTransparentColor = System.Drawing.Color.Magenta; + this.gammaDisplay.Name = "gammaDisplay"; + this.gammaDisplay.Size = new System.Drawing.Size(23, 22); + this.gammaDisplay.Text = "γ"; + this.gammaDisplay.ToolTipText = "Override display of linear data in gamma space\r\n\r\nSee FAQ on \"Gamma display of li" + + "near data\""; + this.gammaDisplay.CheckedChanged += new System.EventHandler(this.updateChannelsHandler); + // // statusbar // this.statusbar.Dock = System.Windows.Forms.DockStyle.None; @@ -871,7 +893,7 @@ this.statusbar.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.Flow; this.statusbar.Location = new System.Drawing.Point(0, 0); this.statusbar.Name = "statusbar"; - this.statusbar.Size = new System.Drawing.Size(420, 19); + this.statusbar.Size = new System.Drawing.Size(420, 18); this.statusbar.SizingGrip = false; this.statusbar.TabIndex = 0; // @@ -984,6 +1006,20 @@ this.texlistContainer.Size = new System.Drawing.Size(136, 260); this.texlistContainer.TabIndex = 1; // + // textureList + // + this.texlistContainer.SetColumnSpan(this.textureList, 2); + this.textureList.Dock = System.Windows.Forms.DockStyle.Fill; + this.textureList.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; + this.textureList.IntegralHeight = false; + this.textureList.ItemHeight = 16; + this.textureList.Location = new System.Drawing.Point(3, 50); + this.textureList.Name = "textureList"; + this.textureList.SelectionMode = System.Windows.Forms.SelectionMode.None; + this.textureList.Size = new System.Drawing.Size(130, 207); + this.textureList.TabIndex = 0; + this.textureList.MouseUp += new System.Windows.Forms.MouseEventHandler(this.textureList_MouseUp); + // // texturefilter // this.texturefilter.Dock = System.Windows.Forms.DockStyle.Fill; @@ -1033,7 +1069,7 @@ // renderToolstripContainer.ContentPanel // this.renderToolstripContainer.ContentPanel.Controls.Add(this.renderScrollTable); - this.renderToolstripContainer.ContentPanel.Size = new System.Drawing.Size(420, 247); + this.renderToolstripContainer.ContentPanel.Size = new System.Drawing.Size(420, 248); this.renderToolstripContainer.LeftToolStripPanelVisible = false; this.renderToolstripContainer.Location = new System.Drawing.Point(299, 87); this.renderToolstripContainer.Name = "renderToolstripContainer"; @@ -1058,16 +1094,43 @@ this.renderScrollTable.RowCount = 2; this.renderScrollTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.renderScrollTable.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.renderScrollTable.Size = new System.Drawing.Size(420, 247); + this.renderScrollTable.Size = new System.Drawing.Size(420, 248); this.renderScrollTable.TabIndex = 2; // + // renderContainer + // + this.renderContainer.BackColor = System.Drawing.Color.Maroon; + this.renderContainer.Controls.Add(this.render); + this.renderContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.renderContainer.Location = new System.Drawing.Point(0, 0); + this.renderContainer.Margin = new System.Windows.Forms.Padding(0); + this.renderContainer.Name = "renderContainer"; + this.renderContainer.Size = new System.Drawing.Size(404, 232); + this.renderContainer.TabIndex = 1; + // + // render + // + this.render.BackColor = System.Drawing.Color.Black; + this.render.Dock = System.Windows.Forms.DockStyle.Fill; + this.render.Location = new System.Drawing.Point(0, 0); + this.render.Name = "render"; + this.render.Size = new System.Drawing.Size(404, 232); + this.render.TabIndex = 0; + this.render.Paint += new System.Windows.Forms.PaintEventHandler(this.render_Paint); + this.render.Layout += new System.Windows.Forms.LayoutEventHandler(this.render_Layout); + this.render.MouseClick += new System.Windows.Forms.MouseEventHandler(this.render_MouseClick); + this.render.MouseDown += new System.Windows.Forms.MouseEventHandler(this.render_MouseClick); + this.render.MouseLeave += new System.EventHandler(this.render_MouseLeave); + this.render.MouseMove += new System.Windows.Forms.MouseEventHandler(this.render_MouseMove); + this.render.MouseUp += new System.Windows.Forms.MouseEventHandler(this.render_MouseUp); + // // renderVScroll // this.renderVScroll.Dock = System.Windows.Forms.DockStyle.Right; this.renderVScroll.Enabled = false; this.renderVScroll.Location = new System.Drawing.Point(404, 0); this.renderVScroll.Name = "renderVScroll"; - this.renderVScroll.Size = new System.Drawing.Size(16, 231); + this.renderVScroll.Size = new System.Drawing.Size(16, 232); this.renderVScroll.TabIndex = 2; this.renderVScroll.Scroll += new System.Windows.Forms.ScrollEventHandler(this.renderVScroll_Scroll); // @@ -1075,7 +1138,7 @@ // this.renderHScroll.Dock = System.Windows.Forms.DockStyle.Bottom; this.renderHScroll.Enabled = false; - this.renderHScroll.Location = new System.Drawing.Point(0, 231); + this.renderHScroll.Location = new System.Drawing.Point(0, 232); this.renderHScroll.Name = "renderHScroll"; this.renderHScroll.Size = new System.Drawing.Size(404, 16); this.renderHScroll.TabIndex = 3; @@ -1083,30 +1146,56 @@ // // pixelContextPanel // - this.pixelContextPanel.ColumnCount = 1; - this.pixelContextPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.pixelContextPanel.ColumnCount = 2; + this.pixelContextPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.pixelContextPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); this.pixelContextPanel.Controls.Add(this.pixelContext, 0, 0); - this.pixelContextPanel.Controls.Add(this.debugPixelContext, 0, 1); + this.pixelContextPanel.Controls.Add(this.debugPixelContext, 1, 1); + this.pixelContextPanel.Controls.Add(this.pixelHistory, 0, 1); this.pixelContextPanel.Location = new System.Drawing.Point(780, 258); this.pixelContextPanel.Name = "pixelContextPanel"; this.pixelContextPanel.RowCount = 2; this.pixelContextPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.pixelContextPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.pixelContextPanel.Size = new System.Drawing.Size(108, 127); + this.pixelContextPanel.Size = new System.Drawing.Size(215, 156); this.pixelContextPanel.TabIndex = 11; // + // pixelContext + // + this.pixelContext.BackColor = System.Drawing.Color.Transparent; + this.pixelContextPanel.SetColumnSpan(this.pixelContext, 2); + this.pixelContext.Dock = System.Windows.Forms.DockStyle.Fill; + this.pixelContext.Location = new System.Drawing.Point(3, 3); + this.pixelContext.Name = "pixelContext"; + this.pixelContext.Size = new System.Drawing.Size(209, 121); + this.pixelContext.TabIndex = 6; + this.pixelContext.Paint += new System.Windows.Forms.PaintEventHandler(this.pixelContext_Paint); + // // debugPixelContext // this.debugPixelContext.Anchor = System.Windows.Forms.AnchorStyles.Bottom; this.debugPixelContext.AutoSize = true; - this.debugPixelContext.Location = new System.Drawing.Point(5, 101); + this.debugPixelContext.Location = new System.Drawing.Point(136, 130); this.debugPixelContext.Name = "debugPixelContext"; - this.debugPixelContext.Size = new System.Drawing.Size(97, 23); + this.debugPixelContext.Size = new System.Drawing.Size(49, 23); this.debugPixelContext.TabIndex = 7; - this.debugPixelContext.Text = "Debug This Pixel"; + this.debugPixelContext.Text = "Debug"; + this.toolTip.SetToolTip(this.debugPixelContext, "Debug this pixel"); this.debugPixelContext.UseVisualStyleBackColor = true; this.debugPixelContext.Click += new System.EventHandler(this.debugPixel_Click); // + // pixelHistory + // + this.pixelHistory.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.pixelHistory.Location = new System.Drawing.Point(29, 130); + this.pixelHistory.Name = "pixelHistory"; + this.pixelHistory.Size = new System.Drawing.Size(48, 23); + this.pixelHistory.TabIndex = 8; + this.pixelHistory.Text = "History"; + this.toolTip.SetToolTip(this.pixelHistory, "Show history for this pixel"); + this.pixelHistory.UseVisualStyleBackColor = true; + this.pixelHistory.Click += new System.EventHandler(this.pixelHistory_Click); + // // tabContextMenu // this.tabContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -1138,40 +1227,6 @@ this.closeTabsToRight.Text = "Close tabs to right"; this.closeTabsToRight.Click += new System.EventHandler(this.closeTabsToRight_Click); // - // gammaDisplay - // - this.gammaDisplay.Checked = true; - this.gammaDisplay.CheckOnClick = true; - this.gammaDisplay.CheckState = System.Windows.Forms.CheckState.Checked; - this.gammaDisplay.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.gammaDisplay.Image = ((System.Drawing.Image)(resources.GetObject("gammaDisplay.Image"))); - this.gammaDisplay.ImageTransparentColor = System.Drawing.Color.Magenta; - this.gammaDisplay.Name = "gammaDisplay"; - this.gammaDisplay.Size = new System.Drawing.Size(23, 22); - this.gammaDisplay.Text = "γ"; - this.gammaDisplay.ToolTipText = "Override display of linear data in gamma space\r\n\r\nSee FAQ on \"Gamma display of li" + - "near data\""; - this.gammaDisplay.CheckedChanged += new System.EventHandler(this.updateChannelsHandler); - // - // gammaSeparator - // - this.gammaSeparator.Name = "gammaSeparator"; - this.gammaSeparator.Size = new System.Drawing.Size(6, 25); - // - // textureList - // - this.texlistContainer.SetColumnSpan(this.textureList, 2); - this.textureList.Dock = System.Windows.Forms.DockStyle.Fill; - this.textureList.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; - this.textureList.IntegralHeight = false; - this.textureList.ItemHeight = 16; - this.textureList.Location = new System.Drawing.Point(3, 50); - this.textureList.Name = "textureList"; - this.textureList.SelectionMode = System.Windows.Forms.SelectionMode.None; - this.textureList.Size = new System.Drawing.Size(130, 207); - this.textureList.TabIndex = 0; - this.textureList.MouseUp += new System.Windows.Forms.MouseEventHandler(this.textureList_MouseUp); - // // texPanel // this.texPanel.AutoScroll = true; @@ -1197,43 +1252,6 @@ this.rtPanel.TabIndex = 2; this.rtPanel.MouseClick += new System.Windows.Forms.MouseEventHandler(this.thumbsLayout_MouseClick); // - // pixelContext - // - this.pixelContext.BackColor = System.Drawing.Color.Transparent; - this.pixelContext.Dock = System.Windows.Forms.DockStyle.Fill; - this.pixelContext.Location = new System.Drawing.Point(3, 3); - this.pixelContext.Name = "pixelContext"; - this.pixelContext.Size = new System.Drawing.Size(102, 92); - this.pixelContext.TabIndex = 6; - this.pixelContext.Paint += new System.Windows.Forms.PaintEventHandler(this.pixelContext_Paint); - // - // renderContainer - // - this.renderContainer.BackColor = System.Drawing.Color.Maroon; - this.renderContainer.Controls.Add(this.render); - this.renderContainer.Dock = System.Windows.Forms.DockStyle.Fill; - this.renderContainer.Location = new System.Drawing.Point(0, 0); - this.renderContainer.Margin = new System.Windows.Forms.Padding(0); - this.renderContainer.Name = "renderContainer"; - this.renderContainer.Size = new System.Drawing.Size(404, 231); - this.renderContainer.TabIndex = 1; - // - // render - // - this.render.BackColor = System.Drawing.Color.Black; - this.render.Dock = System.Windows.Forms.DockStyle.Fill; - this.render.Location = new System.Drawing.Point(0, 0); - this.render.Name = "render"; - this.render.Size = new System.Drawing.Size(404, 231); - this.render.TabIndex = 0; - this.render.Paint += new System.Windows.Forms.PaintEventHandler(this.render_Paint); - this.render.Layout += new System.Windows.Forms.LayoutEventHandler(this.render_Layout); - this.render.MouseClick += new System.Windows.Forms.MouseEventHandler(this.render_MouseClick); - this.render.MouseDown += new System.Windows.Forms.MouseEventHandler(this.render_MouseClick); - this.render.MouseLeave += new System.EventHandler(this.render_MouseLeave); - this.render.MouseMove += new System.Windows.Forms.MouseEventHandler(this.render_MouseMove); - this.render.MouseUp += new System.Windows.Forms.MouseEventHandler(this.render_MouseUp); - // // rangeHistogram // this.rangeHistogram.BackColor = System.Drawing.SystemColors.GradientActiveCaption; @@ -1299,10 +1317,10 @@ this.renderToolstripContainer.ResumeLayout(false); this.renderToolstripContainer.PerformLayout(); this.renderScrollTable.ResumeLayout(false); + this.renderContainer.ResumeLayout(false); this.pixelContextPanel.ResumeLayout(false); this.pixelContextPanel.PerformLayout(); this.tabContextMenu.ResumeLayout(false); - this.renderContainer.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -1403,6 +1421,8 @@ private System.Windows.Forms.ToolStripButton customEdit; private System.Windows.Forms.ToolStripButton gammaDisplay; private System.Windows.Forms.ToolStripSeparator gammaSeparator; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.Button pixelHistory; } } \ No newline at end of file diff --git a/renderdocui/Windows/TextureViewer.cs b/renderdocui/Windows/TextureViewer.cs index 4595e9fa9..aeffd0382 100644 --- a/renderdocui/Windows/TextureViewer.cs +++ b/renderdocui/Windows/TextureViewer.cs @@ -1291,7 +1291,11 @@ namespace renderdocui.Windows if (value == true) { debugPixel.Enabled = debugPixelContext.Enabled = true; - debugPixel.Text = debugPixelContext.Text = "Debug this Pixel"; + toolTip.RemoveAll(); + toolTip.SetToolTip(debugPixelContext, "Debug this pixel"); + toolTip.SetToolTip(pixelHistory, "Show history for this pixel"); + + pixelHistory.Enabled = true; } else { @@ -1299,7 +1303,11 @@ namespace renderdocui.Windows m_CurRealValue = null; debugPixel.Enabled = debugPixelContext.Enabled = false; - debugPixel.Text = debugPixelContext.Text = "RMB to Pick"; + toolTip.RemoveAll(); + toolTip.SetToolTip(debugPixelContext, "Right Click to choose a pixel"); + toolTip.SetToolTip(pixelHistory, "Right Click to choose a pixel"); + + pixelHistory.Enabled = false; } pixelContext.Invalidate(); @@ -2544,6 +2552,22 @@ namespace renderdocui.Windows render.Invalidate(); } + private void pixelHistory_Click(object sender, EventArgs e) + { + PixelModification[] history = null; + + m_Core.Renderer.BeginInvoke((ReplayRenderer r) => + { + history = r.PixelHistory(CurrentTexture.ID, (UInt32)m_PickedPoint.X, (UInt32)m_PickedPoint.Y); + + this.BeginInvoke(new Action(() => + { + PixelHistoryView hist = new PixelHistoryView(m_Core, CurrentTexture, m_PickedPoint, history); + hist.Show(DockPanel); + })); + }); + } + private void debugPixel_Click(object sender, EventArgs e) { ShaderDebugTrace trace = null; diff --git a/renderdocui/Windows/TextureViewer.resx b/renderdocui/Windows/TextureViewer.resx index 0d13e7f8b..ee701534d 100644 --- a/renderdocui/Windows/TextureViewer.resx +++ b/renderdocui/Windows/TextureViewer.resx @@ -241,6 +241,9 @@ 134, 54 + + 243, 54 + 279, 17 diff --git a/renderdocui/renderdocui.csproj b/renderdocui/renderdocui.csproj index d59e6a629..902b699bf 100644 --- a/renderdocui/renderdocui.csproj +++ b/renderdocui/renderdocui.csproj @@ -265,6 +265,12 @@ PipelineStateViewer.cs + + Form + + + PixelHistoryView.cs + Form @@ -355,6 +361,9 @@ PipelineStateViewer.cs + + PixelHistoryView.cs + ShaderViewer.cs