From fcc77f525fd56f95e3057497026d68f27f77c45e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Oct 2013 20:47:52 -0700 Subject: [PATCH 1/8] Implement some basic vertex previews on prim. 3D doesn't work correctly (sometimes it does...) 2D should be working. --- GPU/Common/GPUDebugInterface.h | 12 ++ GPU/Common/VertexDecoderCommon.cpp | 2 +- GPU/Common/VertexDecoderCommon.h | 2 +- GPU/GLES/GLES_GPU.cpp | 4 + GPU/GLES/GLES_GPU.h | 1 + GPU/GLES/TransformPipeline.cpp | 115 ++++++++++++++++ GPU/GLES/TransformPipeline.h | 3 + Windows/GEDebugger/GEDebugger.cpp | 1 + Windows/GEDebugger/GEDebugger.h | 1 + Windows/GEDebugger/SimpleGLWindow.cpp | 57 +++++--- Windows/GEDebugger/SimpleGLWindow.h | 10 ++ Windows/GEDebugger/VertexPreview.cpp | 184 +++++++++++++++++++++++++- 12 files changed, 364 insertions(+), 28 deletions(-) diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index eeb48a5393..901443f245 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -176,6 +176,14 @@ private: bool flipped_; }; +struct GPUDebugVertex { + float u; + float v; + float x; + float y; + float z; +}; + class GPUDebugInterface { public: virtual bool GetCurrentDisplayList(DisplayList &list) = 0; @@ -198,6 +206,10 @@ public: // Calling from a separate thread (e.g. UI) may fail. virtual void SetCmdValue(u32 op) = 0; + virtual bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { + return false; + } + // Needs to be called from the GPU thread, so on the same thread as a notification is fine. // Calling from a separate thread (e.g. UI) may fail. virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index e4ab616770..23378ec60e 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -42,7 +42,7 @@ int DecFmtSize(u8 fmt) { } } -void GetIndexBounds(void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) { +void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) { // Find index bounds. Could cache this in display lists. // Also, this could be greatly sped up with SSE2/NEON, although rarely a bottleneck. int lowerBound = 0x7FFFFFFF; diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 920a0b2dea..500097dbc2 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -71,7 +71,7 @@ struct TransformedVertex u8 color1[4]; // prelit }; -void GetIndexBounds(void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound); +void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound); enum { STAT_VERTSSUBMITTED = 0, diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 7114027899..358e89a8d5 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -1644,3 +1644,7 @@ bool GLES_GPU::GetCurrentTexture(GPUDebugBuffer &buffer) { return false; #endif } + +bool GLES_GPU::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { + return transformDraw_.GetCurrentSimpleVertices(count, vertices, indices); +} diff --git a/GPU/GLES/GLES_GPU.h b/GPU/GLES/GLES_GPU.h index 7ad6bb6863..f046f31374 100644 --- a/GPU/GLES/GLES_GPU.h +++ b/GPU/GLES/GLES_GPU.h @@ -71,6 +71,7 @@ public: bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); bool GetCurrentTexture(GPUDebugBuffer &buffer); + bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); protected: virtual void FastRunLoop(DisplayList &list); diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index aaa79beaa8..0d5305ceb3 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -79,6 +79,7 @@ #include "GPU/GPUState.h" #include "GPU/ge_constants.h" +#include "GPU/Common/SplineCommon.h" #include "GPU/GLES/StateMapping.h" #include "GPU/GLES/TextureCache.h" #include "GPU/GLES/TransformPipeline.h" @@ -842,3 +843,117 @@ bool TransformDrawEngine::TestBoundingBox(void* control_points, int vertexCount, return true; } + +// TODO: Probably move this to common code (with normalization?) + +static inline Vec3f ClipToScreenTemp(const Vec4f& coords) +{ + Vec3f ret; + // TODO: Check for invalid parameters (x2 < x1, etc) + float vpx1 = getFloat24(gstate.viewportx1); + float vpx2 = getFloat24(gstate.viewportx2); + float vpy1 = getFloat24(gstate.viewporty1); + float vpy2 = getFloat24(gstate.viewporty2); + float vpz1 = getFloat24(gstate.viewportz1); + float vpz2 = getFloat24(gstate.viewportz2); + + float retx = coords.x * vpx1 / coords.w + vpx2; + float rety = coords.y * vpy1 / coords.w + vpy2; + float retz = coords.z * vpz1 / coords.w + vpz2; + + if (gstate.clipEnable & 0x1) { + if (retz < 0.f) retz = 0.f; + if (retz > 65535.f) retz = 65535.f; + } + + // 16 = 0xFFFF / 4095.9375 + return Vec3f(retx * 16, rety * 16, retz); +} + +static Vec3f ScreenToDrawing(const Vec3f& coords) +{ + Vec3f ret; + // TODO: What to do when offset > coord? + ret.x = (((u32)coords.x - gstate.getOffsetX16())/16) & 0x3ff; + ret.y = (((u32)coords.y - gstate.getOffsetY16())/16) & 0x3ff; + ret.z = coords.z; + return ret; +} + +// TODO: This probably is not the best interface. +bool TransformDrawEngine::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { + // This is always for the current vertices. + u16 indexLowerBound = 0; + u16 indexUpperBound = count - 1; + + if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + const u8 *inds = Memory::GetPointer(gstate_c.indexAddr); + const u16 *inds16 = (const u16 *)inds; + + if (inds) { + GetIndexBounds(inds, count, gstate.vertType, &indexLowerBound, &indexUpperBound); + indices.resize(count); + switch (gstate.vertType & GE_VTYPE_IDX_MASK) { + case GE_VTYPE_IDX_16BIT: + for (int i = 0; i < count; ++i) { + indices[i] = inds16[i]; + } + break; + case GE_VTYPE_IDX_8BIT: + for (int i = 0; i < count; ++i) { + indices[i] = inds[i]; + } + break; + default: + return false; + } + } else { + indices.clear(); + } + } else { + indices.clear(); + } + + // TODO: Manage better. + u8 *temp_buffer = new u8[65536 * 24]; + SimpleVertex *simpleVertices = new SimpleVertex[indexUpperBound + 1]; + NormalizeVertices((u8 *)simpleVertices, temp_buffer, Memory::GetPointer(gstate_c.vertexAddr), indexLowerBound, indexUpperBound, gstate.vertType); + + Mat3x3 world_matrix(gstate.worldMatrix); + Mat3x3 view_matrix(gstate.viewMatrix); + Mat4x4 projection_matrix(gstate.projMatrix); + + vertices.resize(indexUpperBound + 1); + for (int i = indexLowerBound; i <= indexUpperBound; ++i) { + const SimpleVertex &vert = simpleVertices[i]; + + if (gstate.isModeThrough()) { + vertices[i].u = vert.uv[0]; + vertices[i].v = vert.uv[1]; + vertices[i].x = vert.pos.x; + vertices[i].y = vert.pos.y; + vertices[i].z = vert.pos.z; + } else { + // TODO: This doesn't work correctly and is inefficient. + + Vec3f modelPos = vert.pos; + Vec3f worldPos = (world_matrix * modelPos) + Vec3(gstate.worldMatrix[9], gstate.worldMatrix[10], gstate.worldMatrix[11]); + Vec3f viewPos = (view_matrix * worldPos) + Vec3(gstate.viewMatrix[9], gstate.viewMatrix[10], gstate.viewMatrix[11]); + Vec4f clipPos = projection_matrix * Vec4f(viewPos.x, viewPos.y, viewPos.z, 1.0f); + Vec3f screenPos = ClipToScreenTemp(clipPos); + Vec3f drawPos = ScreenToDrawing(screenPos); + + vertices[i].u = vert.uv[0]; + vertices[i].v = vert.uv[1]; + vertices[i].x = drawPos.x; + vertices[i].y = drawPos.y; + // TODO: Ought to be the drawPos.z but then things don't draw at all... + vertices[i].z = vert.pos.z; + } + } + + delete [] temp_buffer; + delete [] simpleVertices; + + return true; +} diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 4636cc481f..31be94b66b 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -19,6 +19,7 @@ #include +#include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/IndexGenerator.h" #include "GPU/GLES/VertexDecoder.h" #include "gfx/gl_common.h" @@ -97,6 +98,8 @@ public: void SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType); bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType); + bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); + void SetShaderManager(ShaderManager *shaderManager) { shaderManager_ = shaderManager; } diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 4c974e1cef..b98bb108bc 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -116,6 +116,7 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) } CGEDebugger::~CGEDebugger() { + CleanupPrimPreview(); delete flags; delete lighting; delete textureState; diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index de2ef79cad..6e968609e6 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -64,6 +64,7 @@ private: void SetupPreviews(); void UpdatePreviews(); void UpdatePrimPreview(u32 op); + void CleanupPrimPreview(); void UpdateSize(WORD width, WORD height); void SavePosition(); void SetBreakNext(BreakNextType type); diff --git a/Windows/GEDebugger/SimpleGLWindow.cpp b/Windows/GEDebugger/SimpleGLWindow.cpp index 0e8c81fc0f..03e780dab9 100644 --- a/Windows/GEDebugger/SimpleGLWindow.cpp +++ b/Windows/GEDebugger/SimpleGLWindow.cpp @@ -261,6 +261,33 @@ void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) { Redraw(); } +void SimpleGLWindow::GetContentSize(float &x, float &y, float &fw, float &fh) { + fw = (float)tw_; + fh = (float)th_; + x = 0.0f; + y = 0.0f; + + if (flags_ & (RESIZE_SHRINK_FIT | RESIZE_CENTER) && !zoom_) { + float wscale = fw / w_, hscale = fh / h_; + + // Too wide, and width is the biggest problem, so scale based on that. + if (wscale > 1.0f && wscale > hscale) { + fw = (float)w_; + fh /= wscale; + } else if (hscale > 1.0f) { + fw /= hscale; + fh = (float)h_; + } + } + if (flags_ & RESIZE_CENTER) { + x = ((float)w_ - fw) / 2; + y = ((float)h_ - fh) / 2; + } + + x += offsetX_; + y += offsetY_; +} + void SimpleGLWindow::Redraw(bool andSwap) { DrawChecker(); @@ -284,27 +311,9 @@ void SimpleGLWindow::Redraw(bool andSwap) { glBindTexture(GL_TEXTURE_2D, tex_); glsl_bind(drawProgram_); - float fw = (float)tw_, fh = (float)th_; - float x = 0.0f, y = 0.0f; - if (flags_ & (RESIZE_SHRINK_FIT | RESIZE_CENTER) && !zoom_) { - float wscale = fw / w_, hscale = fh / h_; - - // Too wide, and width is the biggest problem, so scale based on that. - if (wscale > 1.0f && wscale > hscale) { - fw = (float)w_; - fh /= wscale; - } else if (hscale > 1.0f) { - fw /= hscale; - fh = (float)h_; - } - } - if (flags_ & RESIZE_CENTER) { - x = ((float)w_ - fw) / 2; - y = ((float)h_ - fh) / 2; - } - - x += offsetX_; - y += offsetY_; + float fw, fh; + float x, y; + GetContentSize(x, y, fw, fh); const float pos[12] = {x,y,0, x+fw,y,0, x+fw,y+fh,0, x,y+fh,0}; static const float texCoords[8] = {0,0, 1,0, 1,1, 0,1}; @@ -332,9 +341,15 @@ void SimpleGLWindow::Clear() { void SimpleGLWindow::Begin() { Redraw(false); + + glDisableVertexAttribArray(drawProgram_->a_position); + glDisableVertexAttribArray(drawProgram_->a_texcoord0); } void SimpleGLWindow::End() { + glEnableVertexAttribArray(drawProgram_->a_position); + glEnableVertexAttribArray(drawProgram_->a_texcoord0); + Swap(); } diff --git a/Windows/GEDebugger/SimpleGLWindow.h b/Windows/GEDebugger/SimpleGLWindow.h index 0feec1c3fd..c69a0ab997 100644 --- a/Windows/GEDebugger/SimpleGLWindow.h +++ b/Windows/GEDebugger/SimpleGLWindow.h @@ -69,6 +69,16 @@ struct SimpleGLWindow { SwapBuffers(hDC_); } + int Width() { + return w_; + } + + int Height() { + return h_; + } + + void GetContentSize(float &x, float &y, float &fw, float &fh); + static void RegisterClass(); protected: void SetupGL(); diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index accfe56f40..edf6056b0e 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -15,17 +15,133 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "math/lin/matrix4x4.h" +#include "gfx_es2/glsl_program.h" #include "Windows/GEDebugger/GEDebugger.h" #include "Windows/GEDebugger/SimpleGLWindow.h" #include "GPU/GPUInterface.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/GPUState.h" -// TODO: Possibly a shader here to do the transforms? +static const char preview_fs[] = + "#ifdef GL_ES\n" + "precision mediump float;\n" + "#endif\n" + "void main() {\n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.6);\n" + "}\n"; + +static const char preview_vs[] = +#ifndef USING_GLES2 + "#version 120\n" +#endif + "attribute vec4 a_position;\n" + "uniform mat4 u_viewproj;\n" + "void main() {\n" + " gl_Position = u_viewproj * a_position;\n" + "}\n"; + +static GLSLProgram *previewProgram = NULL; +static GLSLProgram *texPreviewProgram = NULL; + +static const GLuint glprim[8] = { + GL_POINTS, + GL_LINES, + GL_LINE_STRIP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN, + // This is for RECTANGLES (see ExpandRectangles().) + GL_TRIANGLES, +}; + +static void BindPreviewProgram(GLSLProgram *&prog) { + if (prog == NULL) { + prog = glsl_create_source(preview_vs, preview_fs); + } + + glsl_bind(prog); +} + +static void SwapUVs(GPUDebugVertex &a, GPUDebugVertex &b) { + float tempu = a.u; + float tempv = a.v; + a.u = b.u; + a.v = b.v; + b.u = tempu; + b.v = tempv; +} + +static void RotateUVThrough(GPUDebugVertex v[4]) { + float x1 = v[2].x; + float x2 = v[0].x; + float y1 = v[2].y; + float y2 = v[0].y; + + if ((x1 < x2 && y1 > y2) || (x1 > x2 && y1 < y2)) + SwapUVs(v[1], v[3]); +} + +static void ExpandRectangles(std::vector &vertices, std::vector &indices, int &count, bool throughMode) { + static std::vector newVerts; + static std::vector newInds; + + if (indices.empty()) { + // Ugh, let's just go the easy way. + indices.resize(count); + for (int i = 0; i < count; ++i) { + indices[i] = i; + } + } + + newVerts.resize(indices.size() * 2); + newInds.resize(indices.size() * 3); + + u16 v = 0; + GPUDebugVertex *vert = &newVerts[0]; + u16 *ind = &newInds[0]; + for (size_t i = 0, end = indices.size(); i < end; i += 2) { + const auto &orig_tl = vertices[indices[i]]; + const auto &orig_br = vertices[indices[i + 1]]; + + vert[0] = orig_br; + + // Top right. + vert[1] = orig_br; + vert[1].y = orig_tl.y; + vert[1].v = orig_tl.v; + + vert[2] = orig_tl; + + // Bottom left. + vert[3] = orig_br; + vert[3].x = orig_tl.x; + vert[3].u = orig_tl.u; + + // That's the four corners. Now process UV rotation. + if (throughMode) + RotateUVThrough(vert); + + // Build the two 3 point triangles from our 4 coordinates. + *ind++ = v + 0; + *ind++ = v + 1; + *ind++ = v + 2; + *ind++ = v + 3; + *ind++ = v + 0; + *ind++ = v + 2; + + vert += 4; + v += 4; + } + + std::swap(vertices, newVerts); + std::swap(indices, newInds); + count *= 3; +} void CGEDebugger::UpdatePrimPreview(u32 op) { const u32 prim_type = (op >> 16) & 0xFF; - const u32 count = op & 0xFFFF; + int count = op & 0xFFFF; if (prim_type >= 7) { ERROR_LOG(COMMON, "Unsupported prim type: %x", op); return; @@ -39,12 +155,70 @@ void CGEDebugger::UpdatePrimPreview(u32 op) { } const GEPrimitiveType prim = static_cast(prim_type); + static std::vector vertices; + static std::vector indices; + + if (!gpuDebug->GetCurrentSimpleVertices(count, vertices, indices)) { + ERROR_LOG(COMMON, "Vertex preview not yet supported"); + return; + } + + if (prim == GE_PRIM_RECTANGLES) { + ExpandRectangles(vertices, indices, count, gpuDebug->GetGState().isModeThrough()); + } + + float fw, fh; + float x, y; frameWindow->Begin(); - // TODO: Get the coords, render on top of the texture and framebuffer previews. - // TODO: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);? + frameWindow->GetContentSize(x, y, fw, fh); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + glBindTexture(GL_TEXTURE_2D, 0); + glViewport(x, -y, fw, fh); + glScissor(x, y, fw, fh); + BindPreviewProgram(previewProgram); + + Matrix4x4 ortho; + ortho.setOrtho(0, fw, fh, 0, -1, 1); + glUniformMatrix4fv(previewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr()); + glEnableVertexAttribArray(previewProgram->a_position); + glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data() + 2); + if (indices.empty()) { + glDrawArrays(glprim[prim], 0, count); + } else { + glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, indices.data()); + } + frameWindow->End(); texWindow->Begin(); + texWindow->GetContentSize(x, y, fw, fh); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + glBindTexture(GL_TEXTURE_2D, 0); + glViewport(x, y, fw, fh); + glScissor(x, y, fw, fh); + BindPreviewProgram(texPreviewProgram); + + ortho.setOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0); + glUniformMatrix4fv(texPreviewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr()); + glEnableVertexAttribArray(texPreviewProgram->a_position); + glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data()); + if (indices.empty()) { + glDrawArrays(glprim[prim], 0, count); + } else { + glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, indices.data()); + } + texWindow->End(); -} \ No newline at end of file +} + +void CGEDebugger::CleanupPrimPreview() { + glsl_destroy(previewProgram); + glsl_destroy(texPreviewProgram); +} From 5c08ab6bca322341d4eaa89dc130d34befad598f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Nov 2013 13:23:52 -0800 Subject: [PATCH 2/8] Clean up no-inds rectange preview. --- Windows/GEDebugger/VertexPreview.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index edf6056b0e..c76da41ad7 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -86,23 +86,23 @@ static void ExpandRectangles(std::vector &vertices, std::vector< static std::vector newVerts; static std::vector newInds; + bool useInds = true; + size_t numInds = indices.size(); if (indices.empty()) { - // Ugh, let's just go the easy way. - indices.resize(count); - for (int i = 0; i < count; ++i) { - indices[i] = i; - } + useInds = false; + numInds = count; } - newVerts.resize(indices.size() * 2); - newInds.resize(indices.size() * 3); + // Will need 4 coords and 6 points per rectangle (currently 2 each.) + newVerts.resize(numInds * 2); + newInds.resize(numInds * 3); u16 v = 0; GPUDebugVertex *vert = &newVerts[0]; u16 *ind = &newInds[0]; - for (size_t i = 0, end = indices.size(); i < end; i += 2) { - const auto &orig_tl = vertices[indices[i]]; - const auto &orig_br = vertices[indices[i + 1]]; + for (size_t i = 0, end = numInds; i < end; i += 2) { + const auto &orig_tl = useInds ? vertices[indices[i]] : vertices[i]; + const auto &orig_br = useInds ? vertices[indices[i + 1]] : vertices[i + 1]; vert[0] = orig_br; From b541c81ba30fda4ef5de885da2b5ea3c3000ab1d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Nov 2013 13:27:33 -0800 Subject: [PATCH 3/8] Clean up Mat3x3 etc. constness. --- GPU/GLES/TransformPipeline.cpp | 6 +++--- GPU/Math3D.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 0d5305ceb3..cc11a64530 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -919,9 +919,9 @@ bool TransformDrawEngine::GetCurrentSimpleVertices(int count, std::vector world_matrix(gstate.worldMatrix); - Mat3x3 view_matrix(gstate.viewMatrix); - Mat4x4 projection_matrix(gstate.projMatrix); + const Mat3x3 world_matrix(gstate.worldMatrix); + const Mat3x3 view_matrix(gstate.viewMatrix); + const Mat4x4 projection_matrix(gstate.projMatrix); vertices.resize(indexUpperBound + 1); for (int i = indexLowerBound; i <= indexUpperBound; ++i) { diff --git a/GPU/Math3D.h b/GPU/Math3D.h index 3eca3420bc..d29d0f0c9a 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -530,7 +530,7 @@ public: } template - Vec3 operator * (const Vec3& vec) + Vec3 operator * (const Vec3& vec) const { Vec3 ret; ret.x = values[0]*vec.x + values[3]*vec.y + values[6]*vec.z; @@ -539,7 +539,7 @@ public: return ret; } - Mat3x3 Inverse() + Mat3x3 Inverse() const { float a = values[0]; float b = values[1]; @@ -555,7 +555,7 @@ public: b*f-c*e, c*d-a*f, a*e-b*d) / Det(); } - BaseType Det() + BaseType Det() const { return values[0]*values[4]*values[8] + values[3]*values[7]*values[2] + values[6]*values[1]*values[5] - values[2]*values[4]*values[6] - @@ -588,7 +588,7 @@ public: } template - Vec4 operator * (const Vec4& vec) + Vec4 operator * (const Vec4& vec) const { Vec4 ret; ret.x = values[0]*vec.x + values[4]*vec.y + values[8]*vec.z + values[12]*vec.w; From a3bd2f1365f169513c385fbf828f8f2193cc1e3c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Nov 2013 14:10:57 -0800 Subject: [PATCH 4/8] Fix Vec3ByMatrix44() and use it for matrix math. --- GPU/GLES/TransformPipeline.cpp | 14 ++++++-------- GPU/Math3D.h | 4 ++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index cc11a64530..17a977936f 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -919,10 +919,6 @@ bool TransformDrawEngine::GetCurrentSimpleVertices(int count, std::vector world_matrix(gstate.worldMatrix); - const Mat3x3 view_matrix(gstate.viewMatrix); - const Mat4x4 projection_matrix(gstate.projMatrix); - vertices.resize(indexUpperBound + 1); for (int i = indexLowerBound; i <= indexUpperBound; ++i) { const SimpleVertex &vert = simpleVertices[i]; @@ -936,10 +932,12 @@ bool TransformDrawEngine::GetCurrentSimpleVertices(int count, std::vector(gstate.worldMatrix[9], gstate.worldMatrix[10], gstate.worldMatrix[11]); - Vec3f viewPos = (view_matrix * worldPos) + Vec3(gstate.viewMatrix[9], gstate.viewMatrix[10], gstate.viewMatrix[11]); - Vec4f clipPos = projection_matrix * Vec4f(viewPos.x, viewPos.y, viewPos.z, 1.0f); + float worldPos[3]; + Vec3ByMatrix43(worldPos, vert.pos.AsArray(), gstate.worldMatrix); + float viewPos[3]; + Vec3ByMatrix43(viewPos, worldPos, gstate.viewMatrix); + float clipPos[4]; + Vec3ByMatrix44(clipPos, viewPos, gstate.projMatrix); Vec3f screenPos = ClipToScreenTemp(clipPos); Vec3f drawPos = ScreenToDrawing(screenPos); diff --git a/GPU/Math3D.h b/GPU/Math3D.h index d29d0f0c9a..217076bfa8 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -40,6 +40,7 @@ public: }; T* AsArray() { return &x; } + const T* AsArray() const { return &x; } Vec2() {} Vec2(const T a[2]) : x(a[0]), y(a[1]) {} @@ -173,6 +174,7 @@ public: }; T* AsArray() { return &x; } + const T* AsArray() const { return &x; } Vec3() {} Vec3(const T a[3]) : x(a[0]), y(a[1]), z(a[2]) {} @@ -339,6 +341,7 @@ public: }; T* AsArray() { return &x; } + const T* AsArray() const { return &x; } Vec4() {} Vec4(const T a[4]) : x(a[0]), y(a[1]), z(a[2]), w(a[3]) {} @@ -615,6 +618,7 @@ inline void Vec3ByMatrix44(float vecOut[4], const float v[3], const float m[16]) vecOut[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + m[12]; vecOut[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + m[13]; vecOut[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + m[14]; + vecOut[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + m[15]; } inline void Vec4ByMatrix44(float vecOut[4], const float v[4], const float m[16]) From 018d95180a6bf098619690a6644dc74ed536c55e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Nov 2013 14:31:21 -0800 Subject: [PATCH 5/8] Fix 3d vertex preview. --- GPU/GLES/TransformPipeline.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 17a977936f..fec208f2e7 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -848,7 +848,6 @@ bool TransformDrawEngine::TestBoundingBox(void* control_points, int vertexCount, static inline Vec3f ClipToScreenTemp(const Vec4f& coords) { - Vec3f ret; // TODO: Check for invalid parameters (x2 < x1, etc) float vpx1 = getFloat24(gstate.viewportx1); float vpx2 = getFloat24(gstate.viewportx2); @@ -873,9 +872,12 @@ static inline Vec3f ClipToScreenTemp(const Vec4f& coords) static Vec3f ScreenToDrawing(const Vec3f& coords) { Vec3f ret; - // TODO: What to do when offset > coord? - ret.x = (((u32)coords.x - gstate.getOffsetX16())/16) & 0x3ff; - ret.y = (((u32)coords.y - gstate.getOffsetY16())/16) & 0x3ff; + ret.x = coords.x - gstate.getOffsetX16(); + ret.y = coords.y - gstate.getOffsetY16(); + + // Convert from 16 point to float. + ret.x *= 1.0 / 16.0; + ret.y *= 1.0 / 16.0; ret.z = coords.z; return ret; } @@ -945,8 +947,7 @@ bool TransformDrawEngine::GetCurrentSimpleVertices(int count, std::vector Date: Sun, 17 Nov 2013 14:36:30 -0800 Subject: [PATCH 6/8] Avoid some operator overloads. Causing ambiguity. --- GPU/Math3D.h | 18 ------------------ GPU/Software/Rasterizer.cpp | 2 +- GPU/Software/TransformUnit.cpp | 4 ++-- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/GPU/Math3D.h b/GPU/Math3D.h index 217076bfa8..49311a7433 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -156,12 +156,6 @@ public: Vec2 ts() const { return Vec2(y, x); } }; -template -Vec2 operator * (const V& f, const Vec2& vec) -{ - return Vec2(f*vec.x,f*vec.y); -} - typedef Vec2 Vec2f; template @@ -323,12 +317,6 @@ public: #undef _DEFINE_SWIZZLER2 }; -template -Vec3 operator * (const V& f, const Vec3& vec) -{ - return Vec3(f*vec.x,f*vec.y,f*vec.z); -} - typedef Vec3 Vec3f; template @@ -497,12 +485,6 @@ public: #undef _DEFINE_SWIZZLER3 }; -template -Vec4 operator * (const V& f, const Vec4& vec) -{ - return Vec4(f*vec.x,f*vec.y,f*vec.z,f*vec.w); -} - typedef Vec4 Vec4f; diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index 314e983234..e51d7d2e16 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -572,7 +572,7 @@ static inline Vec4 GetTextureFunctionOutput(const Vec3& prim_color_rgb { int t = (rgba) ? texcolor.a() : 255; int invt = (rgba) ? 255 - t : 0; - out_rgb = (invt * prim_color_rgb + t * texcolor.rgb()) / 255; + out_rgb = (prim_color_rgb * invt + texcolor.rgb() * t) / 255; out_a = prim_color_a; break; } diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index b84071fad8..06b0dcd80d 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -128,9 +128,9 @@ static VertexData ReadVertex(VertexReader& vreader) for (int i = 0; i < vertTypeGetNumBoneWeights(gstate.vertType); ++i) { Mat3x3 bone(&gstate.boneMatrix[12*i]); - tmppos += W[i] * (bone * ModelCoords(pos[0], pos[1], pos[2]) + Vec3(gstate.boneMatrix[12*i+9], gstate.boneMatrix[12*i+10], gstate.boneMatrix[12*i+11])); + tmppos += (bone * ModelCoords(pos[0], pos[1], pos[2]) * W[i] + Vec3(gstate.boneMatrix[12*i+9], gstate.boneMatrix[12*i+10], gstate.boneMatrix[12*i+11])); if (vreader.hasNormal()) - tmpnrm += W[i] * (bone * vertex.normal); + tmpnrm += (bone * vertex.normal) * W[i]; } pos[0] = tmppos.x; From ed16e42ca89eafc0ad5908cf13779e5d2dfacff8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Nov 2013 14:49:51 -0800 Subject: [PATCH 7/8] Cleanup, don't even need z here. --- GPU/GLES/TransformPipeline.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index fec208f2e7..1fd06ac6cd 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -846,7 +846,7 @@ bool TransformDrawEngine::TestBoundingBox(void* control_points, int vertexCount, // TODO: Probably move this to common code (with normalization?) -static inline Vec3f ClipToScreenTemp(const Vec4f& coords) +static inline Vec3f ClipToScreen(const Vec4f& coords) { // TODO: Check for invalid parameters (x2 < x1, etc) float vpx1 = getFloat24(gstate.viewportx1); @@ -860,11 +860,6 @@ static inline Vec3f ClipToScreenTemp(const Vec4f& coords) float rety = coords.y * vpy1 / coords.w + vpy2; float retz = coords.z * vpz1 / coords.w + vpz2; - if (gstate.clipEnable & 0x1) { - if (retz < 0.f) retz = 0.f; - if (retz > 65535.f) retz = 65535.f; - } - // 16 = 0xFFFF / 4095.9375 return Vec3f(retx * 16, rety * 16, retz); } @@ -940,7 +935,7 @@ bool TransformDrawEngine::GetCurrentSimpleVertices(int count, std::vector Date: Sun, 17 Nov 2013 15:05:11 -0800 Subject: [PATCH 8/8] Fix vertex preview when framebuf is an odd size. The previous stuff was wrong, just happened to work. --- Windows/GEDebugger/SimpleGLWindow.h | 8 ++++++++ Windows/GEDebugger/VertexPreview.cpp | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Windows/GEDebugger/SimpleGLWindow.h b/Windows/GEDebugger/SimpleGLWindow.h index c69a0ab997..4aae6d0223 100644 --- a/Windows/GEDebugger/SimpleGLWindow.h +++ b/Windows/GEDebugger/SimpleGLWindow.h @@ -77,6 +77,14 @@ struct SimpleGLWindow { return h_; } + int TexWidth() { + return tw_; + } + + int TexHeight() { + return th_; + } + void GetContentSize(float &x, float &y, float &fw, float &fh); static void RegisterClass(); diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index c76da41ad7..e4ec502aed 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -177,12 +177,12 @@ void CGEDebugger::UpdatePrimPreview(u32 op) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); glBindTexture(GL_TEXTURE_2D, 0); - glViewport(x, -y, fw, fh); + glViewport(x, y, fw, fh); glScissor(x, y, fw, fh); BindPreviewProgram(previewProgram); Matrix4x4 ortho; - ortho.setOrtho(0, fw, fh, 0, -1, 1); + ortho.setOrtho(0, frameWindow->TexWidth(), frameWindow->TexHeight(), 0, -1, 1); glUniformMatrix4fv(previewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr()); glEnableVertexAttribArray(previewProgram->a_position); glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data() + 2);