mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-19 10:31:07 +00:00
Re-implement GL RenderMesh in the new terms - much simpler!
* Still missing several features: - solid shading of 'secondary' data - highlighting of vertices/faces/supporting faces - helpers like axis markers or frustum - post VS data and re-projection
This commit is contained in:
1 parent
da2470dbcf
commit
8318720561
6 files changed
+258
-94
No files matched your search
@@ -113,6 +113,11 @@ BINDING(0) uniform HistogramCBufferData
|
||||
#define RESTYPE_TEX2DMS 0xA
|
||||
#define RESTYPE_TEXTYPEMAX 0xA
|
||||
|
||||
#define MESHDISPLAY_SOLID 0x1
|
||||
#define MESHDISPLAY_FACELIT 0x2
|
||||
#define MESHDISPLAY_SECONDARY 0x3
|
||||
#define MESHDISPLAY_SECONDARY_ALPHA 0x4
|
||||
|
||||
#define TEXDISPLAY_TYPEMASK 0xF
|
||||
#define TEXDISPLAY_UINT_TEX 0x10
|
||||
#define TEXDISPLAY_SINT_TEX 0x20
|
||||
|
||||
@@ -659,6 +659,58 @@ ResourceFormat MakeResourceFormat(WrappedOpenGL &gl, GLenum target, GLenum fmt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
GLenum MakeGLPrimitiveTopology(PrimitiveTopology Topo)
|
||||
{
|
||||
switch(Topo)
|
||||
{
|
||||
default: return eGL_NONE;
|
||||
case eTopology_PointList: return eGL_POINTS;
|
||||
case eTopology_LineStrip: return eGL_LINE_STRIP;
|
||||
case eTopology_LineLoop: return eGL_LINE_LOOP;
|
||||
case eTopology_LineList: return eGL_LINES;
|
||||
case eTopology_LineStrip_Adj: return eGL_LINE_STRIP_ADJACENCY;
|
||||
case eTopology_LineList_Adj: return eGL_LINES_ADJACENCY;
|
||||
case eTopology_TriangleStrip: return eGL_TRIANGLE_STRIP;
|
||||
case eTopology_TriangleFan: return eGL_TRIANGLE_FAN;
|
||||
case eTopology_TriangleList: return eGL_TRIANGLES;
|
||||
case eTopology_TriangleStrip_Adj: return eGL_TRIANGLE_STRIP_ADJACENCY;
|
||||
case eTopology_TriangleList_Adj: return eGL_TRIANGLES_ADJACENCY;
|
||||
case eTopology_PatchList_1CPs:
|
||||
case eTopology_PatchList_2CPs:
|
||||
case eTopology_PatchList_3CPs:
|
||||
case eTopology_PatchList_4CPs:
|
||||
case eTopology_PatchList_5CPs:
|
||||
case eTopology_PatchList_6CPs:
|
||||
case eTopology_PatchList_7CPs:
|
||||
case eTopology_PatchList_8CPs:
|
||||
case eTopology_PatchList_9CPs:
|
||||
case eTopology_PatchList_10CPs:
|
||||
case eTopology_PatchList_11CPs:
|
||||
case eTopology_PatchList_12CPs:
|
||||
case eTopology_PatchList_13CPs:
|
||||
case eTopology_PatchList_14CPs:
|
||||
case eTopology_PatchList_15CPs:
|
||||
case eTopology_PatchList_16CPs:
|
||||
case eTopology_PatchList_17CPs:
|
||||
case eTopology_PatchList_18CPs:
|
||||
case eTopology_PatchList_19CPs:
|
||||
case eTopology_PatchList_20CPs:
|
||||
case eTopology_PatchList_21CPs:
|
||||
case eTopology_PatchList_22CPs:
|
||||
case eTopology_PatchList_23CPs:
|
||||
case eTopology_PatchList_24CPs:
|
||||
case eTopology_PatchList_25CPs:
|
||||
case eTopology_PatchList_26CPs:
|
||||
case eTopology_PatchList_27CPs:
|
||||
case eTopology_PatchList_28CPs:
|
||||
case eTopology_PatchList_29CPs:
|
||||
case eTopology_PatchList_30CPs:
|
||||
case eTopology_PatchList_31CPs:
|
||||
case eTopology_PatchList_32CPs:
|
||||
return eGL_PATCHES;
|
||||
}
|
||||
}
|
||||
|
||||
PrimitiveTopology MakePrimitiveTopology(const GLHookSet &gl, GLenum Topo)
|
||||
{
|
||||
switch(Topo)
|
||||
|
||||
@@ -87,6 +87,7 @@ GLenum ShaderEnum(size_t idx);
|
||||
ResourceFormat MakeResourceFormat(WrappedOpenGL &gl, GLenum target, GLenum fmt);
|
||||
GLenum MakeGLFormat(WrappedOpenGL &gl, GLenum target, ResourceFormat fmt);
|
||||
PrimitiveTopology MakePrimitiveTopology(const GLHookSet &gl, GLenum Topo);
|
||||
GLenum MakeGLPrimitiveTopology(PrimitiveTopology Topo);
|
||||
const char *BlendString(GLenum blendenum);
|
||||
const char *SamplerString(GLenum smpenum);
|
||||
|
||||
|
||||
@@ -1008,6 +1008,8 @@ bool GLReplay::RenderTexture(TextureDisplay cfg)
|
||||
gl.glBlendFunc(eGL_SRC_ALPHA, eGL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
gl.glDisable(eGL_DEPTH_TEST);
|
||||
|
||||
gl.glEnable(eGL_FRAMEBUFFER_SRGB);
|
||||
|
||||
gl.glBindVertexArray(DebugData.emptyVAO);
|
||||
@@ -1452,61 +1454,12 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl
|
||||
|
||||
void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshFormat> &secondaryDraws, MeshDisplay cfg)
|
||||
{
|
||||
#if 0
|
||||
WrappedOpenGL &gl = *m_pDriver;
|
||||
|
||||
MakeCurrentReplayContext(m_DebugCtx);
|
||||
|
||||
GLuint curFBO = 0;
|
||||
gl.glGetIntegerv(eGL_FRAMEBUFFER_BINDING, (GLint*)&curFBO);
|
||||
|
||||
OutputWindow *outw = NULL;
|
||||
for(auto it = m_OutputWindows.begin(); it != m_OutputWindows.end(); ++it)
|
||||
{
|
||||
if(it->second.BlitData.windowFBO == curFBO)
|
||||
{
|
||||
outw = &it->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!outw) return;
|
||||
|
||||
const auto &attr = m_CurPipelineState.m_VtxIn.attributes[0];
|
||||
const auto &vb = m_CurPipelineState.m_VtxIn.vbuffers[attr.BufferSlot];
|
||||
|
||||
if(vb.Buffer == ResourceId())
|
||||
if(cfg.position.buf == ResourceId())
|
||||
return;
|
||||
|
||||
MakeCurrentReplayContext(&m_ReplayCtx);
|
||||
|
||||
GLint viewport[4];
|
||||
gl.glGetIntegerv(eGL_VIEWPORT, viewport);
|
||||
|
||||
gl.glGetIntegerv(eGL_FRAMEBUFFER_BINDING, (GLint*)&curFBO);
|
||||
|
||||
if(outw->BlitData.replayFBO == 0)
|
||||
{
|
||||
gl.glGenFramebuffers(1, &outw->BlitData.replayFBO);
|
||||
gl.glBindFramebuffer(eGL_FRAMEBUFFER, outw->BlitData.replayFBO);
|
||||
|
||||
gl.glFramebufferTexture(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, outw->BlitData.backbuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glBindFramebuffer(eGL_FRAMEBUFFER, outw->BlitData.replayFBO);
|
||||
}
|
||||
|
||||
gl.glViewport(0, 0, (GLsizei)DebugData.outWidth, (GLsizei)DebugData.outHeight);
|
||||
|
||||
GLuint curProg = 0;
|
||||
gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg);
|
||||
|
||||
gl.glUseProgram(DebugData.meshProg);
|
||||
|
||||
float wireCol[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
GLint colLoc = gl.glGetUniformLocation(DebugData.meshProg, "RENDERDOC_GenericFS_Color");
|
||||
gl.glUniform4fv(colLoc, 1, wireCol);
|
||||
MakeCurrentReplayContext(m_DebugCtx);
|
||||
|
||||
Matrix4f projMat = Matrix4f::Perspective(90.0f, 0.1f, 100000.0f, DebugData.outWidth/DebugData.outHeight);
|
||||
|
||||
@@ -1519,62 +1472,203 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
|
||||
Matrix4f camMat = cam.GetMatrix();
|
||||
|
||||
Matrix4f ModelViewProj = projMat.Mul(camMat);
|
||||
|
||||
GLint mvpLoc = gl.glGetUniformLocation(DebugData.meshProg, "ModelViewProj");
|
||||
gl.glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, ModelViewProj.Data());
|
||||
|
||||
GLuint curVAO = 0;
|
||||
gl.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint*)&curVAO);
|
||||
|
||||
GLuint curArr = 0;
|
||||
gl.glGetIntegerv(eGL_ARRAY_BUFFER_BINDING, (GLint*)&curArr);
|
||||
|
||||
gl.glBindVertexArray(DebugData.meshVAO);
|
||||
|
||||
// TODO: we should probably use glBindVertexBuffer, glVertexAttribFormat, glVertexAttribBinding.
|
||||
// For now just assume things about the format and vbuffer.
|
||||
const MeshFormat *fmts[2] = { &cfg.position, &cfg.second };
|
||||
|
||||
gl.glBindBuffer(eGL_ARRAY_BUFFER, m_pDriver->GetResourceManager()->GetLiveResource(vb.Buffer).name);
|
||||
for(uint32_t i=0; i < 2; i++)
|
||||
{
|
||||
if(fmts[i]->buf == ResourceId()) continue;
|
||||
|
||||
if(attr.Format.compType == eCompType_Float && attr.Format.compByteWidth == 4)
|
||||
{
|
||||
gl.glVertexAttribPointer(0, attr.Format.compCount, eGL_FLOAT, GL_FALSE, 0, (void *)intptr_t(vb.Offset + attr.RelativeOffset));
|
||||
}
|
||||
else if(attr.Format.compType == eCompType_Float && attr.Format.compByteWidth == 2)
|
||||
{
|
||||
gl.glVertexAttribPointer(0, attr.Format.compCount, eGL_HALF_FLOAT, GL_FALSE, 0, (void *)intptr_t(vb.Offset + attr.RelativeOffset));
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Not handling mesh display of unsupported format");
|
||||
return;
|
||||
if(fmts[i]->specialFormat != eSpecial_Unknown)
|
||||
{
|
||||
if(fmts[i]->specialFormat == eSpecial_R10G10B10A2)
|
||||
{
|
||||
if(fmts[i]->compType == eCompType_UInt)
|
||||
gl.glVertexAttribIFormat(i, 4, eGL_UNSIGNED_INT_2_10_10_10_REV, 0);
|
||||
if(fmts[i]->compType == eCompType_SInt)
|
||||
gl.glVertexAttribIFormat(i, 4, eGL_INT_2_10_10_10_REV, 0);
|
||||
}
|
||||
else if(fmts[i]->specialFormat == eSpecial_R11G11B10)
|
||||
{
|
||||
gl.glVertexAttribFormat(i, 4, eGL_UNSIGNED_INT_10F_11F_11F_REV, GL_FALSE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCWARN("Unsupported special vertex attribute format: %x", fmts[i]->specialFormat);
|
||||
}
|
||||
}
|
||||
else if(fmts[i]->compType == eCompType_Float ||
|
||||
fmts[i]->compType == eCompType_UNorm ||
|
||||
fmts[i]->compType == eCompType_SNorm)
|
||||
{
|
||||
GLenum fmttype = eGL_UNSIGNED_INT;
|
||||
|
||||
if(fmts[i]->compByteWidth == 4)
|
||||
{
|
||||
if(fmts[i]->compType == eCompType_Float) fmttype = eGL_FLOAT;
|
||||
else if(fmts[i]->compType == eCompType_UNorm) fmttype = eGL_UNSIGNED_INT;
|
||||
else if(fmts[i]->compType == eCompType_SNorm) fmttype = eGL_INT;
|
||||
}
|
||||
else if(fmts[i]->compByteWidth == 2)
|
||||
{
|
||||
if(fmts[i]->compType == eCompType_Float) fmttype = eGL_HALF_FLOAT;
|
||||
else if(fmts[i]->compType == eCompType_UNorm) fmttype = eGL_UNSIGNED_SHORT;
|
||||
else if(fmts[i]->compType == eCompType_SNorm) fmttype = eGL_SHORT;
|
||||
}
|
||||
else if(fmts[i]->compByteWidth == 1)
|
||||
{
|
||||
if(fmts[i]->compType == eCompType_UNorm) fmttype = eGL_UNSIGNED_BYTE;
|
||||
else if(fmts[i]->compType == eCompType_SNorm) fmttype = eGL_BYTE;
|
||||
}
|
||||
|
||||
gl.glVertexAttribFormat(i, fmts[i]->compCount, fmttype, fmts[i]->compType != eCompType_Float, 0);
|
||||
}
|
||||
else if(fmts[i]->compType == eCompType_UInt ||
|
||||
fmts[i]->compType == eCompType_SInt)
|
||||
{
|
||||
GLenum fmttype = eGL_UNSIGNED_INT;
|
||||
|
||||
if(fmts[i]->compByteWidth == 4)
|
||||
{
|
||||
if(fmts[i]->compType == eCompType_UInt) fmttype = eGL_UNSIGNED_INT;
|
||||
else if(fmts[i]->compType == eCompType_SInt) fmttype = eGL_INT;
|
||||
}
|
||||
else if(fmts[i]->compByteWidth == 2)
|
||||
{
|
||||
if(fmts[i]->compType == eCompType_UInt) fmttype = eGL_UNSIGNED_SHORT;
|
||||
else if(fmts[i]->compType == eCompType_SInt) fmttype = eGL_SHORT;
|
||||
}
|
||||
else if(fmts[i]->compByteWidth == 1)
|
||||
{
|
||||
if(fmts[i]->compType == eCompType_UInt) fmttype = eGL_UNSIGNED_BYTE;
|
||||
else if(fmts[i]->compType == eCompType_SInt) fmttype = eGL_BYTE;
|
||||
}
|
||||
|
||||
gl.glVertexAttribIFormat(i, fmts[i]->compCount, fmttype, 0);
|
||||
}
|
||||
else if(fmts[i]->compType == eCompType_Double)
|
||||
{
|
||||
gl.glVertexAttribLFormat(i, fmts[i]->compCount, eGL_DOUBLE, 0);
|
||||
}
|
||||
|
||||
gl.glBindVertexBuffer(i, m_pDriver->GetResourceManager()->GetCurrentResource(fmts[i]->buf).name, fmts[i]->offset, fmts[i]->stride);
|
||||
}
|
||||
|
||||
// enable position attribute
|
||||
gl.glEnableVertexAttribArray(0);
|
||||
|
||||
GLenum topo = MakeGLPrimitiveTopology(cfg.position.topo);
|
||||
|
||||
gl.glDisable(eGL_DEPTH_TEST);
|
||||
|
||||
GLuint prog = DebugData.meshProg;
|
||||
|
||||
if(cfg.solidShadeMode == eShade_Lit)
|
||||
{
|
||||
GLint depthTest = GL_FALSE;
|
||||
gl.glGetIntegerv(eGL_DEPTH_TEST, (GLint*)&depthTest);
|
||||
GLenum polyMode = eGL_FILL;
|
||||
if(!VendorCheck[VendorCheck_AMD_polygon_mode_query])
|
||||
gl.glGetIntegerv(eGL_POLYGON_MODE, (GLint*)&polyMode);
|
||||
// pick program with GS for per-face lighting
|
||||
}
|
||||
|
||||
GLint colLoc = gl.glGetUniformLocation(prog, "RENDERDOC_GenericFS_Color");
|
||||
GLint mvpLoc = gl.glGetUniformLocation(prog, "ModelViewProj");
|
||||
GLint fmtLoc = gl.glGetUniformLocation(prog, "Mesh_DisplayFormat");
|
||||
|
||||
gl.glUseProgram(prog);
|
||||
|
||||
if(cfg.position.unproject)
|
||||
{
|
||||
// calc reproject matrix
|
||||
}
|
||||
|
||||
gl.glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, ModelViewProj.Data());
|
||||
|
||||
// solid render
|
||||
if(cfg.solidShadeMode != eShade_None && topo != eGL_PATCHES)
|
||||
{
|
||||
if(cfg.solidShadeMode == eShade_Lit)
|
||||
{
|
||||
// set GS-specific uniform
|
||||
}
|
||||
|
||||
float wireCol[] = { 0.8f, 0.8f, 0.0f, 1.0f };
|
||||
gl.glUniform4fv(colLoc, 1, wireCol);
|
||||
|
||||
GLint OutputDisplayFormat = (int)cfg.solidShadeMode;
|
||||
if(cfg.solidShadeMode == eShade_Secondary && cfg.second.showAlpha)
|
||||
OutputDisplayFormat = MESHDISPLAY_SECONDARY_ALPHA;
|
||||
gl.glUniform1i(fmtLoc, OutputDisplayFormat);
|
||||
|
||||
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_FILL);
|
||||
|
||||
if(cfg.position.idxbuf != ResourceId())
|
||||
{
|
||||
GLenum idxtype = eGL_UNSIGNED_BYTE;
|
||||
if(cfg.position.idxByteWidth == 2)
|
||||
idxtype = eGL_UNSIGNED_SHORT;
|
||||
else if(cfg.position.idxByteWidth == 4)
|
||||
idxtype = eGL_UNSIGNED_INT;
|
||||
|
||||
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, m_pDriver->GetResourceManager()->GetCurrentResource(cfg.position.idxbuf).name);
|
||||
gl.glDrawElements(topo, cfg.position.numVerts, idxtype, (const void *)(cfg.position.idxoffs));
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glDrawArrays(topo, 0, cfg.position.numVerts);
|
||||
}
|
||||
}
|
||||
|
||||
colLoc = gl.glGetUniformLocation(prog, "RENDERDOC_GenericFS_Color");
|
||||
mvpLoc = gl.glGetUniformLocation(prog, "ModelViewProj");
|
||||
fmtLoc = gl.glGetUniformLocation(prog, "Mesh_DisplayFormat");
|
||||
|
||||
gl.glUseProgram(prog);
|
||||
|
||||
gl.glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, ModelViewProj.Data());
|
||||
|
||||
// wireframe render
|
||||
if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw || topo == eGL_PATCHES)
|
||||
{
|
||||
float wireCol[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
gl.glUniform4fv(colLoc, 1, wireCol);
|
||||
|
||||
gl.glDisable(eGL_DEPTH_TEST);
|
||||
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_LINE);
|
||||
|
||||
ReplayLog(frameID, 0, events[0], eReplay_OnlyDraw);
|
||||
if(topo == eGL_PATCHES) topo = eGL_POINTS;
|
||||
|
||||
if(depthTest)
|
||||
gl.glEnable(eGL_DEPTH_TEST);
|
||||
if(polyMode != eGL_LINE)
|
||||
gl.glPolygonMode(eGL_FRONT_AND_BACK, polyMode);
|
||||
if(cfg.position.idxbuf != ResourceId())
|
||||
{
|
||||
GLenum idxtype = eGL_UNSIGNED_BYTE;
|
||||
if(cfg.position.idxByteWidth == 2)
|
||||
idxtype = eGL_UNSIGNED_SHORT;
|
||||
else if(cfg.position.idxByteWidth == 4)
|
||||
idxtype = eGL_UNSIGNED_INT;
|
||||
|
||||
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, m_pDriver->GetResourceManager()->GetCurrentResource(cfg.position.idxbuf).name);
|
||||
gl.glDrawElements(topo, cfg.position.numVerts, idxtype, (const void *)(cfg.position.idxoffs));
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glDrawArrays(topo, 0, cfg.position.numVerts);
|
||||
}
|
||||
}
|
||||
|
||||
if(!cfg.position.unproject)
|
||||
{
|
||||
// draw axis markers
|
||||
}
|
||||
|
||||
if(cfg.highlightVert != ~0U)
|
||||
{
|
||||
// show highlighted vertex
|
||||
}
|
||||
|
||||
gl.glBindVertexArray(curVAO);
|
||||
gl.glBindBuffer(eGL_ARRAY_BUFFER, curArr);
|
||||
|
||||
gl.glUseProgram(curProg);
|
||||
gl.glViewport(viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
|
||||
gl.glBindFramebuffer(eGL_FRAMEBUFFER, curFBO);
|
||||
#endif
|
||||
if(cfg.position.unproject)
|
||||
{
|
||||
// 'fake' helper frustum
|
||||
}
|
||||
|
||||
// set this back as most other things want fill, and we don't want to have to a) track it
|
||||
// b) set fill explicitly everywhere else
|
||||
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_FILL);
|
||||
}
|
||||
@@ -1100,7 +1100,7 @@ void GLReplay::SavePipelineState()
|
||||
fmt.special = true;
|
||||
fmt.specialFormat = eSpecial_R11G11B10;
|
||||
fmt.compCount = 3;
|
||||
fmt.compType = eCompType_SInt;
|
||||
fmt.compType = eCompType_Float;
|
||||
fmt.strname = "GL_UNSIGNED_INT_10F_11F_11F_REV";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -406,6 +406,18 @@ namespace renderdocui.Code
|
||||
ret[a].InstanceRate = (int)m_GL.m_VtxIn.vbuffers[attrs[i].BufferSlot].Divisor;
|
||||
ret[a].Format = attrs[i].Format;
|
||||
|
||||
if (m_GL.m_VS.ShaderDetails != null)
|
||||
{
|
||||
foreach (var isig in m_GL.m_VS.ShaderDetails.InputSig)
|
||||
{
|
||||
if (isig.regIndex == attrs[i].BufferSlot)
|
||||
{
|
||||
ret[a].Name = isig.varName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a++;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user