From 404614616446b56e7acecca4aaabd833964cc7ba Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 15:14:41 +0100 Subject: [PATCH] Add experimental wireframe mode for debugging. Fix texenv color. Code cleanup. --- Core/Config.cpp | 4 ++ Core/Config.h | 1 + GPU/GLES/DisplayListInterpreter.cpp | 32 ++++++++++++++ GPU/GLES/DisplayListInterpreter.h | 6 +++ GPU/GLES/FragmentShaderGenerator.cpp | 2 +- GPU/GLES/ShaderManager.cpp | 16 +++++-- GPU/GLES/TransformPipeline.cpp | 64 +++++++++++++++++----------- Windows/WndMainWindow.cpp | 5 +++ Windows/ppsspp.rc | 1 + Windows/resource.h | 3 +- 10 files changed, 104 insertions(+), 30 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index eb09dece92..befe00334f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -64,6 +64,10 @@ void CConfig::Load(const char *iniFileName) IniFile::Section *control = iniFile.GetOrCreateSection("Control"); control->Get("ShowStick", &bShowAnalogStick, false); control->Get("ShowTouchControls", &bShowTouchControls, true); + + + // Ephemeral settings + bDrawWireframe = false; } void CConfig::Save() diff --git a/Core/Config.h b/Core/Config.h index d873fcb725..461859e4aa 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -43,6 +43,7 @@ public: bool bIgnoreBadMemAccess; bool bDisplayFramebuffer; bool bBufferedRendering; + bool bDrawWireframe; bool bShowTouchControls; bool bShowDebuggerOnLoad; diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 90931d75bc..1662d17c06 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -116,6 +116,8 @@ void GLES_GPU::CopyDisplayToOutput() if (!g_Config.bBufferedRendering) return; + EndDebugDraw(); + VirtualFramebuffer *vfb = GetDisplayFBO(); fbo_unbind(); @@ -145,6 +147,8 @@ void GLES_GPU::CopyDisplayToOutput() shaderManager.DirtyShader(); shaderManager.DirtyUniform(DIRTY_ALL); gstate_c.textureChanged = true; + + BeginDebugDraw(); } GLES_GPU::VirtualFramebuffer *GLES_GPU::GetDisplayFBO() @@ -221,6 +225,20 @@ void GLES_GPU::SetRenderFrameBuffer() } } +void GLES_GPU::BeginDebugDraw() +{ + if (g_Config.bDrawWireframe) { +#ifndef USING_GLES2 + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif + // glClear(GL_COLOR_BUFFER_BIT); + } +} +void GLES_GPU::EndDebugDraw() { +#ifndef USING_GLES2 + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif +} // Render queue @@ -698,6 +716,20 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) } break; + case GE_CMD_TEXMAPMODE: + DEBUG_LOG(G3D,"Tex map mode: %06x", data); + break; + + case GE_CMD_TEXSHADELS: + DEBUG_LOG(G3D,"Tex shade light sources: %06x", data); + break; + + case GE_CMD_CLUTFORMAT: + { + DEBUG_LOG(G3D,"DL Clut format: %06x", data); + } + break; + case GE_CMD_TRANSFERSRC: { // Nothing to do, the next one prints diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index a105ca7818..8fe6ae971a 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -51,11 +51,17 @@ public: private: // TransformPipeline.cpp void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead = 0); + void ApplyDrawState(); + void Flush(); void UpdateViewportAndProjection(); void DrawBezier(int ucount, int vcount); void DoBlockTransfer(); bool ProcessDLQueue(); + // Applies states for debugging if enabled. + void BeginDebugDraw(); + void EndDebugDraw(); + FramebufferManager framebufferManager; ShaderManager *shaderManager_; diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index e42e96e2b6..0b4003c3a2 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -85,7 +85,7 @@ char *GenerateFragmentShader() WRITE(p, "uniform vec3 u_fogcolor;\n"); WRITE(p, "uniform vec2 u_fogcoef;\n"); } - WRITE(p, "uniform vec4 u_texenv;\n"); + WRITE(p, "uniform vec3 u_texenv;\n"); WRITE(p, "varying vec4 v_color0;\n"); if (lmode) WRITE(p, "varying vec4 v_color1;\n"); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 857968560b..78303948c8 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -97,9 +97,20 @@ LinkedShader::~LinkedShader() { glDeleteProgram(program); } +// Utility +static void SetColorUniform3(int uniform, u32 color) +{ + const float col[3] = { ((color & 0xFF0000) >> 16) / 255.0f, ((color & 0xFF00) >> 8) / 255.0f, ((color & 0xFF)) / 255.0f}; + glUniform3fv(uniform, 1, col); +} + void LinkedShader::use() { glUseProgram(program); glUniform1i(u_tex, 0); + + if (!dirtyUniforms) + return; + // Update any dirty uniforms before we draw if (u_proj != -1 && (dirtyUniforms & DIRTY_PROJMATRIX)) { glUniformMatrix4fv(u_proj, 1, GL_FALSE, gstate.projMatrix); @@ -122,14 +133,13 @@ void LinkedShader::use() { glUniformMatrix4fv(u_proj_through, 1, GL_FALSE, proj_through.getReadPtr()); } if (u_texenv != -1 && (dirtyUniforms & DIRTY_TEXENV)) { - glUniform4f(u_texenv, 1.0, 1.0, 1.0, 1.0); // TODO + SetColorUniform3(u_texenv, gstate.texenvcolor); } if (u_alpharef != -1 && (dirtyUniforms & DIRTY_ALPHAREF)) { glUniform4f(u_alpharef, ((float)((gstate.alphatest >> 8) & 0xFF)) / 255.0f, 0.0f, 0.0f, 0.0f); } if (u_fogcolor != -1 && (dirtyUniforms & DIRTY_FOGCOLOR)) { - const float fogc[3] = { ((gstate.fogcolor & 0xFF0000) >> 16) / 255.0f, ((gstate.fogcolor & 0xFF00) >> 8) / 255.0f, ((gstate.fogcolor & 0xFF)) / 255.0f}; - glUniform3fv(u_fogcolor, 1, fogc); + SetColorUniform3(u_fogcolor, gstate.fogcolor); } if (u_fogcoef != -1 && (dirtyUniforms & DIRTY_FOGCOEF)) { const float fogcoef[2] = { getFloat24(gstate.fog1), getFloat24(gstate.fog2) }; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 58ce633357..b5569bfea4 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -226,6 +226,16 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte *bytesRead = vertexCount * dec.VertexSize(); bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; + + /* + DEBUG_LOG(G3D, "View matrix:"); + const float *m = &gstate.viewMatrix[0]; + DEBUG_LOG(G3D, "%f %f %f", m[0], m[1], m[2]); + DEBUG_LOG(G3D, "%f %f %f", m[3], m[4], m[5]); + DEBUG_LOG(G3D, "%f %f %f", m[6], m[7], m[8]); + DEBUG_LOG(G3D, "%f %f %f", m[9], m[10], m[11]); + */ + // Then, transform and draw in one big swoop (urgh!) // need to move this to the shader. @@ -423,7 +433,6 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte memcpy(&transformed[index].color1, c1, 4 * sizeof(float)); } - // Step 2: Expand using the index buffer, and expand rectangles. const TransformedVertex *drawBuffer = transformed; @@ -526,6 +535,35 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } } + ApplyDrawState(); + UpdateViewportAndProjection(); + LinkedShader *program = shaderManager_->ApplyShader(prim); + + // TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, these spam the gDebugger log. + glEnableVertexAttribArray(program->a_position); + if (useTexCoord && program->a_texcoord != -1) glEnableVertexAttribArray(program->a_texcoord); + if (program->a_color0 != -1) glEnableVertexAttribArray(program->a_color0); + if (program->a_color1 != -1) glEnableVertexAttribArray(program->a_color1); + const int vertexSize = sizeof(transformed[0]); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer); + if (useTexCoord && program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4); + if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4); + if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4); + // NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans); + if (drawIndexed) { + glDrawElements(glprim[prim], numTrans, glIndexType, (GLvoid *)inds); + } else { + glDrawArrays(glprim[prim], 0, numTrans); + } + glDisableVertexAttribArray(program->a_position); + if (useTexCoord && program->a_texcoord != -1) glDisableVertexAttribArray(program->a_texcoord); + if (program->a_color0 != -1) glDisableVertexAttribArray(program->a_color0); + if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); +} + +void GLES_GPU::ApplyDrawState() +{ + // TODO: All this setup is soon so expensive that we'll need dirty flags, or simply do it in the command writes where we detect dirty by xoring. Silly to do all this work on every drawcall. // TODO: The top bit of the alpha channel should be written to the stencil bit somehow. This appears to require very expensive multipass rendering :( Alternatively, one could do a @@ -620,30 +658,6 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte float depthRangeMin = gstate_c.zOff - gstate_c.zScale; float depthRangeMax = gstate_c.zOff + gstate_c.zScale; glstate.depthRange.set(depthRangeMin, depthRangeMax); - - UpdateViewportAndProjection(); - LinkedShader *program = shaderManager_->ApplyShader(prim); - - // TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, these spam the gDebugger log. - glEnableVertexAttribArray(program->a_position); - if (useTexCoord && program->a_texcoord != -1) glEnableVertexAttribArray(program->a_texcoord); - if (program->a_color0 != -1) glEnableVertexAttribArray(program->a_color0); - if (program->a_color1 != -1) glEnableVertexAttribArray(program->a_color1); - const int vertexSize = sizeof(transformed[0]); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer); - if (useTexCoord && program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4); - if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4); - if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4); - // NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans); - if (drawIndexed) { - glDrawElements(glprim[prim], numTrans, glIndexType, (GLvoid *)inds); - } else { - glDrawArrays(glprim[prim], 0, numTrans); - } - glDisableVertexAttribArray(program->a_position); - if (useTexCoord && program->a_texcoord != -1) glDisableVertexAttribArray(program->a_texcoord); - if (program->a_color0 != -1) glDisableVertexAttribArray(program->a_color0); - if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } void GLES_GPU::UpdateViewportAndProjection() diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 91f12d24c1..51664cc983 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -483,6 +483,10 @@ namespace MainWindow _ViewFullScreen(hWnd); } break; + case ID_OPTIONS_WIREFRAME: + g_Config.bDrawWireframe = !g_Config.bDrawWireframe; + UpdateMenus(); + break; case ID_OPTIONS_DISPLAYRAWFRAMEBUFFER: g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer; @@ -627,6 +631,7 @@ namespace MainWindow CHECKITEM(ID_CPU_DYNAREC,g_Config.iCpuCore == CPU_JIT); CHECKITEM(ID_OPTIONS_BUFFEREDRENDERING, g_Config.bBufferedRendering); CHECKITEM(ID_OPTIONS_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats); + CHECKITEM(ID_OPTIONS_WIREFRAME, g_Config.bDrawWireframe); BOOL enable = !Core_IsStepping(); EnableMenuItem(menu,ID_EMULATION_RUN,enable); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 8ddb89699d..4d12eb0163 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -214,6 +214,7 @@ BEGIN MENUITEM "&Toggle Full Screen\tF12", ID_OPTIONS_FULLSCREEN MENUITEM "&Display Raw Framebuffer", ID_OPTIONS_DISPLAYRAWFRAMEBUFFER MENUITEM "&Buffered Rendering\tF5", ID_OPTIONS_BUFFEREDRENDERING + MENUITEM "&Wireframe (experimental)", ID_OPTIONS_WIREFRAME MENUITEM "&Show Debug Statistics", ID_OPTIONS_SHOWDEBUGSTATISTICS MENUITEM SEPARATOR MENUITEM "Screen &1x\tCtrl+1", ID_OPTIONS_SCREEN1X diff --git a/Windows/resource.h b/Windows/resource.h index 594a397e12..631760dffe 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -243,13 +243,14 @@ #define ID_EMULATION_FASTINTERPRETER 40120 #define ID_CPU_FASTINTERPRETER 40121 #define ID_OPTIONS_SHOWDEBUGSTATISTICS 40122 +#define ID_OPTIONS_WIREFRAME 40123 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 232 -#define _APS_NEXT_COMMAND_VALUE 40123 +#define _APS_NEXT_COMMAND_VALUE 40124 #define _APS_NEXT_CONTROL_VALUE 1162 #define _APS_NEXT_SYMED_VALUE 101 #endif