Implement quad overdraw overlays for GL

* The implementation needs the fine dFdx/dFdy variants, which are only
  available in GLSL 4.50 and above. Without that support we fall back
  to the normal dFdx/dFdy which are implementation dependent. In my
  quick test on nvidia it so happened that it was still fine, but that's
  not guaranteed.
This commit is contained in:
baldurk
2015-02-12 20:04:48 +00:00
parent a7185cbf9c
commit 7cbb68f329
11 changed files with 415 additions and 28 deletions
+1
View File
@@ -74,6 +74,7 @@ data/glsl/mesh.frago \
data/glsl/mesh.geomo \
data/glsl/text.verto \
data/glsl/text.frago \
data/glsl/quadoverdraw.frago \
data/glsl/histogram.compo \
data/glsl/arraymscopy.compo \
data/sourcecodepro.ttfo
+1
View File
@@ -35,6 +35,7 @@ DECLARE_EMBED(blit_frag);
DECLARE_EMBED(texdisplay_frag);
DECLARE_EMBED(checkerboard_frag);
DECLARE_EMBED(histogram_comp);
DECLARE_EMBED(quadoverdraw_frag);
DECLARE_EMBED(arraymscopy_comp);
DECLARE_EMBED(mesh_vert);
DECLARE_EMBED(mesh_frag);
+96
View File
@@ -0,0 +1,96 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015 Baldur Karlsson
*
* 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.
******************************************************************************/
////////////////////////////////////////////////////////////////////////////////////////////
// Below shaders courtesy of Stephen Hill (@self_shadow), converted to glsl trivially
//
// http://blog.selfshadow.com/2012/11/12/counting-quads/
// https://github.com/selfshadow/demos/blob/master/QuadShading/QuadShading.fx
////////////////////////////////////////////////////////////////////////////////////////////
layout(binding = 0, r32ui) uniform coherent uimage2DArray overdrawImage;
#ifdef RENDERDOC_QuadOverdrawPS
layout(early_fragment_tests) in;
void main()
{
uint c0 = uint(gl_SampleMaskIn[0]);
// Obtain coverage for all pixels in the quad, via 'message passing'*.
// (* For more details, see:
// "Shader Amortization using Pixel Quad Message Passing", Eric Penner, GPU Pro 2.)
uvec2 p = uvec2(uint(gl_FragCoord.x) & 1, uint(gl_FragCoord.y) & 1);
ivec2 sign = ivec2(p.x > 0 ? -1 : 1, p.y > 0 ? -1 : 1);
uint c1 = c0 + sign.x*int(dFdxFine(c0));
uint c2 = c0 + sign.y*int(dFdyFine(c0));
uint c3 = c2 + sign.x*int(dFdxFine(c2));
// Count the live pixels, minus 1 (zero indexing)
uint pixelCount = c0 + c1 + c2 + c3 - 1;
ivec3 quad = ivec3(gl_FragCoord.xy*0.5, pixelCount);
imageAtomicAdd(overdrawImage, quad, 1);
}
#endif // RENDERDOC_QuadOverdrawPS
#ifdef RENDERDOC_QOResolvePS
#define NUM_RAMP_COLOURS 128
uniform vec4 overdrawRampColours[NUM_RAMP_COLOURS];
vec4 ToColour(uint v)
{
return overdrawRampColours[min(v, uint(NUM_RAMP_COLOURS-1))];
}
layout (location = 0) out vec4 color_out;
void main()
{
ivec2 quad = ivec2(gl_FragCoord.xy*0.5f);
uint overdraw = 0;
for(uint i = 0; i < 4; i++)
overdraw += imageLoad(overdrawImage, ivec3(quad, i)).x/(i + 1);
color_out = ToColour(overdraw);
}
#endif // RENDERDOC_QOResolvePS
////////////////////////////////////////////////////////////////////////////////////////////
// Above shaders courtesy of Stephen Hill (@self_shadow), converted to glsl trivially
//
// http://blog.selfshadow.com/2012/11/12/counting-quads/
// https://github.com/selfshadow/demos/blob/master/QuadShading/QuadShading.fx
////////////////////////////////////////////////////////////////////////////////////////////
+1
View File
@@ -124,6 +124,7 @@ RESOURCE_histogram_comp TYPE_EMBED "glsl/histogram.comp"
RESOURCE_mesh_frag TYPE_EMBED "glsl/mesh.frag"
RESOURCE_mesh_geom TYPE_EMBED "glsl/mesh.geom"
RESOURCE_arraymscopy_comp TYPE_EMBED "glsl/arraymscopy.comp"
RESOURCE_quadoverdraw_frag TYPE_EMBED "glsl/quadoverdraw.frag"
RESOURCE_sourcecodepro_ttf TYPE_EMBED "sourcecodepro.ttf"
+1
View File
@@ -26,6 +26,7 @@
#define RESOURCE_mesh_frag 213
#define RESOURCE_mesh_geom 214
#define RESOURCE_arraymscopy_comp 215
#define RESOURCE_quadoverdraw_frag 216
#define RESOURCE_sourcecodepro_ttf 301
+288 -28
View File
@@ -180,6 +180,8 @@ void GLReplay::InitDebugData()
MakeCurrentReplayContext(m_DebugCtx);
}
WrappedOpenGL &gl = *m_pDriver;
DebugData.outWidth = 0.0f; DebugData.outHeight = 0.0f;
string blitvsSource = GetEmbeddedResource(blit_vert);
@@ -205,6 +207,54 @@ void GLReplay::InitDebugData()
DebugData.texDisplayProg[i] = CreateShaderProgram(NULL, glsl.c_str());
}
GLint numsl = 0;
gl.glGetIntegerv(eGL_NUM_SHADING_LANGUAGE_VERSIONS, &numsl);
bool support450 = false;
for(GLint i=0; i < numsl; i++)
{
const char *sl = (const char *)gl.glGetStringi(eGL_SHADING_LANGUAGE_VERSION, (GLuint)i);
if(sl[0] == '4' && sl[1] == '5' && sl[2] == '0')
support450 = true;
if(sl[0] == '4' && sl[1] == '.' && sl[2] == '5')
support450 = true;
if(support450)
break;
}
if(support450)
{
DebugData.quadoverdraw420 = false;
string glsl = "#version 450 core\n\n";
glsl += "#define RENDERDOC_QuadOverdrawPS\n\n";
glsl += GetEmbeddedResource(quadoverdraw_frag);
DebugData.quadoverdrawFSProg = CreateShaderProgram(NULL, glsl.c_str());
glsl = "#version 420 core\n\n";
glsl += "#define RENDERDOC_QOResolvePS\n\n";
glsl += GetEmbeddedResource(quadoverdraw_frag);
DebugData.quadoverdrawResolveProg = CreateShaderProgram(blitvsSource.c_str(), glsl.c_str());
}
else
{
DebugData.quadoverdraw420 = true;
string glsl = "#version 420 core\n\n";
glsl += "#define RENDERDOC_QuadOverdrawPS\n\n";
glsl += "#define dFdxFine dFdx\n\n"; // dFdx fine functions not available before GLSL 450
glsl += "#define dFdyFine dFdy\n\n"; // use normal dFdx, which might be coarse, so won't show quad overdraw properly
glsl += GetEmbeddedResource(quadoverdraw_frag);
DebugData.quadoverdrawFSProg = CreateShaderProgram(NULL, glsl.c_str());
glsl = "#version 420 core\n\n";
glsl += "#define RENDERDOC_QOResolvePS\n\n";
glsl += GetEmbeddedResource(quadoverdraw_frag);
DebugData.quadoverdrawResolveProg = CreateShaderProgram(blitvsSource.c_str(), glsl.c_str());
}
string checkerfs = GetEmbeddedResource(checkerboard_frag);
DebugData.checkerProg = CreateShaderProgram(blitvsSource.c_str(), checkerfs.c_str());
@@ -223,8 +273,6 @@ void GLReplay::InitDebugData()
DebugData.meshProg = CreateShaderProgram(meshvs.c_str(), meshfs.c_str());
DebugData.meshgsProg = CreateShaderProgram(meshvs.c_str(), meshfs.c_str(), meshgs.c_str());
WrappedOpenGL &gl = *m_pDriver;
void *ctx = gl.GetCtx();
gl.glGenProgramPipelines(1, &DebugData.texDisplayPipe);
@@ -496,6 +544,12 @@ void GLReplay::DeleteDebugData()
}
gl.glDeleteProgram(DebugData.blitProg);
if(DebugData.quadoverdrawFSProg)
{
gl.glDeleteProgram(DebugData.quadoverdrawFSProg);
gl.glDeleteProgram(DebugData.quadoverdrawResolveProg);
}
gl.glDeleteProgram(DebugData.texDisplayVSProg);
for(int i=0; i < 3; i++)
@@ -1355,34 +1409,21 @@ void GLReplay::RenderHighlightBox(float w, float h, float scale)
gl.glDrawArrays(eGL_LINE_LOOP, 0, 4);
}
ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector<uint32_t> &passEvents)
void GLReplay::SetupOverlayPipeline(GLuint Program, GLuint Pipeline, GLuint fragProgram)
{
WrappedOpenGL &gl = *m_pDriver;
MakeCurrentReplayContext(&m_ReplayCtx);
void *ctx = m_ReplayCtx.ctx;
GLRenderState rs(&gl.GetHookset(), NULL, READING);
rs.FetchState(ctx, &gl);
// use our overlay pipeline that we'll fill up with all the right
// shaders, then replace the fragment shader with our own.
gl.glUseProgram(0);
gl.glBindProgramPipeline(DebugData.overlayPipe);
// we bind the separable program created for each shader, and copy
// uniforms and attrib bindings from the 'real' programs, wherever
// they are.
if(rs.Program == 0)
if(Program == 0)
{
if(rs.Pipeline == 0)
if(Pipeline == 0)
{
return ResourceId();
return;
}
else
{
ResourceId id = m_pDriver->GetResourceManager()->GetID(ProgramPipeRes(ctx, rs.Pipeline));
ResourceId id = m_pDriver->GetResourceManager()->GetID(ProgramPipeRes(ctx, Pipeline));
auto &pipeDetails = m_pDriver->m_Pipelines[id];
for(size_t i=0; i < 4; i++)
@@ -1404,8 +1445,8 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl
}
else
{
auto &progDetails = m_pDriver->m_Programs[m_pDriver->GetResourceManager()->GetID(ProgramRes(ctx, rs.Program))];
auto &progDetails = m_pDriver->m_Programs[m_pDriver->GetResourceManager()->GetID(ProgramRes(ctx, Program))];
for(size_t i=0; i < 4; i++)
{
if(progDetails.stageShaders[i] != ResourceId())
@@ -1414,16 +1455,38 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl
gl.glUseProgramStages(DebugData.overlayPipe, ShaderBit(i), progdst);
CopyProgramUniforms(gl.GetHookset(), rs.Program, progdst);
CopyProgramUniforms(gl.GetHookset(), Program, progdst);
if(i == 0)
CopyProgramAttribBindings(gl.GetHookset(), rs.Program, progdst, GetShader(progDetails.stageShaders[i]));
CopyProgramAttribBindings(gl.GetHookset(), Program, progdst, GetShader(progDetails.stageShaders[i]));
}
}
}
// use the generic FS program by default, can be overridden for specific overlays if needed
gl.glUseProgramStages(DebugData.overlayPipe, eGL_FRAGMENT_SHADER_BIT, DebugData.genericFSProg);
gl.glUseProgramStages(DebugData.overlayPipe, eGL_FRAGMENT_SHADER_BIT, fragProgram);
}
ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector<uint32_t> &passEvents)
{
WrappedOpenGL &gl = *m_pDriver;
MakeCurrentReplayContext(&m_ReplayCtx);
void *ctx = m_ReplayCtx.ctx;
GLRenderState rs(&gl.GetHookset(), NULL, READING);
rs.FetchState(ctx, &gl);
// use our overlay pipeline that we'll fill up with all the right
// shaders, then replace the fragment shader with our own.
gl.glUseProgram(0);
gl.glBindProgramPipeline(DebugData.overlayPipe);
// we bind the separable program created for each shader, and copy
// uniforms and attrib bindings from the 'real' programs, wherever
// they are.
SetupOverlayPipeline(rs.Program, rs.Pipeline, DebugData.genericFSProg);
auto &texDetails = m_pDriver->m_Textures[texid];
@@ -1448,7 +1511,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl
DebugData.overlayTexWidth = texDetails.width;
DebugData.overlayTexHeight = texDetails.height;
gl.glTexStorage2D(eGL_TEXTURE_2D, 1, eGL_SRGB8_ALPHA8, texDetails.width, texDetails.height);
gl.glTexStorage2D(eGL_TEXTURE_2D, 1, eGL_RGBA16, texDetails.width, texDetails.height);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MIN_FILTER, eGL_NEAREST);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAG_FILTER, eGL_NEAREST);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_S, eGL_CLAMP_TO_EDGE);
@@ -1669,8 +1732,205 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl
}
else if(overlay == eTexOverlay_QuadOverdrawDraw || overlay == eTexOverlay_QuadOverdrawPass)
{
float unknown[] = { 0.2f, 0.1f, 0.1f, 0.5f };
gl.glClearBufferfv(eGL_COLOR, 0, unknown);
if(DebugData.quadoverdraw420)
{
RDCWARN("Quad overdraw requires GLSL 4.50 for dFd(xy)fine, using possibly coarse dFd(xy).");
m_pDriver->AddDebugMessage(eDbgCategory_Portability, eDbgSeverity_Medium, eDbgSource_RuntimeWarning,
"Quad overdraw requires GLSL 4.50 for dFd(xy)fine, using possibly coarse dFd(xy).");
}
{
SCOPED_TIMER("Quad Overdraw");
float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
gl.glClearBufferfv(eGL_COLOR, 0, black);
vector<uint32_t> events = passEvents;
if(overlay == eTexOverlay_QuadOverdrawDraw)
events.clear();
events.push_back(eventID);
if(!events.empty())
{
GLuint replacefbo = 0;
GLuint quadtexs[3] = { 0 };
gl.glGenFramebuffers(1, &replacefbo);
gl.glBindFramebuffer(eGL_FRAMEBUFFER, replacefbo);
gl.glGenTextures(3, quadtexs);
// image for quad usage
gl.glBindTexture(eGL_TEXTURE_2D_ARRAY, quadtexs[2]);
gl.glTexStorage3D(eGL_TEXTURE_2D_ARRAY, 1, eGL_R32UI, texDetails.width>>1, texDetails.height>>1, 4);
// temporarily attach to FBO to clear it
GLint zero = 0;
gl.glFramebufferTextureLayer(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, quadtexs[2], 0, 0);
gl.glClearBufferiv(eGL_COLOR, 0, &zero);
gl.glFramebufferTextureLayer(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, quadtexs[2], 0, 1);
gl.glClearBufferiv(eGL_COLOR, 0, &zero);
gl.glFramebufferTextureLayer(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, quadtexs[2], 0, 2);
gl.glClearBufferiv(eGL_COLOR, 0, &zero);
gl.glFramebufferTextureLayer(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, quadtexs[2], 0, 3);
gl.glClearBufferiv(eGL_COLOR, 0, &zero);
gl.glBindTexture(eGL_TEXTURE_2D, quadtexs[0]);
gl.glTexStorage2D(eGL_TEXTURE_2D, 1, eGL_RGBA8, texDetails.width, texDetails.height);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MIN_FILTER, eGL_NEAREST);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAG_FILTER, eGL_NEAREST);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_S, eGL_CLAMP_TO_EDGE);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_T, eGL_CLAMP_TO_EDGE);
gl.glFramebufferTexture(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, quadtexs[0], 0);
gl.glBindTexture(eGL_TEXTURE_2D, quadtexs[1]);
gl.glTexStorage2D(eGL_TEXTURE_2D, 1, eGL_DEPTH32F_STENCIL8, texDetails.width, texDetails.height);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MIN_FILTER, eGL_NEAREST);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAG_FILTER, eGL_NEAREST);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_S, eGL_CLAMP_TO_EDGE);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_T, eGL_CLAMP_TO_EDGE);
gl.glFramebufferTexture(eGL_FRAMEBUFFER, eGL_DEPTH_STENCIL_ATTACHMENT, quadtexs[1], 0);
if(overlay == eTexOverlay_QuadOverdrawPass)
ReplayLog(frameID, 0, events[0], eReplay_WithoutDraw);
else
rs.ApplyState(m_pDriver->GetCtx(), m_pDriver);
GLuint lastProg = 0, lastPipe = 0;
for(size_t i=0; i < events.size(); i++)
{
GLint depthwritemask = 1;
GLint stencilfmask = 0xff, stencilbmask = 0xff;
GLuint curdrawfbo = 0, curreadfbo = 0;
struct
{
GLuint name;
GLuint level;
GLboolean layered;
GLuint layer;
GLenum access;
GLenum format;
} curimage0 = {0};
// save the state we're going to mess with
{
gl.glGetIntegerv(eGL_DEPTH_WRITEMASK, &depthwritemask);
gl.glGetIntegerv(eGL_STENCIL_WRITEMASK, &stencilfmask);
gl.glGetIntegerv(eGL_STENCIL_BACK_WRITEMASK, &stencilbmask);
gl.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint *)&curdrawfbo);
gl.glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, (GLint *)&curreadfbo);
gl.glGetIntegeri_v(eGL_IMAGE_BINDING_NAME, 0, (GLint *)&curimage0.name);
gl.glGetIntegeri_v(eGL_IMAGE_BINDING_LEVEL, 0, (GLint*)&curimage0.level);
gl.glGetIntegeri_v(eGL_IMAGE_BINDING_ACCESS, 0, (GLint*)&curimage0.access);
gl.glGetIntegeri_v(eGL_IMAGE_BINDING_FORMAT, 0, (GLint*)&curimage0.format);
gl.glGetBooleani_v(eGL_IMAGE_BINDING_LAYERED, 0, &curimage0.layered);
if(curimage0.layered)
gl.glGetIntegeri_v(eGL_IMAGE_BINDING_LAYER, 0, (GLint*)&curimage0.layer);
}
// disable depth and stencil writes
gl.glDepthMask(GL_FALSE);
gl.glStencilMask(GL_FALSE);
// bind our FBO
gl.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, replacefbo);
// bind image
gl.glBindImageTexture(0, quadtexs[2], 0, GL_TRUE, 0, eGL_READ_WRITE, eGL_R32UI);
GLuint prog = 0, pipe = 0;
gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint *)&prog);
gl.glGetIntegerv(eGL_PROGRAM_PIPELINE_BINDING, (GLint *)&pipe);
// replace fragment shader. This is exactly what we did
// at the start of this function for the single-event case, but now we have
// to do it for every event
SetupOverlayPipeline(prog, pipe, DebugData.quadoverdrawFSProg);
gl.glUseProgram(0);
gl.glBindProgramPipeline(DebugData.overlayPipe);
lastProg = prog;
lastPipe = pipe;
gl.glBindFramebuffer(eGL_READ_FRAMEBUFFER, curdrawfbo);
gl.glBlitFramebuffer(0, 0, texDetails.width, texDetails.height,
0, 0, texDetails.width, texDetails.height,
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, eGL_NEAREST);
ReplayLog(frameID, events[i], events[i], eReplay_OnlyDraw);
// pop the state that we messed with
{
gl.glBindProgramPipeline(pipe);
gl.glUseProgram(prog);
if(curimage0.name)
gl.glBindImageTexture(0, curimage0.name, curimage0.level, curimage0.layered ? GL_TRUE : GL_FALSE, curimage0.layer, curimage0.access, curimage0.format);
else
gl.glBindImageTexture(0, 0, 0, GL_FALSE, 0, eGL_READ_ONLY, eGL_R32UI);
gl.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, curdrawfbo);
gl.glBindFramebuffer(eGL_READ_FRAMEBUFFER, curreadfbo);
gl.glDepthMask(depthwritemask ? GL_TRUE : GL_FALSE);
gl.glStencilMaskSeparate(eGL_FRONT, (GLuint)stencilfmask);
gl.glStencilMaskSeparate(eGL_BACK, (GLuint)stencilbmask);
}
if(overlay == eTexOverlay_QuadOverdrawPass)
{
ReplayLog(frameID, events[i], events[i], eReplay_OnlyDraw);
if(i+1 < events.size())
ReplayLog(frameID, events[i], events[i+1], eReplay_WithoutDraw);
}
}
// resolve pass
{
gl.glUseProgram(DebugData.quadoverdrawResolveProg);
gl.glBindProgramPipeline(0);
GLint rampLoc = gl.glGetUniformLocation(DebugData.quadoverdrawResolveProg, "overdrawRampColours");
gl.glProgramUniform4fv(DebugData.quadoverdrawResolveProg, rampLoc, ARRAY_COUNT(overdrawRamp), (float *)&overdrawRamp[0].x);
// modify our fbo to attach the overlay texture instead
gl.glBindFramebuffer(eGL_FRAMEBUFFER, replacefbo);
gl.glFramebufferTexture(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, DebugData.overlayTex, 0);
gl.glFramebufferTexture(eGL_FRAMEBUFFER, eGL_DEPTH_STENCIL_ATTACHMENT, 0, 0);
gl.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
gl.glDisable(eGL_BLEND);
gl.glDisable(eGL_SCISSOR_TEST);
gl.glDepthMask(GL_FALSE);
gl.glDisable(eGL_CULL_FACE);
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_FILL);
gl.glDisable(eGL_DEPTH_TEST);
gl.glDisable(eGL_STENCIL_TEST);
gl.glStencilMask(0);
gl.glViewport(0, 0, texDetails.width, texDetails.height);
gl.glBindImageTexture(0, quadtexs[2], 0, GL_FALSE, 0, eGL_READ_WRITE, eGL_R32UI);
GLuint emptyVAO = 0;
gl.glGenVertexArrays(1, &emptyVAO);
gl.glBindVertexArray(emptyVAO);
gl.glDrawArrays(eGL_TRIANGLE_STRIP, 0, 4);
gl.glBindVertexArray(0);
gl.glDeleteVertexArrays(1, &emptyVAO);
gl.glFramebufferTexture(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, quadtexs[0], 0);
}
gl.glDeleteFramebuffers(1, &replacefbo);
gl.glDeleteTextures(3, quadtexs);
if(overlay == eTexOverlay_QuadOverdrawPass)
ReplayLog(frameID, 0, eventID, eReplay_WithoutDraw);
}
}
}
else
{
+15
View File
@@ -1928,6 +1928,21 @@ void WrappedOpenGL::FinishCapture()
//m_SuccessfulCapture = false;
}
void WrappedOpenGL::AddDebugMessage(DebugMessageCategory c, DebugMessageSeverity sv, DebugMessageSource src, std::string d)
{
if(m_State == READING || src == eDbgSource_RuntimeWarning)
{
DebugMessage msg;
msg.eventID = m_CurEventID;
msg.messageID = 0;
msg.source = src;
msg.category = c;
msg.severity = sv;
msg.description = d;
m_DebugMessages.push_back(msg);
}
}
vector<DebugMessage> WrappedOpenGL::GetDebugMessages()
{
vector<DebugMessage> ret;
+3
View File
@@ -373,6 +373,9 @@ class WrappedOpenGL
void SetDebugMsgContext(const char *context) { m_DebugMsgContext = context; }
void AddDebugMessage(DebugMessage msg) { if(m_State < WRITING) m_DebugMessages.push_back(msg); }
void AddDebugMessage(DebugMessageCategory c, DebugMessageSeverity sv, DebugMessageSource src, std::string d);
// replay interface
void Initialise(GLInitParams &params);
void ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType);
+5
View File
@@ -195,6 +195,7 @@ class GLReplay : public IReplayDriver
const vector<byte> &data);
void CreateCustomShaderTex(uint32_t w, uint32_t h);
void SetupOverlayPipeline(GLuint Program, GLuint Pipeline, GLuint fragProgram);
void GetMapping(WrappedOpenGL &gl, GLuint curProg, int shadIdx, ShaderReflection *refl, ShaderBindpointMapping &mapping);
@@ -289,6 +290,10 @@ class GLReplay : public IReplayDriver
GLuint pickPixelTex;
GLuint pickPixelFBO;
GLuint quadoverdrawFSProg;
GLuint quadoverdrawResolveProg;
bool quadoverdraw420;
GLuint overlayTex;
GLuint overlayFBO;
GLuint overlayPipe;
+1
View File
@@ -376,6 +376,7 @@
<None Include="data\glsl\mesh.frag" />
<None Include="data\glsl\mesh.geom" />
<None Include="data\glsl\mesh.vert" />
<None Include="data\glsl\quadoverdraw.frag" />
<None Include="data\glsl\texdisplay.frag" />
<None Include="data\glsl\text.frag" />
<None Include="data\glsl\text.vert" />
+3
View File
@@ -610,6 +610,9 @@
<None Include="data\glsl\arraymscopy.comp">
<Filter>Resources\glsl</Filter>
</None>
<None Include="data\glsl\quadoverdraw.frag">
<Filter>Resources\glsl</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="data\renderdoc.rc">