diff --git a/CMakeLists.txt b/CMakeLists.txt index 418f674667..9f4325f0d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1583,6 +1583,8 @@ set(GPU_SOURCES GPU/GPUState.h GPU/Math3D.cpp GPU/Math3D.h + GPU/Software/BinManager.cpp + GPU/Software/BinManager.h GPU/Software/Clipper.cpp GPU/Software/Clipper.h GPU/Software/DrawPixel.cpp diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 91cadddc57..a7877051d0 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -452,6 +452,7 @@ + @@ -630,6 +631,7 @@ + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index ef62c791c0..7351bb3b08 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -276,6 +276,9 @@ Software + + Software + @@ -554,6 +557,9 @@ Software + + Software + diff --git a/GPU/Software/BinManager.cpp b/GPU/Software/BinManager.cpp new file mode 100644 index 0000000000..4c44a5c635 --- /dev/null +++ b/GPU/Software/BinManager.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2022- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "GPU/Software/BinManager.h" +#include "GPU/Software/Rasterizer.h" +#include "GPU/Software/RasterizerRectangle.h" + +void BinManager::AddTriangle(const VertexData &v0, const VertexData &v1, const VertexData &v2) { + Vec2 d01((int)v0.screenpos.x - (int)v1.screenpos.x, (int)v0.screenpos.y - (int)v1.screenpos.y); + Vec2 d02((int)v0.screenpos.x - (int)v2.screenpos.x, (int)v0.screenpos.y - (int)v2.screenpos.y); + Vec2 d12((int)v1.screenpos.x - (int)v2.screenpos.x, (int)v1.screenpos.y - (int)v2.screenpos.y); + + // Drop primitives which are not in CCW order by checking the cross product. + if (d01.x * d02.y - d01.y * d02.x < 0) + return; + // If all points have identical coords, we'll have 0 weights and not skip properly, so skip here. + if (d01.x == 0 && d01.y == 0 && d02.x == 0 && d02.y == 0) + return; + + // TODO + Rasterizer::DrawTriangle(v0, v1, v2, enqueueState_); +} + +void BinManager::AddClearRect(const VertexData &v0, const VertexData &v1) { + // TODO + Rasterizer::ClearRectangle(v0, v1, enqueueState_); +} + +void BinManager::AddSprite(const VertexData &v0, const VertexData &v1) { + // TODO + Rasterizer::DrawSprite(v0, v1, enqueueState_); +} + +void BinManager::AddLine(const VertexData &v0, const VertexData &v1) { + // TODO + Rasterizer::DrawLine(v0, v1, enqueueState_); +} + +void BinManager::AddPoint(const VertexData &v0) { + // TODO + Rasterizer::DrawPoint(v0, enqueueState_); +} + +void BinManager::Flush() { + // TODO +} diff --git a/GPU/Software/BinManager.h b/GPU/Software/BinManager.h new file mode 100644 index 0000000000..ba9272f396 --- /dev/null +++ b/GPU/Software/BinManager.h @@ -0,0 +1,42 @@ +// Copyright (c) 2022- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "GPU/Software/Rasterizer.h" + +class BinManager { +public: + void SetEnqueueState(const Rasterizer::RasterizerState &state) { + enqueueState_ = state; + } + + const Rasterizer::RasterizerState &State() { + return enqueueState_; + } + + void AddTriangle(const VertexData &v0, const VertexData &v1, const VertexData &v2); + void AddClearRect(const VertexData &v0, const VertexData &v1); + void AddSprite(const VertexData &v0, const VertexData &v1); + void AddLine(const VertexData &v0, const VertexData &v1); + void AddPoint(const VertexData &v0); + + void Flush(); + +private: + Rasterizer::RasterizerState enqueueState_; +}; diff --git a/GPU/Software/Clipper.cpp b/GPU/Software/Clipper.cpp index bbfc7409d7..fb3bd8ceff 100644 --- a/GPU/Software/Clipper.cpp +++ b/GPU/Software/Clipper.cpp @@ -19,6 +19,7 @@ #include "GPU/GPUState.h" +#include "GPU/Software/BinManager.h" #include "GPU/Software/Clipper.h" #include "GPU/Software/Rasterizer.h" #include "GPU/Software/RasterizerRectangle.h" @@ -127,7 +128,7 @@ static void RotateUVThrough(const VertexData &tl, const VertexData &br, VertexDa } } -void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const Rasterizer::RasterizerState &state, bool fromRectangle); +void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, BinManager &binner, bool fromRectangle); static inline bool CheckOutsideZ(ClipCoords p, int &pos, int &neg) { constexpr float outsideValue = 1.000030517578125f; @@ -143,7 +144,7 @@ static inline bool CheckOutsideZ(ClipCoords p, int &pos, int &neg) { return false; } -void ProcessRect(const VertexData &v0, const VertexData &v1, const Rasterizer::RasterizerState &state) { +void ProcessRect(const VertexData &v0, const VertexData &v1, BinManager &binner) { if (!gstate.isModeThrough()) { // We may discard the entire rect based on depth values. int outsidePos = 0, outsideNeg = 0; @@ -191,14 +192,14 @@ void ProcessRect(const VertexData &v0, const VertexData &v1, const Rasterizer::R } // Four triangles to do backfaces as well. Two of them will get backface culled. - ProcessTriangleInternal(*topleft, *topright, *bottomright, buf[3], state, true); - ProcessTriangleInternal(*bottomright, *topright, *topleft, buf[3], state, true); - ProcessTriangleInternal(*bottomright, *bottomleft, *topleft, buf[3], state, true); - ProcessTriangleInternal(*topleft, *bottomleft, *bottomright, buf[3], state, true); + ProcessTriangleInternal(*topleft, *topright, *bottomright, buf[3], binner, true); + ProcessTriangleInternal(*bottomright, *topright, *topleft, buf[3], binner, true); + ProcessTriangleInternal(*bottomright, *bottomleft, *topleft, buf[3], binner, true); + ProcessTriangleInternal(*topleft, *bottomleft, *bottomright, buf[3], binner, true); } else { // through mode handling - if (Rasterizer::RectangleFastPath(v0, v1, state)) { + if (Rasterizer::RectangleFastPath(v0, v1, binner)) { return; } @@ -240,26 +241,26 @@ void ProcessRect(const VertexData &v0, const VertexData &v1, const Rasterizer::R RotateUVThrough(v0, v1, *topright, *bottomleft); if (gstate.isModeClear()) { - Rasterizer::ClearRectangle(v0, v1, state); + binner.AddClearRect(v0, v1); } else { // Four triangles to do backfaces as well. Two of them will get backface culled. - Rasterizer::DrawTriangle(*topleft, *topright, *bottomleft, state); - Rasterizer::DrawTriangle(*bottomleft, *topright, *topleft, state); - Rasterizer::DrawTriangle(*topright, *bottomright, *bottomleft, state); - Rasterizer::DrawTriangle(*bottomleft, *bottomright, *topright, state); + binner.AddTriangle(*topleft, *topright, *bottomleft); + binner.AddTriangle(*bottomleft, *topright, *topleft); + binner.AddTriangle(*topright, *bottomright, *bottomleft); + binner.AddTriangle(*bottomleft, *bottomright, *topright); } } } -void ProcessPoint(VertexData &v0, const Rasterizer::RasterizerState &state) { +void ProcessPoint(VertexData &v0, BinManager &binner) { // Points need no clipping. Will be bounds checked in the rasterizer (which seems backwards?) - Rasterizer::DrawPoint(v0, state); + binner.AddPoint(v0); } -void ProcessLine(VertexData &v0, VertexData &v1, const Rasterizer::RasterizerState &state) { +void ProcessLine(VertexData &v0, VertexData &v1, BinManager &binner) { if (gstate.isModeThrough()) { // Actually, should clip this one too so we don't need to do bounds checks in the rasterizer. - Rasterizer::DrawLine(v0, v1, state); + binner.AddLine(v0, v1); return; } @@ -286,19 +287,19 @@ void ProcessLine(VertexData &v0, VertexData &v1, const Rasterizer::RasterizerSta VertexData data[2] = { *Vertices[0], *Vertices[1] }; data[0].screenpos = TransformUnit::ClipToScreen(data[0].clippos); data[1].screenpos = TransformUnit::ClipToScreen(data[1].clippos); - Rasterizer::DrawLine(data[0], data[1], state); + binner.AddLine(data[0], data[1]); } -void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const Rasterizer::RasterizerState &state, bool fromRectangle) { +void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, BinManager &binner, bool fromRectangle) { if (gstate.isModeThrough()) { // In case of cull reordering, make sure the right color is on the final vertex. if (gstate.getShadeMode() == GE_SHADE_FLAT) { VertexData corrected2 = v2; corrected2.color0 = provoking.color0; corrected2.color1 = provoking.color1; - Rasterizer::DrawTriangle(v0, v1, corrected2, state); + binner.AddTriangle(v0, v1, corrected2); } else { - Rasterizer::DrawTriangle(v0, v1, v2, state); + binner.AddTriangle(v0, v1, v2); } return; } @@ -382,13 +383,13 @@ void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, con data[2].color1 = provoking.color1; } - Rasterizer::DrawTriangle(data[0], data[1], data[2], state); + binner.AddTriangle(data[0], data[1], data[2]); } } } -void ProcessTriangle(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const Rasterizer::RasterizerState &state) { - ProcessTriangleInternal(v0, v1, v2, provoking, state, false); +void ProcessTriangle(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, BinManager &binner) { + ProcessTriangleInternal(v0, v1, v2, provoking, binner, false); } } // namespace diff --git a/GPU/Software/Clipper.h b/GPU/Software/Clipper.h index c5f555eb66..f55d56510d 100644 --- a/GPU/Software/Clipper.h +++ b/GPU/Software/Clipper.h @@ -22,15 +22,13 @@ struct PixelFuncID; struct SamplerID; -namespace Rasterizer { -struct RasterizerState; -}; +class BinManager; namespace Clipper { -void ProcessPoint(VertexData &v0, const Rasterizer::RasterizerState &state); -void ProcessLine(VertexData &v0, VertexData &v1, const Rasterizer::RasterizerState &state); -void ProcessTriangle(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const Rasterizer::RasterizerState &state); -void ProcessRect(const VertexData &v0, const VertexData &v1, const Rasterizer::RasterizerState &state); +void ProcessPoint(VertexData &v0, BinManager &binner); +void ProcessLine(VertexData &v0, VertexData &v1, BinManager &binner); +void ProcessTriangle(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, BinManager &binner); +void ProcessRect(const VertexData &v0, const VertexData &v1, BinManager &binner); } diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index ce9f90ae44..180188ea26 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -970,17 +970,6 @@ void DrawTriangleSlice( void DrawTriangle(const VertexData &v0, const VertexData &v1, const VertexData &v2, const RasterizerState &state) { PROFILE_THIS_SCOPE("draw_tri"); - Vec2 d01((int)v0.screenpos.x - (int)v1.screenpos.x, (int)v0.screenpos.y - (int)v1.screenpos.y); - Vec2 d02((int)v0.screenpos.x - (int)v2.screenpos.x, (int)v0.screenpos.y - (int)v2.screenpos.y); - Vec2 d12((int)v1.screenpos.x - (int)v2.screenpos.x, (int)v1.screenpos.y - (int)v2.screenpos.y); - - // Drop primitives which are not in CCW order by checking the cross product - if (d01.x * d02.y - d01.y * d02.x < 0) - return; - // If all points have identical coords, we'll have 0 weights and not skip properly, so skip here. - if (d01.x == 0 && d01.y == 0 && d02.x == 0 && d02.y == 0) - return; - int minX = std::min(std::min(v0.screenpos.x, v1.screenpos.x), v2.screenpos.x) & ~0xF; int minY = std::min(std::min(v0.screenpos.y, v1.screenpos.y), v2.screenpos.y) & ~0xF; int maxX = std::max(std::max(v0.screenpos.x, v1.screenpos.x), v2.screenpos.x) | 0xF; diff --git a/GPU/Software/RasterizerRectangle.cpp b/GPU/Software/RasterizerRectangle.cpp index af02589094..8b920642d9 100644 --- a/GPU/Software/RasterizerRectangle.cpp +++ b/GPU/Software/RasterizerRectangle.cpp @@ -16,6 +16,7 @@ #include "GPU/GPUState.h" #include "GPU/Common/TextureCacheCommon.h" +#include "GPU/Software/BinManager.h" #include "GPU/Software/DrawPixel.h" #include "GPU/Software/Rasterizer.h" #include "GPU/Software/Sampler.h" @@ -273,7 +274,9 @@ static inline bool NoClampOrWrap(const Vec2f &tc) { } // Returns true if the normal path should be skipped. -bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const RasterizerState &state) { +bool RectangleFastPath(const VertexData &v0, const VertexData &v1, BinManager &binner) { + const RasterizerState &state = binner.State(); + g_DarkStalkerStretch = DSStretch::Off; // Check for 1:1 texture mapping. In that case we can call DrawSprite. int xdiff = v1.screenpos.x - v0.screenpos.x; @@ -289,7 +292,7 @@ bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const Rasteri bool state_check = !state.pixelID.clearMode && NoClampOrWrap(v0.texturecoords) && NoClampOrWrap(v1.texturecoords); // TODO: No mipmap levels? Might be a font at level 1... if ((coord_check || !state.enableTextures) && orient_check && state_check) { - Rasterizer::DrawSprite(v0, v1, state); + binner.AddSprite(v0, v1); return true; } @@ -311,7 +314,7 @@ bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const Rasteri gstate.textureMapEnable &= ~1; VertexData newV1 = v1; newV1.color0 = Vec4(0, 0, 0, 255); - Rasterizer::DrawSprite(v0, newV1, state); + binner.AddSprite(v0, newV1); gstate.textureMapEnable |= 1; } return true; diff --git a/GPU/Software/RasterizerRectangle.h b/GPU/Software/RasterizerRectangle.h index 76c41f727d..801fff5b2a 100644 --- a/GPU/Software/RasterizerRectangle.h +++ b/GPU/Software/RasterizerRectangle.h @@ -12,9 +12,12 @@ // sense to specifically detect rectangles that do 1:1 texture mapping (like a sprite), because // the JIT will then be able to eliminate UV interpolation. +class BinManager; + namespace Rasterizer { // Returns true if the normal path should be skipped. - bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const RasterizerState &state); + bool RectangleFastPath(const VertexData &v0, const VertexData &v1, BinManager &binner); + void DrawSprite(const VertexData &v0, const VertexData &v1, const RasterizerState &state); bool DetectRectangleFromThroughModeStrip(const VertexData data[4]); bool DetectRectangleFromThroughModeFan(const VertexData *data, int c, int *tlIndex, int *brIndex); diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 0c490c2057..83e85e06e3 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -29,6 +29,7 @@ #include "GPU/Common/SplineCommon.h" #include "GPU/Common/TextureDecoder.h" #include "GPU/Debugger/Debugger.h" +#include "GPU/Software/BinManager.h" #include "GPU/Software/Clipper.h" #include "GPU/Software/FuncId.h" #include "GPU/Software/Lighting.h" @@ -345,6 +346,9 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy Rasterizer::RasterizerState state; ComputeRasterizerState(&state); + BinManager binner; + binner.SetEnqueueState(state); + bool outside_range_flag = false; switch (prim_type) { case GE_PRIM_POINTS: @@ -376,22 +380,22 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy case GE_PRIM_TRIANGLES: { if (!gstate.isCullEnabled() || gstate.isModeClear()) { - Clipper::ProcessTriangle(data[0], data[1], data[2], data[2], state); - Clipper::ProcessTriangle(data[2], data[1], data[0], data[2], state); + Clipper::ProcessTriangle(data[0], data[1], data[2], data[2], binner); + Clipper::ProcessTriangle(data[2], data[1], data[0], data[2], binner); } else if (!gstate.getCullMode()) { - Clipper::ProcessTriangle(data[2], data[1], data[0], data[2], state); + Clipper::ProcessTriangle(data[2], data[1], data[0], data[2], binner); } else { - Clipper::ProcessTriangle(data[0], data[1], data[2], data[2], state); + Clipper::ProcessTriangle(data[0], data[1], data[2], data[2], binner); } break; } case GE_PRIM_LINES: - Clipper::ProcessLine(data[0], data[1], state); + Clipper::ProcessLine(data[0], data[1], binner); break; case GE_PRIM_POINTS: - Clipper::ProcessPoint(data[0], state); + Clipper::ProcessPoint(data[0], binner); break; default: @@ -431,14 +435,14 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy } if (data_index == 4) { - Clipper::ProcessRect(data[0], data[1], state); - Clipper::ProcessRect(data[2], data[3], state); + Clipper::ProcessRect(data[0], data[1], binner); + Clipper::ProcessRect(data[2], data[3], binner); data_index = 0; } } if (data_index >= 2) { - Clipper::ProcessRect(data[0], data[1], state); + Clipper::ProcessRect(data[0], data[1], binner); data_index -= 2; } break; @@ -467,7 +471,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy --skip_count; } else { // We already incremented data_index, so data_index & 1 is previous one. - Clipper::ProcessLine(data[data_index & 1], data[(data_index & 1) ^ 1], state); + Clipper::ProcessLine(data[data_index & 1], data[(data_index & 1) ^ 1], binner); } } break; @@ -493,7 +497,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy // If a strip is effectively a rectangle, draw it as such! if (!outside_range_flag && Rasterizer::DetectRectangleFromThroughModeStrip(data)) { - Clipper::ProcessRect(data[0], data[3], state); + Clipper::ProcessRect(data[0], data[3], binner); break; } } @@ -521,14 +525,14 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy } if (!gstate.isCullEnabled() || gstate.isModeClear()) { - Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], state); - Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], state); + Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], binner); + Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], binner); } else if ((!gstate.getCullMode()) ^ ((data_index - 1) % 2)) { // We need to reverse the vertex order for each second primitive, // but we additionally need to do that for every primitive if CCW cullmode is used. - Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], state); + Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], binner); } else { - Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], state); + Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], binner); } } break; @@ -569,7 +573,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy int tl = -1, br = -1; if (!outside_range_flag && Rasterizer::DetectRectangleFromThroughModeFan(data, vertex_count, &tl, &br)) { - Clipper::ProcessRect(data[tl], data[br], state); + Clipper::ProcessRect(data[tl], data[br], binner); break; } } @@ -597,14 +601,14 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy } if (!gstate.isCullEnabled() || gstate.isModeClear()) { - Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], state); - Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], state); + Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], binner); + Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], binner); } else if ((!gstate.getCullMode()) ^ ((data_index - 1) % 2)) { // We need to reverse the vertex order for each second primitive, // but we additionally need to do that for every primitive if CCW cullmode is used. - Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], state); + Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], binner); } else { - Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], state); + Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], binner); } } break; @@ -615,6 +619,8 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy break; } + binner.Flush(); + GPUDebug::NotifyDraw(); } diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index d8e70972e6..a97aa2d25b 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -425,6 +425,7 @@ + @@ -486,6 +487,7 @@ + diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters index 2f982e10b0..069e5eab00 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters @@ -45,6 +45,7 @@ + @@ -104,6 +105,7 @@ + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 6e255a8c36..6e1d3eb471 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -364,6 +364,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/GPU/GLES/ShaderManagerGLES.cpp.arm \ $(SRC)/GPU/GLES/FragmentTestCacheGLES.cpp.arm \ $(SRC)/GPU/GLES/TextureScalerGLES.cpp \ + $(SRC)/GPU/Software/BinManager.cpp \ $(SRC)/GPU/Software/Clipper.cpp \ $(SRC)/GPU/Software/DrawPixel.cpp.arm \ $(SRC)/GPU/Software/FuncId.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 9d4a0dcbd1..a0e60371c4 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -351,6 +351,7 @@ SOURCES_CXX += \ $(GPUDIR)/GPU.cpp \ $(GPUDIR)/GPUState.cpp \ $(GPUDIR)/Math3D.cpp \ + $(GPUDIR)/Software/BinManager.cpp \ $(GPUDIR)/Software/Clipper.cpp \ $(GPUDIR)/Software/DrawPixel.cpp \ $(GPUDIR)/Software/FuncId.cpp \