diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 39c892bea..0d78a89a2 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -22,6 +22,7 @@ #include "Common/CommonTypes.h" +#include "GPU/GPUState.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/VertexDecoderCommon.h" @@ -56,6 +57,36 @@ public: std::vector DebugGetVertexLoaderIDs(); std::string DebugGetVertexLoaderString(std::string id, DebugShaderStringType stringType); + + int EstimatePerVertexCost() { + // TODO: This is transform cost, also account for rasterization cost somehow... although it probably + // runs in parallel with transform. + + // Also, this is all pure guesswork. If we can find a way to do measurements, that would be great. + + // GTA wants a low value to run smooth, GoW wants a high value (otherwise it thinks things + // went too fast and starts doing all the work over again). + + int cost = 20; + if (gstate.isLightingEnabled()) { + cost += 10; + + for (int i = 0; i < 4; i++) { + if (gstate.isLightChanEnabled(i)) + cost += 10; + } + } + + if (gstate.getUVGenMode() != GE_TEXMAP_TEXTURE_COORDS) { + cost += 20; + } + int morphCount = gstate.getNumMorphWeights(); + if (morphCount > 1) { + cost += 5 * morphCount; + } + return cost; + } + protected: // Preprocessing for spline/bezier u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType); diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index d9513aa78..3c4255a86 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -135,36 +135,6 @@ public: void SetupVertexDecoder(u32 vertType); void SetupVertexDecoderInternal(u32 vertType); - // This requires a SetupVertexDecoder call first. - int EstimatePerVertexCost() { - // TODO: This is transform cost, also account for rasterization cost somehow... although it probably - // runs in parallel with transform. - - // Also, this is all pure guesswork. If we can find a way to do measurements, that would be great. - - // GTA wants a low value to run smooth, GoW wants a high value (otherwise it thinks things - // went too fast and starts doing all the work over again). - - int cost = 20; - if (gstate.isLightingEnabled()) { - cost += 10; - - for (int i = 0; i < 4; i++) { - if (gstate.isLightChanEnabled(i)) - cost += 10; - } - } - - if (gstate.getUVGenMode() != GE_TEXMAP_TEXTURE_COORDS) { - cost += 20; - } - if (dec_ && dec_->morphcount > 1) { - cost += 5 * dec_->morphcount; - } - - return cost; - } - // So that this can be inlined void Flush() { if (!numDrawCalls) diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index ec3f08011..779bb2127 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -332,7 +332,7 @@ static const CommandTableEntry commandTable[] = { // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... {GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, &GPU_DX9::Execute_LoadClut}, - {GE_CMD_TRANSFERSTART, FLAG_FLUSHBEFORE | FLAG_EXECUTE | FLAG_READS_PC}, + {GE_CMD_TRANSFERSTART, FLAG_FLUSHBEFORE | FLAG_EXECUTE | FLAG_READS_PC, &GPU_DX9::Execute_BlockTransferStart}, // We don't use the dither table. {GE_CMD_DITH0}, @@ -1311,7 +1311,6 @@ void GPU_DX9::Execute_Generic(u32 op, u32 diff) { Execute_Prim(op, diff); break; - // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. case GE_CMD_BEZIER: Execute_Bezier(op, diff); break; @@ -1452,17 +1451,9 @@ void GPU_DX9::Execute_Generic(u32 op, u32 diff) { case GE_CMD_TRANSFERSIZE: break; - case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK - { - // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, - // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. - // Can we skip this entirely on SkipDraw? It skips some things internally. - DoBlockTransfer(gstate_c.skipDrawReason); - - // Fixes Gran Turismo's funky text issue, since it overwrites the current texture. - gstate_c.textureChanged = TEXCHANGE_UPDATED; - break; - } + case GE_CMD_TRANSFERSTART: + Execute_BlockTransferStart(op, diff); + break; case GE_CMD_TEXSIZE0: Execute_TexSize0(op, diff); diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 74f0da189..8f52e7ec9 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -272,7 +272,7 @@ static void ConvertProjMatrixToD3DThrough(Matrix4x4 &in) { in.translateAndScale(Vec3(xoff, yoff, 0.5f), Vec3(1.0f, 1.0f, 0.5f)); } -void ShaderManagerDX9::PSUpdateUniforms(int dirtyUniforms) { +void ShaderManagerDX9::PSUpdateUniforms(u32 dirtyUniforms) { if (dirtyUniforms & DIRTY_TEXENV) { PSSetColorUniform3(CONST_PS_TEXENV, gstate.texenvcolor); } @@ -324,7 +324,7 @@ void ShaderManagerDX9::PSUpdateUniforms(int dirtyUniforms) { } } -void ShaderManagerDX9::VSUpdateUniforms(int dirtyUniforms) { +void ShaderManagerDX9::VSUpdateUniforms(u32 dirtyUniforms) { // Update any dirty uniforms before we draw if (dirtyUniforms & DIRTY_PROJMATRIX) { Matrix4x4 flippedMatrix; diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h index 947960fa2..8b196fe89 100644 --- a/GPU/Directx9/ShaderManagerDX9.h +++ b/GPU/Directx9/ShaderManagerDX9.h @@ -137,8 +137,8 @@ public: std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType); private: - void PSUpdateUniforms(int dirtyUniforms); - void VSUpdateUniforms(int dirtyUniforms); + void PSUpdateUniforms(u32 dirtyUniforms); + void VSUpdateUniforms(u32 dirtyUniforms); void PSSetColorUniform3Alpha255(int creg, u32 color, u8 alpha); void PSSetColorUniform3(int creg, u32 color); void PSSetFloat(int creg, float value); diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index d8d7f0a4b..f085fe40f 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -139,36 +139,6 @@ public: void SetupVertexDecoder(u32 vertType); inline void SetupVertexDecoderInternal(u32 vertType); - // This requires a SetupVertexDecoder call first. - int EstimatePerVertexCost() { - // TODO: This is transform cost, also account for rasterization cost somehow... although it probably - // runs in parallel with transform. - - // Also, this is all pure guesswork. If we can find a way to do measurements, that would be great. - - // GTA wants a low value to run smooth, GoW wants a high value (otherwise it thinks things - // went too fast and starts doing all the work over again). - - int cost = 20; - if (gstate.isLightingEnabled()) { - cost += 10; - - for (int i = 0; i < 4; i++) { - if (gstate.isLightChanEnabled(i)) - cost += 10; - } - } - - if (gstate.getUVGenMode() != GE_TEXMAP_TEXTURE_COORDS) { - cost += 20; - } - if (dec_ && dec_->morphcount > 1) { - cost += 5 * dec_->morphcount; - } - - return cost; - } - // So that this can be inlined void Flush() { if (!numDrawCalls) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 432153fbb..c53fb5e6d 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -335,7 +335,7 @@ static const CommandTableEntry commandTable[] = { // Changes that trigger data copies. Only flushing on change for LOADCLUT must be a bit of a hack... {GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPU_GLES::Execute_LoadClut}, - {GE_CMD_TRANSFERSTART, FLAG_FLUSHBEFORE | FLAG_EXECUTE | FLAG_READS_PC, 0, &GPU_GLES::Execute_BlockTransferStart}, + {GE_CMD_TRANSFERSTART, FLAG_FLUSHBEFORE | FLAG_EXECUTE | FLAG_READS_PC, 0, &GPUCommon::Execute_BlockTransferStart}, // We don't use the dither table. {GE_CMD_DITH0}, @@ -1512,16 +1512,6 @@ void GPU_GLES::Execute_BoneMtxData(u32 op, u32 diff) { gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (num & 0x7F); } -void GPU_GLES::Execute_BlockTransferStart(u32 op, u32 diff) { - // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, - // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. - // Can we skip this on SkipDraw? - DoBlockTransfer(gstate_c.skipDrawReason); - - // Fixes Gran Turismo's funky text issue, since it overwrites the current texture. - gstate_c.textureChanged = TEXCHANGE_UPDATED; -} - void GPU_GLES::Execute_Generic(u32 op, u32 diff) { u32 cmd = op >> 24; u32 data = op & 0xFFFFFF; @@ -1543,7 +1533,6 @@ void GPU_GLES::Execute_Generic(u32 op, u32 diff) { Execute_Prim(op, diff); break; - // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. case GE_CMD_BEZIER: Execute_Bezier(op, diff); break; @@ -1692,7 +1681,7 @@ void GPU_GLES::Execute_Generic(u32 op, u32 diff) { case GE_CMD_TRANSFERSIZE: break; - case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK + case GE_CMD_TRANSFERSTART: Execute_BlockTransferStart(op, diff); break; diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index fa4afa590..ee6796a3c 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -140,7 +140,6 @@ public: void Execute_TgenMtxData(u32 op, u32 diff); void Execute_BoneMtxNum(u32 op, u32 diff); void Execute_BoneMtxData(u32 op, u32 diff); - void Execute_BlockTransferStart(u32 op, u32 diff); // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index f2fcca9a7..f160c08a0 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -547,12 +547,6 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) { glUniform2fv(u_fogcoef, 1, fogcoef); } - // Texturing - - // If this dirty check is changed to true, Frontier Gate Boost works in texcoord speedhack mode. - // This means that it's not a flushing issue. - // It uses GE_TEXMAP_TEXTURE_MATRIX with GE_PROJMAP_UV a lot. - // Can't figure out why it doesn't dirty at the right points though... if (dirty & DIRTY_UVSCALEOFFSET) { const float invW = 1.0f / (float)gstate_c.curTextureWidth; const float invH = 1.0f / (float)gstate_c.curTextureHeight; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index f0c7492b2..a03d8ecf4 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1153,6 +1153,16 @@ void GPUCommon::Execute_BoundingBox(u32 op, u32 diff) { } } +void GPUCommon::Execute_BlockTransferStart(u32 op, u32 diff) { + // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, + // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. + // Can we skip this on SkipDraw? + DoBlockTransfer(gstate_c.skipDrawReason); + + // Fixes Gran Turismo's funky text issue, since it overwrites the current texture. + gstate_c.textureChanged = TEXCHANGE_UPDATED; +} + void GPUCommon::ExecuteOp(u32 op, u32 diff) { const u32 cmd = op >> 24; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 6f03cf693..c3fad930e 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -83,6 +83,7 @@ public: void Execute_Bezier(u32 op, u32 diff); void Execute_Spline(u32 op, u32 diff); void Execute_BoundingBox(u32 op, u32 diff); + void Execute_BlockTransferStart(u32 op, u32 diff); u64 GetTickEstimate() override { #if defined(_M_X64) || defined(__ANDROID__) diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 826dc8404..5c430f087 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -393,6 +393,7 @@ struct GPUgstate { bool isModeThrough() const { return (vertType & GE_VTYPE_THROUGH) != 0; } bool areNormalsReversed() const { return reversenormals & 1; } bool isSkinningEnabled() const { return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); } + int getNumMorphWeights() const { return ((vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT) + 1; } GEPatchPrimType getPatchPrimitiveType() const { return static_cast(patchprimitive & 3); } bool isPatchNormalsReversed() const { return patchfacing & 1; } diff --git a/GPU/GeDisasm.cpp b/GPU/GeDisasm.cpp index 5a0d88bb3..f996d2c06 100644 --- a/GPU/GeDisasm.cpp +++ b/GPU/GeDisasm.cpp @@ -135,7 +135,6 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer, int bufsize) { } break; - // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. case GE_CMD_BEZIER: { int bz_ucount = data & 0xFF; @@ -521,7 +520,7 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer, int bufsize) { break; } - case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK + case GE_CMD_TRANSFERSTART: if (data & ~1) snprintf(buffer, bufsize, "Block transfer start: %d (extra %x)", data & 1, data & ~1); else diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index fd6b5e211..58cde7ca7 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -77,7 +77,6 @@ void NullGPU::ExecuteOp(u32 op, u32 diff) { } break; - // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. case GE_CMD_BEZIER: { int bz_ucount = data & 0xFF; @@ -92,7 +91,6 @@ void NullGPU::ExecuteOp(u32 op, u32 diff) { int sp_vcount = (data >> 8) & 0xFF; int sp_utype = (data >> 16) & 0x3; int sp_vtype = (data >> 18) & 0x3; - //drawSpline(sp_ucount, sp_vcount, sp_utype, sp_vtype); DEBUG_LOG(G3D,"DL DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype); } break; diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 5f8dc04d2..b51d17479 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -21,7 +21,7 @@ #include "GPU/Common/GPUDebugInterface.h" #include "thin3d/thin3d.h" -typedef struct { +struct FormatBuffer { union { u8 *data; u16 *as16; @@ -43,7 +43,7 @@ typedef struct { inline u32 Get32(int x, int y, int stride) { return as32[x + y * stride]; } -} FormatBuffer; +}; class ShaderManagerGLES; diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index c27a5a805..b047d92ae 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -94,36 +94,6 @@ public: void SetupVertexDecoder(u32 vertType); void SetupVertexDecoderInternal(u32 vertType); - // This requires a SetupVertexDecoder call first. - int EstimatePerVertexCost() { - // TODO: This is transform cost, also account for rasterization cost somehow... although it probably - // runs in parallel with transform. - - // Also, this is all pure guesswork. If we can find a way to do measurements, that would be great. - - // GTA wants a low value to run smooth, GoW wants a high value (otherwise it thinks things - // went too fast and starts doing all the work over again). - - int cost = 20; - if (gstate.isLightingEnabled()) { - cost += 10; - - for (int i = 0; i < 4; i++) { - if (gstate.isLightChanEnabled(i)) - cost += 10; - } - } - - if (gstate.getUVGenMode() != GE_TEXMAP_TEXTURE_COORDS) { - cost += 20; - } - if (dec_ && dec_->morphcount > 1) { - cost += 5 * dec_->morphcount; - } - - return cost; - } - // So that this can be inlined void Flush(VkCommandBuffer cmd) { if (!numDrawCalls) diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index f706e9704..94c5903e8 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -1301,16 +1301,6 @@ void GPU_Vulkan::Execute_BoneMtxData(u32 op, u32 diff) { gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (num & 0x7F); } -void GPU_Vulkan::Execute_BlockTransferStart(u32 op, u32 diff) { - // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, - // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. - // Can we skip this on SkipDraw? - DoBlockTransfer(gstate_c.skipDrawReason); - - // Fixes Gran Turismo's funky text issue, since it overwrites the current texture. - gstate_c.textureChanged = TEXCHANGE_UPDATED; -} - void GPU_Vulkan::Execute_Generic(u32 op, u32 diff) { u32 cmd = op >> 24; u32 data = op & 0xFFFFFF; @@ -1332,7 +1322,6 @@ void GPU_Vulkan::Execute_Generic(u32 op, u32 diff) { Execute_Prim(op, diff); break; - // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. case GE_CMD_BEZIER: Execute_Bezier(op, diff); break; @@ -1481,7 +1470,7 @@ void GPU_Vulkan::Execute_Generic(u32 op, u32 diff) { case GE_CMD_TRANSFERSIZE: break; - case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK + case GE_CMD_TRANSFERSTART: Execute_BlockTransferStart(op, diff); break; diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 935f08638..14b755d56 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -127,7 +127,6 @@ public: void Execute_TgenMtxData(u32 op, u32 diff); void Execute_BoneMtxNum(u32 op, u32 diff); void Execute_BoneMtxData(u32 op, u32 diff); - void Execute_BlockTransferStart(u32 op, u32 diff); // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; diff --git a/Qt/Debugger/debugger_displaylist.cpp b/Qt/Debugger/debugger_displaylist.cpp index 663e26814..6dfb9847a 100644 --- a/Qt/Debugger/debugger_displaylist.cpp +++ b/Qt/Debugger/debugger_displaylist.cpp @@ -674,7 +674,7 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg return QString("Block Transfer Rect Size: %1 x %2").arg(w).arg(h); } - case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK + case GE_CMD_TRANSFERSTART: { return QString("Block Transfer Start : %1").arg(data ? "32-bit texel size" : "16-bit texel size"); }