From 25bc3942845ce7461b19969bf23d6b44b0a1ec76 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Dec 2013 12:57:30 -0800 Subject: [PATCH 1/5] Ignore the material update flag w/o vertex color. Instead of using materialambient for all of them. Fixes #3918, and seems to match tests with 3dstudio. --- GPU/Directx9/TransformPipelineDX9.cpp | 9 +++++---- GPU/Directx9/VertexShaderGeneratorDX9.cpp | 8 ++++---- GPU/GLES/SoftwareTransform.cpp | 9 +++++---- GPU/GLES/VertexShaderGenerator.cpp | 8 ++++---- GPU/Software/Lighting.cpp | 10 +++++----- GPU/Software/Lighting.h | 2 +- GPU/Software/TransformUnit.cpp | 2 +- 7 files changed, 25 insertions(+), 23 deletions(-) diff --git a/GPU/Directx9/TransformPipelineDX9.cpp b/GPU/Directx9/TransformPipelineDX9.cpp index af9ddaf3f4..d483e43bf4 100644 --- a/GPU/Directx9/TransformPipelineDX9.cpp +++ b/GPU/Directx9/TransformPipelineDX9.cpp @@ -137,7 +137,7 @@ using namespace DX9; // that's common between the many vertices of a draw call. class Lighter { public: - Lighter(); + Lighter(int vertType); void Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f normal); private: @@ -152,7 +152,7 @@ private: int materialUpdate_; }; -Lighter::Lighter() { +Lighter::Lighter(int vertType) { doShadeMapping_ = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP; materialEmissive.GetFromRGB(gstate.materialemissive); materialEmissive.a = 0.0f; @@ -166,7 +166,8 @@ Lighter::Lighter() { materialSpecular.a = 1.0f; specCoef_ = getFloat24(gstate.materialspecularcoef); // viewer_ = Vec3f(-gstate.viewMatrix[9], -gstate.viewMatrix[10], -gstate.viewMatrix[11]); - materialUpdate_ = gstate.materialupdate & 7; + bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0; + materialUpdate_ = hasColor ? gstate.materialupdate & 7 : 0; } void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f norm) @@ -560,7 +561,7 @@ void TransformDrawEngineDX9::SoftwareTransformAndDraw( float widthFactor = (float) w / (float) gstate_c.curTextureWidth; float heightFactor = (float) h / (float) gstate_c.curTextureHeight; - Lighter lighter; + Lighter lighter(vertType); float fog_end = getFloat24(gstate.fog1); float fog_slope = getFloat24(gstate.fog2); diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index 8cb2f71c91..32acf24c7a 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.cpp +++ b/GPU/Directx9/VertexShaderGeneratorDX9.cpp @@ -210,7 +210,7 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) { } if (gstate.isLightingEnabled()) { WRITE(p, "float4 u_ambient;\n"); - if ((gstate.materialupdate & 2) == 0) + if ((gstate.materialupdate & 2) == 0 || !hasColor) WRITE(p, "float3 u_matdiffuse;\n"); // if ((gstate.materialupdate & 4) == 0) WRITE(p, "float4 u_matspecular;\n"); // Specular coef is contained in alpha @@ -371,9 +371,9 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) { // TODO: Declare variables for dots for shade mapping if needed. - const char *ambientStr = (gstate.materialupdate & 1) ? (hasColor ? "In.C1" : "u_matambientalpha") : "u_matambientalpha"; - const char *diffuseStr = (gstate.materialupdate & 2) ? (hasColor ? "In.C1.rgb" : "u_matambientalpha.rgb") : "u_matdiffuse"; - const char *specularStr = (gstate.materialupdate & 4) ? (hasColor ? "In.C1.rgb" : "u_matambientalpha.rgb") : "u_matspecular.rgb"; + const char *ambientStr = (gstate.materialupdate & 1) && hasColor ? "In.C1" : "u_matambientalpha"; + const char *diffuseStr = (gstate.materialupdate & 2) && hasColor ? "In.C1.rgb" : "u_matdiffuse"; + const char *specularStr = (gstate.materialupdate & 4) && hasColor ? "In.C1.rgb" : "u_matspecular.rgb"; bool diffuseIsZero = true; bool specularIsZero = true; diff --git a/GPU/GLES/SoftwareTransform.cpp b/GPU/GLES/SoftwareTransform.cpp index 5c7e167326..d32c6be5e4 100644 --- a/GPU/GLES/SoftwareTransform.cpp +++ b/GPU/GLES/SoftwareTransform.cpp @@ -51,7 +51,7 @@ inline float clamp(float in, float min, float max) { // that's common between the many vertices of a draw call. class Lighter { public: - Lighter(); + Lighter(int vertType); void Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f normal); private: @@ -66,7 +66,7 @@ private: int materialUpdate_; }; -Lighter::Lighter() { +Lighter::Lighter(int vertType) { doShadeMapping_ = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP; materialEmissive.GetFromRGB(gstate.materialemissive); materialEmissive.a = 0.0f; @@ -80,7 +80,8 @@ Lighter::Lighter() { materialSpecular.a = 1.0f; specCoef_ = getFloat24(gstate.materialspecularcoef); // viewer_ = Vec3f(-gstate.viewMatrix[9], -gstate.viewMatrix[10], -gstate.viewMatrix[11]); - materialUpdate_ = gstate.materialupdate & 7; + bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0; + materialUpdate_ = hasColor ? gstate.materialupdate & 7 : 0; } void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f norm) @@ -307,7 +308,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( float widthFactor = (float) w / (float) gstate_c.curTextureWidth; float heightFactor = (float) h / (float) gstate_c.curTextureHeight; - Lighter lighter; + Lighter lighter(vertType); float fog_end = getFloat24(gstate.fog1); float fog_slope = getFloat24(gstate.fog2); diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index df2dd02b1b..af8d47210e 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -297,7 +297,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf } if (gstate.isLightingEnabled()) { WRITE(p, "uniform lowp vec4 u_ambient;\n"); - if ((gstate.materialupdate & 2) == 0) + if ((gstate.materialupdate & 2) == 0 || !hasColor) WRITE(p, "uniform lowp vec3 u_matdiffuse;\n"); // if ((gstate.materialupdate & 4) == 0) WRITE(p, "uniform lowp vec4 u_matspecular;\n"); // Specular coef is contained in alpha @@ -451,9 +451,9 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf // TODO: Declare variables for dots for shade mapping if needed. - const char *ambientStr = (gstate.materialupdate & 1) ? (hasColor ? "color0" : "u_matambientalpha") : "u_matambientalpha"; - const char *diffuseStr = (gstate.materialupdate & 2) ? (hasColor ? "color0.rgb" : "u_matambientalpha.rgb") : "u_matdiffuse"; - const char *specularStr = (gstate.materialupdate & 4) ? (hasColor ? "color0.rgb" : "u_matambientalpha.rgb") : "u_matspecular.rgb"; + const char *ambientStr = (gstate.materialupdate & 1) && hasColor ? "color0" : "u_matambientalpha"; + const char *diffuseStr = (gstate.materialupdate & 2) && hasColor ? "color0.rgb" : "u_matdiffuse"; + const char *specularStr = (gstate.materialupdate & 4) && hasColor ? "color0.rgb" : "u_matspecular.rgb"; bool diffuseIsZero = true; bool specularIsZero = true; diff --git a/GPU/Software/Lighting.cpp b/GPU/Software/Lighting.cpp index 4977873a67..d2a127373c 100644 --- a/GPU/Software/Lighting.cpp +++ b/GPU/Software/Lighting.cpp @@ -21,11 +21,11 @@ namespace Lighting { -void Process(VertexData& vertex) +void Process(VertexData& vertex, bool hasColor) { Vec3 mec = Vec3(gstate.getMaterialEmissiveR(), gstate.getMaterialEmissiveG(), gstate.getMaterialEmissiveB()); - Vec3 mac = (gstate.materialupdate&1) + Vec3 mac = hasColor && (gstate.materialupdate&1) ? vertex.color0.rgb() : Vec3(gstate.getMaterialAmbientR(), gstate.getMaterialAmbientG(), gstate.getMaterialAmbientB()); Vec3 final_color = mec + mac * Vec3(gstate.getAmbientR(), gstate.getAmbientG(), gstate.getAmbientB()) / 255; @@ -92,7 +92,7 @@ void Process(VertexData& vertex) // diffuse lighting Vec3 ldc = Vec3(gstate.getDiffuseColorR(light), gstate.getDiffuseColorG(light), gstate.getDiffuseColorB(light)); - Vec3 mdc = (gstate.materialupdate&2) + Vec3 mdc = hasColor && (gstate.materialupdate&2) ? vertex.color0.rgb() : Vec3(gstate.getMaterialDiffuseR(), gstate.getMaterialDiffuseG(), gstate.getMaterialDiffuseB()); @@ -115,7 +115,7 @@ void Process(VertexData& vertex) Vec3 H = worldE / worldE.Length() + L / L.Length(); Vec3 lsc = Vec3(gstate.getSpecularColorR(light), gstate.getSpecularColorG(light), gstate.getSpecularColorB(light)); - Vec3 msc = (gstate.materialupdate&4) + Vec3 msc = hasColor && (gstate.materialupdate&4) ? vertex.color0.rgb() : Vec3(gstate.getMaterialSpecularR(), gstate.getMaterialSpecularG(), gstate.getMaterialSpecularB()); @@ -144,7 +144,7 @@ void Process(VertexData& vertex) vertex.color1 = Vec3(0, 0, 0); } - int maa = (gstate.materialupdate&1) ? vertex.color0.a() : gstate.getMaterialAmbientA(); + int maa = hasColor && (gstate.materialupdate&1) ? vertex.color0.a() : gstate.getMaterialAmbientA(); vertex.color0.a() = gstate.getAmbientA() * maa / 255; vertex.color0 = vertex.color0.Clamp(0, 255); diff --git a/GPU/Software/Lighting.h b/GPU/Software/Lighting.h index 6d1aea34eb..9e08eacade 100644 --- a/GPU/Software/Lighting.h +++ b/GPU/Software/Lighting.h @@ -21,6 +21,6 @@ namespace Lighting { -void Process(VertexData& vertex); +void Process(VertexData& vertex, bool hasColor); } \ No newline at end of file diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index d5f51b8bb9..8d411af214 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -177,7 +177,7 @@ static VertexData ReadVertex(VertexReader& vreader) vertex.worldnormal /= vertex.worldnormal.Length(); } - Lighting::Process(vertex); + Lighting::Process(vertex, vreader.hasColor0()); } else { vertex.screenpos.x = (u32)pos[0] * 16 + gstate.getOffsetX16(); vertex.screenpos.y = (u32)pos[1] * 16 + gstate.getOffsetY16(); From 9f8695982620150cba370e77a7a3a6461cd583d5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Dec 2013 12:59:26 -0800 Subject: [PATCH 2/5] Fix typesafety (ScreenCoords not DrawingCoords.) --- GPU/Software/Rasterizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index 4fa96379ac..5c46dbb292 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -433,7 +433,7 @@ static inline bool DepthTestPassed(int x, int y, u16 z) } } -static inline bool IsRightSideOrFlatBottomLine(const Vec2& vertex, const Vec2& line1, const Vec2& line2) +static inline bool IsRightSideOrFlatBottomLine(const Vec2& vertex, const Vec2& line1, const Vec2& line2) { if (line1.y == line2.y) { // just check if vertex is above us => bottom line parallel to x-axis From eb0ea71f24c77234e875f36a5fd30188a22684a5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Dec 2013 13:02:04 -0800 Subject: [PATCH 3/5] softgpu: Use region for debugger buffer previews. It's fine if it resizes or etc., but this should generally be the interesting area of vram to show, without any confusing noise on the side/etc. --- GPU/Software/Rasterizer.cpp | 12 +++++++----- GPU/Software/SoftGpu.cpp | 34 ++++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index 5c46dbb292..0aad8f6206 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -1260,14 +1260,16 @@ void DrawLine(const VertexData &v0, const VertexData &v1) bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - buffer.Allocate(gstate.DepthBufStride(), 512, GPU_DBG_FORMAT_8BIT); + int w = gstate.getRegionX2() - gstate.getRegionX1() + 1; + int h = gstate.getRegionY2() - gstate.getRegionY1() + 1; + buffer.Allocate(w, h, GPU_DBG_FORMAT_8BIT); u8 *row = buffer.GetData(); - for (int y = 0; y < 512; ++y) { - for (int x = 0; x < gstate.DepthBufStride(); ++x) { - row[x] = GetPixelStencil(x, y); + for (int y = gstate.getRegionY1(); y <= gstate.getRegionY2(); ++y) { + for (int x = gstate.getRegionX1(); x <= gstate.getRegionX2(); ++x) { + row[x - gstate.getRegionX1()] = GetPixelStencil(x, y); } - row += gstate.DepthBufStride(); + row += w; } return true; } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 32e5461eda..864a9c3042 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -865,17 +865,39 @@ bool SoftGPU::FramebufferDirty() { bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { - // We don't know the height, so just use 512, which should be the max (hopefully?) - // TODO: Could check clipping and such, though...? - buffer = GPUDebugBuffer(fb.data, gstate.FrameBufStride(), 512, gstate.FrameBufFormat()); + int w = gstate.getRegionX2() - gstate.getRegionX1() + 1; + int h = gstate.getRegionY2() - gstate.getRegionY1() + 1; + buffer.Allocate(w, h, gstate.FrameBufFormat()); + + u8 *src = fb.data; + u8 *dst = buffer.GetData(); + for (int y = gstate.getRegionY1(); y <= gstate.getRegionY2(); ++y) { + if (gstate.FrameBufFormat() == GE_FORMAT_8888) { + memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * 4); + dst += w * 4; + src += gstate.FrameBufStride() * 4; + } else { + memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * 2); + dst += w * 2; + src += gstate.FrameBufStride() * 2; + } + } return true; } bool SoftGPU::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - // We don't know the height, so just use 512, which should be the max (hopefully?) - // TODO: Could check clipping and such, though...? - buffer = GPUDebugBuffer(depthbuf.data, gstate.DepthBufStride(), 512, GPU_DBG_FORMAT_16BIT); + int w = gstate.getRegionX2() - gstate.getRegionX1() + 1; + int h = gstate.getRegionY2() - gstate.getRegionY1() + 1; + buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT); + + u8 *src = depthbuf.data; + u8 *dst = buffer.GetData(); + for (int y = gstate.getRegionY1(); y <= gstate.getRegionY2(); ++y) { + memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * 2); + dst += w * 2; + src += gstate.DepthBufStride() * 2; + } return true; } From 473fb866e666139d7016b91544c8b5e66ad53d07 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Dec 2013 13:32:55 -0800 Subject: [PATCH 4/5] softgpu: Implement vertex preview. And move ConvertMatrix4x3To4x4() into a common place since there were differing implementations, which was only confusing. --- GPU/Directx9/ShaderManagerDX9.cpp | 26 ++-------- GPU/GLES/ShaderManager.cpp | 26 ++-------- GPU/GLES/Spline.cpp | 8 ++- GPU/GLES/TransformPipeline.cpp | 19 ------- GPU/GLES/TransformPipeline.h | 3 ++ GPU/Math3D.cpp | 4 ++ GPU/Math3D.h | 34 ++++++++++-- GPU/Software/SoftGpu.cpp | 5 ++ GPU/Software/SoftGpu.h | 1 + GPU/Software/TransformUnit.cpp | 86 ++++++++++++++++++++++++++++++- GPU/Software/TransformUnit.h | 5 ++ 11 files changed, 146 insertions(+), 71 deletions(-) diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 8d2e7a68e1..a11366f10b 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -26,6 +26,7 @@ #include "Common/Common.h" #include "Core/Reporting.h" +#include "GPU/Math3D.h" #include "GPU/GPUState.h" #include "GPU/ge_constants.h" #include "GPU/Directx9/ShaderManagerDX9.h" @@ -257,29 +258,10 @@ void LinkedShaderDX9::SetColorUniform3ExtraFloat(D3DXHANDLE uniform, u32 color, SetFloatArray(uniform, col, 4); } -static void ConvertMatrix4x3To4x4(const float *m4x3, float *m4x4) { - m4x4[0] = m4x3[0]; - m4x4[1] = m4x3[1]; - m4x4[2] = m4x3[2]; - m4x4[3] = 0.0f; - m4x4[4] = m4x3[3]; - m4x4[5] = m4x3[4]; - m4x4[6] = m4x3[5]; - m4x4[7] = 0.0f; - m4x4[8] = m4x3[6]; - m4x4[9] = m4x3[7]; - m4x4[10] = m4x3[8]; - m4x4[11] = 0.0f; - m4x4[12] = m4x3[9]; - m4x4[13] = m4x3[10]; - m4x4[14] = m4x3[11]; - m4x4[15] = 1.0f; -} - // Utility void LinkedShaderDX9::SetMatrix4x3(D3DXHANDLE uniform, const float *m4x3) { float m4x4[16]; - ConvertMatrix4x3To4x4(m4x3, m4x4); + ConvertMatrix4x3To4x4(m4x4, m4x3); if (m_vs->constant->SetMatrix(pD3Ddevice, uniform, (D3DXMATRIX*)m4x4) == D3D_OK); else @@ -423,7 +405,7 @@ void LinkedShaderDX9::updateUniforms() { bool allDirty = true; for (int i = 0; i < numBones; i++) { if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { - ConvertMatrix4x3To4x4(gstate.boneMatrix + 12 * i, allBones + 16 * i); + ConvertMatrix4x3To4x4(allBones + 16 * i, gstate.boneMatrix + 12 * i); } else { allDirty = false; } @@ -444,7 +426,7 @@ void LinkedShaderDX9::updateUniforms() { float bonetemp[16]; for (int i = 0; i < numBones; i++) { if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { - ConvertMatrix4x3To4x4(gstate.boneMatrix + 12 * i, bonetemp); + ConvertMatrix4x3To4x4(bonetemp, gstate.boneMatrix + 12 * i); if (u_bone[i] != 0) SetMatrix(u_bone[i], bonetemp); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index cfe94beb83..7c80bea049 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -32,6 +32,7 @@ #include "Core/Config.h" #include "Core/Reporting.h" +#include "GPU/Math3D.h" #include "GPU/GPUState.h" #include "GPU/ge_constants.h" #include "GPU/GLES/ShaderManager.h" @@ -307,28 +308,9 @@ static void SetColorUniform3ExtraFloat(int uniform, u32 color, float extra) { glUniform4fv(uniform, 1, col); } -static void ConvertMatrix4x3To4x4(const float *m4x3, float *m4x4) { - m4x4[0] = m4x3[0]; - m4x4[1] = m4x3[1]; - m4x4[2] = m4x3[2]; - m4x4[3] = 0.0f; - m4x4[4] = m4x3[3]; - m4x4[5] = m4x3[4]; - m4x4[6] = m4x3[5]; - m4x4[7] = 0.0f; - m4x4[8] = m4x3[6]; - m4x4[9] = m4x3[7]; - m4x4[10] = m4x3[8]; - m4x4[11] = 0.0f; - m4x4[12] = m4x3[9]; - m4x4[13] = m4x3[10]; - m4x4[14] = m4x3[11]; - m4x4[15] = 1.0f; -} - static void SetMatrix4x3(int uniform, const float *m4x3) { float m4x4[16]; - ConvertMatrix4x3To4x4(m4x3, m4x4); + ConvertMatrix4x3To4x4(m4x4, m4x3); glUniformMatrix4fv(uniform, 1, GL_FALSE, m4x4); } @@ -496,7 +478,7 @@ void LinkedShader::UpdateUniforms(u32 vertType) { bool allDirty = true; for (int i = 0; i < numBones; i++) { if (dirty & (DIRTY_BONEMATRIX0 << i)) { - ConvertMatrix4x3To4x4(gstate.boneMatrix + 12 * i, allBones + 16 * i); + ConvertMatrix4x3To4x4(allBones + 16 * i, gstate.boneMatrix + 12 * i); } else { allDirty = false; } @@ -517,7 +499,7 @@ void LinkedShader::UpdateUniforms(u32 vertType) { float bonetemp[16]; for (int i = 0; i < numBones; i++) { if (dirty & (DIRTY_BONEMATRIX0 << i)) { - ConvertMatrix4x3To4x4(gstate.boneMatrix + 12 * i, bonetemp); + ConvertMatrix4x3To4x4(bonetemp, gstate.boneMatrix + 12 * i); glUniformMatrix4fv(u_bone[i], 1, GL_FALSE, bonetemp); } } diff --git a/GPU/GLES/Spline.cpp b/GPU/GLES/Spline.cpp index 2c59e53194..8ecd6c63a1 100644 --- a/GPU/GLES/Spline.cpp +++ b/GPU/GLES/Spline.cpp @@ -28,10 +28,9 @@ // The rest of the transform pipeline like lighting will go as normal, either hardware or software. // The implementation is initially a bit inefficient but shouldn't be a big deal. // An intermediate buffer of not-easy-to-predict size is stored at bufPtr. -u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) { +u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType) { // First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate // implementation of the vertex decoder. - VertexDecoder *dec = GetVertexDecoder(vertType); dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound); // OK, morphing eliminated but bones still remain to be taken care of. @@ -128,6 +127,11 @@ u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inP return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & GE_VTYPE_IDX_MASK); } +u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) { + VertexDecoder *dec = GetVertexDecoder(vertType); + return NormalizeVertices(outPtr, bufPtr, inPtr, dec, lowerBound, upperBound, vertType); +} + #define START_OPEN 1 #define END_OPEN 2 diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index b3de237982..4bf759d70a 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -751,25 +751,6 @@ void PlanesFromMatrix(float mtx[16], Plane planes[6]) { planes[5].Set(mtx[3]-mtx[2], mtx[7]-mtx[6], mtx[11]-mtx[10], mtx[15]-mtx[14]); // Far } -static void ConvertMatrix4x3To4x4(float *m4x4, const float *m4x3) { - m4x4[0] = m4x3[0]; - m4x4[1] = m4x3[1]; - m4x4[2] = m4x3[2]; - m4x4[3] = 0.0f; - m4x4[4] = m4x3[3]; - m4x4[5] = m4x3[4]; - m4x4[6] = m4x3[5]; - m4x4[7] = 0.0f; - m4x4[8] = m4x3[6]; - m4x4[9] = m4x3[7]; - m4x4[10] = m4x3[8]; - m4x4[11] = 0.0f; - m4x4[12] = m4x3[9]; - m4x4[13] = m4x3[10]; - m4x4[14] = m4x3[11]; - m4x4[15] = 1.0f; -} - // This code is HIGHLY unoptimized! // // It does the simplest and safest test possible: If all points of a bbox is outside a single of diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 7d463237dc..8fb489c662 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -132,6 +132,9 @@ public: return decJitCache_->IsInSpace(ptr); } + // Really just for convenience to share with softgpu. + static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType); + private: void DecodeVerts(); void DecodeVertsStep(); diff --git a/GPU/Math3D.cpp b/GPU/Math3D.cpp index 48577017eb..a521628588 100644 --- a/GPU/Math3D.cpp +++ b/GPU/Math3D.cpp @@ -17,6 +17,8 @@ #include "Math3D.h" +namespace Math3D { + template<> float Vec2::Length() const { @@ -188,3 +190,5 @@ float Vec4::Normalize() (*this) = (*this)/len; return len; } + +}; // namespace Math3D \ No newline at end of file diff --git a/GPU/Math3D.h b/GPU/Math3D.h index e1095511b1..f5502c304c 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -19,6 +19,8 @@ #include +namespace Math3D { + // Helper for Vec classes to clamp values. template inline static T VecClamp(const T &v, const T &low, const T &high) @@ -318,8 +320,6 @@ public: #undef _DEFINE_SWIZZLER2 }; -typedef Vec3 Vec3f; - template class Vec4 { @@ -488,8 +488,6 @@ public: #undef _DEFINE_SWIZZLER3 }; -typedef Vec4 Vec4f; - template class Mat3x3 @@ -590,6 +588,11 @@ private: BaseType values[4*4]; }; +}; // namespace Math3D + +typedef Math3D::Vec3 Vec3f; +typedef Math3D::Vec4 Vec4f; + inline void Vec3ByMatrix43(float vecOut[3], const float v[3], const float m[12]) { @@ -629,12 +632,33 @@ inline void Matrix4ByMatrix4(float out[16], const float a[16], const float b[16] Vec4ByMatrix44(out + 12, a + 12, b); } +inline void ConvertMatrix4x3To4x4(float *m4x4, const float *m4x3) { + m4x4[0] = m4x3[0]; + m4x4[1] = m4x3[1]; + m4x4[2] = m4x3[2]; + m4x4[3] = 0.0f; + m4x4[4] = m4x3[3]; + m4x4[5] = m4x3[4]; + m4x4[6] = m4x3[5]; + m4x4[7] = 0.0f; + m4x4[8] = m4x3[6]; + m4x4[9] = m4x3[7]; + m4x4[10] = m4x3[8]; + m4x4[11] = 0.0f; + m4x4[12] = m4x3[9]; + m4x4[13] = m4x3[10]; + m4x4[14] = m4x3[11]; + m4x4[15] = 1.0f; +} + inline float Vec3Dot(const float v1[3], const float v2[3]) { return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; } +namespace Math3D { + template inline T Dot(const Vec2& a, const Vec2& b) { @@ -659,6 +683,8 @@ inline Vec3 Cross(const Vec3& a, const Vec3& b) return Vec3(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x); } +}; // namespace Math3D + // linear interpolation via float: 0.0=begin, 1.0=end template inline X Lerp(const X& begin, const X& end, const float t) diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 864a9c3042..267ee7b6f0 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -910,3 +910,8 @@ bool SoftGPU::GetCurrentTexture(GPUDebugBuffer &buffer) { return Rasterizer::GetCurrentTexture(buffer); } + +bool SoftGPU::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) +{ + return TransformUnit::GetCurrentSimpleVertices(count, vertices, indices); +} diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 5efb39afe9..575e18fea8 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -86,6 +86,7 @@ public: virtual bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); virtual bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); virtual bool GetCurrentTexture(GPUDebugBuffer &buffer); + bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); protected: virtual void FastRunLoop(DisplayList &list); diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 8d411af214..0e964740e5 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -16,8 +16,11 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Core/Host.h" -#include "../GPUState.h" -#include "../GLES/VertexDecoder.h" +#include "Core/Config.h" +#include "GPU/GPUState.h" +#include "GPU/GLES/VertexDecoder.h" +#include "GPU/GLES/TransformPipeline.h" +#include "GPU/Common/SplineCommon.h" #include "TransformUnit.h" #include "Clipper.h" @@ -473,3 +476,82 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type host->GPUNotifyDraw(); } + +// TODO: This probably is not the best interface. +bool TransformUnit::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(); + } + + static std::vector temp_buffer; + static std::vector simpleVertices; + temp_buffer.resize(65536 * 24 / sizeof(u32)); + simpleVertices.resize(indexUpperBound + 1); + + VertexDecoder vdecoder; + vdecoder.SetVertexType(gstate.vertType); + TransformDrawEngine::NormalizeVertices((u8 *)(&simpleVertices[0]), (u8 *)(&temp_buffer[0]), Memory::GetPointer(gstate_c.vertexAddr), &vdecoder, indexLowerBound, indexUpperBound, gstate.vertType); + + float world[16]; + float view[16]; + float worldview[16]; + float worldviewproj[16]; + ConvertMatrix4x3To4x4(world, gstate.worldMatrix); + ConvertMatrix4x3To4x4(view, gstate.viewMatrix); + Matrix4ByMatrix4(worldview, world, view); + Matrix4ByMatrix4(worldviewproj, worldview, 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 { + float clipPos[4]; + Vec3ByMatrix44(clipPos, vert.pos.AsArray(), worldviewproj); + ScreenCoords screenPos = ClipToScreen(clipPos); + DrawingCoords 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; + vertices[i].z = 1.0; + } + } + + return true; +} diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index ba616cc30d..fbcd459a22 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -18,8 +18,11 @@ #pragma once #include "CommonTypes.h" +#include "GPU/Common/GPUDebugInterface.h" #include "../Math3D.h" +using namespace Math3D; + typedef u16 fixed16; typedef u16 u10; // TODO: erm... :/ @@ -118,4 +121,6 @@ public: static void SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type); static void SubmitPrimitive(void* vertices, void* indices, u32 prim_type, int vertex_count, u32 vertex_type, int *bytesRead); + + static bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); }; From 8f73ae07c056653cdb639aeba6716311a8bcbb82 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Dec 2013 13:43:13 -0800 Subject: [PATCH 5/5] softgpu: Fix preview region y1 in ge debugger. --- GPU/Software/SoftGpu.cpp | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 267ee7b6f0..4945fa9172 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -865,38 +865,34 @@ bool SoftGPU::FramebufferDirty() { bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { - int w = gstate.getRegionX2() - gstate.getRegionX1() + 1; - int h = gstate.getRegionY2() - gstate.getRegionY1() + 1; + const int w = gstate.getRegionX2() - gstate.getRegionX1() + 1; + const int h = gstate.getRegionY2() - gstate.getRegionY1() + 1; buffer.Allocate(w, h, gstate.FrameBufFormat()); - u8 *src = fb.data; + const int depth = gstate.FrameBufFormat() == GE_FORMAT_8888 ? 4 : 2; + const u8 *src = fb.data + gstate.FrameBufStride() * depth * gstate.getRegionY1(); u8 *dst = buffer.GetData(); for (int y = gstate.getRegionY1(); y <= gstate.getRegionY2(); ++y) { - if (gstate.FrameBufFormat() == GE_FORMAT_8888) { - memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * 4); - dst += w * 4; - src += gstate.FrameBufStride() * 4; - } else { - memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * 2); - dst += w * 2; - src += gstate.FrameBufStride() * 2; - } + memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * depth); + dst += w * depth; + src += gstate.FrameBufStride() * depth; } return true; } bool SoftGPU::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - int w = gstate.getRegionX2() - gstate.getRegionX1() + 1; - int h = gstate.getRegionY2() - gstate.getRegionY1() + 1; + const int w = gstate.getRegionX2() - gstate.getRegionX1() + 1; + const int h = gstate.getRegionY2() - gstate.getRegionY1() + 1; buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT); - u8 *src = depthbuf.data; + const int depth = 2; + const u8 *src = depthbuf.data + gstate.DepthBufStride() * depth * gstate.getRegionY1(); u8 *dst = buffer.GetData(); for (int y = gstate.getRegionY1(); y <= gstate.getRegionY2(); ++y) { - memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * 2); - dst += w * 2; - src += gstate.DepthBufStride() * 2; + memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * depth); + dst += w * depth; + src += gstate.DepthBufStride() * depth; } return true; }