Merge pull request #7668 from hrydgard/consolidate-spline

Consolidate spline code
This commit is contained in:
Henrik Rydgård 2015-04-08 22:20:55 +02:00
commit a67f009679
14 changed files with 235 additions and 480 deletions

View File

@ -1452,7 +1452,6 @@ add_library(GPU OBJECT
GPU/GLES/Framebuffer.h
GPU/GLES/ShaderManager.cpp
GPU/GLES/ShaderManager.h
GPU/GLES/Spline.cpp
GPU/GLES/StateMapping.cpp
GPU/GLES/StateMapping.h
GPU/GLES/StencilBuffer.cpp

View File

@ -25,7 +25,30 @@
#include <algorithm>
DrawEngineCommon::~DrawEngineCommon() { }
#define QUAD_INDICES_MAX 65536
DrawEngineCommon::DrawEngineCommon() : dec_(nullptr) {
quadIndices_ = new u16[6 * QUAD_INDICES_MAX];
decJitCache_ = new VertexDecoderJitCache();
}
DrawEngineCommon::~DrawEngineCommon() {
delete[] quadIndices_;
delete decJitCache_;
for (auto iter = decoderMap_.begin(); iter != decoderMap_.end(); iter++) {
delete iter->second;
}
}
VertexDecoder *DrawEngineCommon::GetVertexDecoder(u32 vtype) {
auto iter = decoderMap_.find(vtype);
if (iter != decoderMap_.end())
return iter->second;
VertexDecoder *dec = new VertexDecoder();
dec->SetVertexType(vtype, decOptions_, decJitCache_);
decoderMap_[vtype] = dec;
return dec;
}
struct Plane {
float x, y, z, w;

View File

@ -18,10 +18,12 @@
#pragma once
#include <vector>
#include <unordered_map>
#include "Common/CommonTypes.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/Common/VertexDecoderCommon.h"
class VertexDecoder;
@ -34,20 +36,41 @@ enum {
class DrawEngineCommon {
public:
DrawEngineCommon();
virtual ~DrawEngineCommon();
bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType);
// TODO: This can be shared once the decoder cache / etc. are.
virtual u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) = 0;
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType);
// Flush is normally non-virtual but here's a virtual way to call it, used by the shared spline code, which is expensive anyway.
// Not really sure if these wrappers are worth it...
virtual void DispatchFlush() = 0;
// Same for SubmitPrim
virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) = 0;
void SubmitSpline(const void *control_points, const void *indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType);
void SubmitBezier(const void *control_points, const void *indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType);
protected:
// Preprocessing for spline/bezier
u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType);
VertexDecoder *GetVertexDecoder(u32 vtype);
// Vertex collector buffers
u8 *decoded;
u16 *decIndex;
u8 *splineBuffer;
// Cached vertex decoders
std::unordered_map<u32, VertexDecoder *> decoderMap_;
VertexDecoder *dec_;
VertexDecoderJitCache *decJitCache_;
VertexDecoderOptions decOptions_;
// Fixed index buffer for easy quad generation from spline/bezier
u16 *quadIndices_;
};

View File

@ -22,6 +22,7 @@
#include "Core/Config.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/DrawEngineCommon.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
@ -722,3 +723,179 @@ void TesselateBezierPatch(u8 *&dest, u16 *&indices, int &count, int tess_u, int
break;
}
}
u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) {
const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24);
VertexDecoder *dec = GetVertexDecoder(vertTypeID);
return DrawEngineCommon::NormalizeVertices(outPtr, bufPtr, inPtr, dec, lowerBound, upperBound, vertType);
}
const GEPrimitiveType primType[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS };
void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType) {
DispatchFlush();
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 18;
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
// TODO: Do something less idiotic to manage this buffer
SimpleVertex **points = new SimpleVertex *[count_u * count_v];
// Make an array of pointers to the control points, to get rid of indices.
for (int idx = 0; idx < count_u * count_v; idx++) {
if (indices)
points[idx] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
points[idx] = simplified_control_points + idx;
}
int count = 0;
u8 *dest = splineBuffer;
SplinePatchLocal patch;
patch.type_u = type_u;
patch.type_v = type_v;
patch.count_u = count_u;
patch.count_v = count_v;
patch.points = points;
int maxVertexCount = SPLINE_BUFFER_SIZE / vertexSize;
TesselateSplinePatch(dest, quadIndices_, count, patch, origVertType, maxVertexCount);
delete[] points;
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0;
gstate_c.uv.vOff = 0;
}
int bytesRead;
DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
DispatchFlush();
if (g_Config.bPrescaleUV) {
gstate_c.uv = prevUVScale;
}
}
void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType) {
DispatchFlush();
// TODO: Verify correct functionality with < 4.
if (count_u < 4 || count_v < 4)
return;
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
// There are normally not a lot of control points so just splitting decoded should be reasonably safe, although not great.
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 18;
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
// Bezier patches share less control points than spline patches. Otherwise they are pretty much the same (except bezier don't support the open/close thing)
int num_patches_u = (count_u - 1) / 3;
int num_patches_v = (count_v - 1) / 3;
BezierPatch* patches = new BezierPatch[num_patches_u * num_patches_v];
for (int patch_u = 0; patch_u < num_patches_u; patch_u++) {
for (int patch_v = 0; patch_v < num_patches_v; patch_v++) {
BezierPatch& patch = patches[patch_u + patch_v * num_patches_u];
for (int point = 0; point < 16; ++point) {
int idx = (patch_u * 3 + point % 4) + (patch_v * 3 + point / 4) * count_u;
if (indices)
patch.points[point] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
patch.points[point] = simplified_control_points + idx;
}
patch.u_index = patch_u * 3;
patch.v_index = patch_v * 3;
patch.index = patch_v * num_patches_u + patch_u;
}
}
int count = 0;
u8 *dest = splineBuffer;
// Simple approximation of the real tesselation factor.
// We shouldn't really split up into separate 4x4 patches, instead we should do something that works
// like the splines, so we subdivide across the whole "mega-patch".
if (num_patches_u == 0) num_patches_u = 1;
if (num_patches_v == 0) num_patches_v = 1;
int tess_u = gstate.getPatchDivisionU();
int tess_v = gstate.getPatchDivisionV();
if (tess_u < 4) tess_u = 4;
if (tess_v < 4) tess_v = 4;
u16 *inds = quadIndices_;
int maxVertices = SPLINE_BUFFER_SIZE / vertexSize;
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
BezierPatch& patch = patches[patch_idx];
TesselateBezierPatch(dest, inds, count, tess_u, tess_v, patch, origVertType, maxVertices);
}
delete[] patches;
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0;
gstate_c.uv.vOff = 0;
}
int bytesRead;
DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
DispatchFlush();
if (g_Config.bPrescaleUV) {
gstate_c.uv = prevUVScale;
}
}

View File

@ -1,200 +0,0 @@
// Copyright (c) 2013- 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 "Core/Config.h"
#include "Core/MemMap.h"
#include "GPU/Directx9/TransformPipelineDX9.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/VertexDecoderCommon.h"
namespace DX9 {
u32 TransformDrawEngineDX9::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) {
const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24);
VertexDecoder *dec = GetVertexDecoder(vertTypeID);
return DrawEngineCommon::NormalizeVertices(outPtr, bufPtr, inPtr, dec, lowerBound, upperBound, vertType);
}
const GEPrimitiveType primType[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS };
void TransformDrawEngineDX9::SubmitSpline(const void *control_points, const void *indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType) {
Flush();
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 18;
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
// TODO: Do something less idiotic to manage this buffer
SimpleVertex **points = new SimpleVertex *[count_u * count_v];
// Make an array of pointers to the control points, to get rid of indices.
for (int idx = 0; idx < count_u * count_v; idx++) {
if (indices)
points[idx] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
points[idx] = simplified_control_points + idx;
}
int count = 0;
u8 *dest = splineBuffer;
SplinePatchLocal patch;
patch.type_u = type_u;
patch.type_v = type_v;
patch.count_u = count_u;
patch.count_v = count_v;
patch.points = points;
int maxVertices = SPLINE_BUFFER_SIZE / vertexSize;
TesselateSplinePatch(dest, quadIndices_, count, patch, origVertType, maxVertices);
delete[] points;
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0;
gstate_c.uv.vOff = 0;
}
int bytesRead = 0;
SubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
Flush();
if (g_Config.bPrescaleUV) {
gstate_c.uv = prevUVScale;
}
}
void TransformDrawEngineDX9::SubmitBezier(const void *control_points, const void *indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType) {
Flush();
// TODO: Verify correct functionality with < 4.
if (count_u < 4 || count_v < 4)
return;
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 18;
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
// Bezier patches share less control points than spline patches. Otherwise they are pretty much the same (except bezier don't support the open/close thing)
int num_patches_u = (count_u - 1) / 3;
int num_patches_v = (count_v - 1) / 3;
BezierPatch* patches = new BezierPatch[num_patches_u * num_patches_v];
for (int patch_u = 0; patch_u < num_patches_u; patch_u++) {
for (int patch_v = 0; patch_v < num_patches_v; patch_v++) {
BezierPatch& patch = patches[patch_u + patch_v * num_patches_u];
for (int point = 0; point < 16; ++point) {
int idx = (patch_u * 3 + point%4) + (patch_v * 3 + point/4) * count_u;
if (indices)
patch.points[point] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
patch.points[point] = simplified_control_points + idx;
}
patch.u_index = patch_u * 3;
patch.v_index = patch_v * 3;
patch.index = patch_v * num_patches_u + patch_u;
}
}
u8 *dest = splineBuffer;
int count = 0;
// Simple approximation of the real tesselation factor.
// We shouldn't really split up into separate 4x4 patches, instead we should do something that works
// like the splines, so we subdivide across the whole "mega-patch".
if (num_patches_u == 0) num_patches_u = 1;
if (num_patches_v == 0) num_patches_v = 1;
int tess_u = gstate.getPatchDivisionU();
int tess_v = gstate.getPatchDivisionV();
if (tess_u < 4) tess_u = 4;
if (tess_v < 4) tess_v = 4;
int maxVertices = SPLINE_BUFFER_SIZE / vertexSize;
u16 *inds = quadIndices_;
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
BezierPatch& patch = patches[patch_idx];
TesselateBezierPatch(dest, inds, count, tess_u, tess_v, patch, origVertType, maxVertices);
}
delete[] patches;
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0;
gstate_c.uv.vOff = 0;
}
int bytesRead = 0;
SubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
Flush();
if (g_Config.bPrescaleUV) {
gstate_c.uv = prevUVScale;
}
}
};

View File

@ -74,8 +74,6 @@ enum {
TRANSFORMED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * sizeof(TransformedVertex)
};
#define QUAD_INDICES_MAX 65536
#define VERTEXCACHE_DECIMATION_INTERVAL 17
enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 };
@ -83,7 +81,6 @@ enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MA
TransformDrawEngineDX9::TransformDrawEngineDX9()
: decodedVerts_(0),
prevPrim_(GE_PRIM_INVALID),
dec_(0),
lastVType_(-1),
shaderManager_(0),
textureCache_(0),
@ -110,15 +107,11 @@ TransformDrawEngineDX9::TransformDrawEngineDX9()
transformed = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE);
transformedExpanded = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
quadIndices_ = new u16[6 * QUAD_INDICES_MAX];
if (g_Config.bPrescaleUV) {
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
}
indexGen.Setup(decIndex);
decJitCache_ = new VertexDecoderJitCache();
InitDeviceObjects();
}
@ -129,19 +122,12 @@ TransformDrawEngineDX9::~TransformDrawEngineDX9() {
FreeMemoryPages(splineBuffer, SPLINE_BUFFER_SIZE);
FreeMemoryPages(transformed, TRANSFORMED_VERTEX_BUFFER_SIZE);
FreeMemoryPages(transformedExpanded, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
delete[] quadIndices_;
delete decJitCache_;
for (auto decl = vertexDeclMap_.begin(); decl != vertexDeclMap_.end(); ++decl) {
if (decl->second) {
decl->second->Release();
}
}
for (auto iter = decoderMap_.begin(); iter != decoderMap_.end(); iter++) {
delete iter->second;
}
delete [] uvScale;
}

View File

@ -110,8 +110,6 @@ public:
virtual ~TransformDrawEngineDX9();
void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead);
void SubmitSpline(const void *control_points, const void *indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType);
void SubmitBezier(const void *control_points, const void *indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType);
void SetShaderManager(ShaderManagerDX9 *shaderManager) {
shaderManager_ = shaderManager;
@ -179,9 +177,10 @@ public:
bool IsCodePtrVertexDecoder(const u8 *ptr) const;
protected:
// Preprocessing for spline/bezier
virtual u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) override;
void DispatchFlush() override { Flush(); }
void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) override {
SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead);
}
private:
void DecodeVerts();
@ -221,10 +220,6 @@ private:
int decodedVerts_;
GEPrimitiveType prevPrim_;
// Cached vertex decoders
std::unordered_map<u32, VertexDecoder *> decoderMap_;
VertexDecoder *dec_;
VertexDecoderJitCache *decJitCache_;
u32 lastVType_;
TransformedVertex *transformed;
@ -232,9 +227,6 @@ private:
std::unordered_map<u32, VertexArrayInfoDX9 *> vai_;
std::unordered_map<u32, IDirect3DVertexDeclaration9 *> vertexDeclMap_;
// Fixed index buffer for easy quad generation from spline/bezier
u16 *quadIndices_;
// Other
ShaderManagerDX9 *shaderManager_;
@ -254,7 +246,6 @@ private:
UVScale *uvScale;
bool fboTexBound_;
VertexDecoderOptions decOptions_;
};
} // namespace

View File

@ -1,202 +0,0 @@
// Copyright (c) 2013- 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/GLES/TransformPipeline.h"
#include "Core/Config.h"
#include "Core/MemMap.h"
#include "GPU/Math3D.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/DrawEngineCommon.h"
#include "GPU/Common/VertexDecoderCommon.h"
// Here's how to evaluate them fast:
// http://and-what-happened.blogspot.se/2012/07/evaluating-b-splines-aka-basis-splines.html
u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) {
const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24);
VertexDecoder *dec = GetVertexDecoder(vertTypeID);
return DrawEngineCommon::NormalizeVertices(outPtr, bufPtr, inPtr, dec, lowerBound, upperBound, vertType);
}
const GEPrimitiveType primType[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS };
void TransformDrawEngine::SubmitSpline(const void *control_points, const void *indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType) {
Flush();
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 18;
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
// TODO: Do something less idiotic to manage this buffer
SimpleVertex **points = new SimpleVertex *[count_u * count_v];
// Make an array of pointers to the control points, to get rid of indices.
for (int idx = 0; idx < count_u * count_v; idx++) {
if (indices)
points[idx] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
points[idx] = simplified_control_points + idx;
}
int count = 0;
u8 *dest = splineBuffer;
SplinePatchLocal patch;
patch.type_u = type_u;
patch.type_v = type_v;
patch.count_u = count_u;
patch.count_v = count_v;
patch.points = points;
int maxVertexCount = SPLINE_BUFFER_SIZE / vertexSize;
TesselateSplinePatch(dest, quadIndices_, count, patch, origVertType, maxVertexCount);
delete[] points;
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0;
gstate_c.uv.vOff = 0;
}
int bytesRead;
SubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
Flush();
if (g_Config.bPrescaleUV) {
gstate_c.uv = prevUVScale;
}
}
void TransformDrawEngine::SubmitBezier(const void *control_points, const void *indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType) {
Flush();
// TODO: Verify correct functionality with < 4.
if (count_u < 4 || count_v < 4)
return;
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
// There are normally not a lot of control points so just splitting decoded should be reasonably safe, although not great.
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 18;
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
// Bezier patches share less control points than spline patches. Otherwise they are pretty much the same (except bezier don't support the open/close thing)
int num_patches_u = (count_u - 1) / 3;
int num_patches_v = (count_v - 1) / 3;
BezierPatch* patches = new BezierPatch[num_patches_u * num_patches_v];
for (int patch_u = 0; patch_u < num_patches_u; patch_u++) {
for (int patch_v = 0; patch_v < num_patches_v; patch_v++) {
BezierPatch& patch = patches[patch_u + patch_v * num_patches_u];
for (int point = 0; point < 16; ++point) {
int idx = (patch_u * 3 + point%4) + (patch_v * 3 + point/4) * count_u;
if (indices)
patch.points[point] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
patch.points[point] = simplified_control_points + idx;
}
patch.u_index = patch_u * 3;
patch.v_index = patch_v * 3;
patch.index = patch_v * num_patches_u + patch_u;
}
}
int count = 0;
u8 *dest = splineBuffer;
// Simple approximation of the real tesselation factor.
// We shouldn't really split up into separate 4x4 patches, instead we should do something that works
// like the splines, so we subdivide across the whole "mega-patch".
if (num_patches_u == 0) num_patches_u = 1;
if (num_patches_v == 0) num_patches_v = 1;
int tess_u = gstate.getPatchDivisionU();
int tess_v = gstate.getPatchDivisionV();
if (tess_u < 4) tess_u = 4;
if (tess_v < 4) tess_v = 4;
u16 *inds = quadIndices_;
int maxVertices = SPLINE_BUFFER_SIZE / vertexSize;
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
BezierPatch& patch = patches[patch_idx];
TesselateBezierPatch(dest, inds, count, tess_u, tess_v, patch, origVertType, maxVertices);
}
delete[] patches;
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0;
gstate_c.uv.vOff = 0;
}
int bytesRead;
SubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
Flush();
if (g_Config.bPrescaleUV) {
gstate_c.uv = prevUVScale;
}
}

View File

@ -106,8 +106,6 @@ enum {
TRANSFORMED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * sizeof(TransformedVertex)
};
#define QUAD_INDICES_MAX 65536
#define VERTEXCACHE_DECIMATION_INTERVAL 17
#define VERTEXCACHE_NAME_CACHE_SIZE 64
#define VERTEXCACHE_NAME_CACHE_FULL_SIZE 80
@ -118,7 +116,6 @@ enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MA
TransformDrawEngine::TransformDrawEngine()
: decodedVerts_(0),
prevPrim_(GE_PRIM_INVALID),
dec_(0),
lastVType_(-1),
shaderManager_(0),
textureCache_(0),
@ -141,13 +138,10 @@ TransformDrawEngine::TransformDrawEngine()
transformed = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE);
transformedExpanded = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
quadIndices_ = new u16[6 * QUAD_INDICES_MAX];
if (g_Config.bPrescaleUV) {
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
}
indexGen.Setup(decIndex);
decJitCache_ = new VertexDecoderJitCache();
InitDeviceObjects();
register_gl_resource_holder(this);
@ -160,13 +154,8 @@ TransformDrawEngine::~TransformDrawEngine() {
FreeMemoryPages(splineBuffer, SPLINE_BUFFER_SIZE);
FreeMemoryPages(transformed, TRANSFORMED_VERTEX_BUFFER_SIZE);
FreeMemoryPages(transformedExpanded, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
delete [] quadIndices_;
unregister_gl_resource_holder(this);
delete decJitCache_;
for (auto iter = decoderMap_.begin(); iter != decoderMap_.end(); iter++) {
delete iter->second;
}
delete [] uvScale;
}
@ -241,16 +230,6 @@ static void SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt
VertexAttribSetup(ATTR_POSITION, decFmt.posfmt, decFmt.stride, vertexData + decFmt.posoff);
}
VertexDecoder *TransformDrawEngine::GetVertexDecoder(u32 vtype) {
auto iter = decoderMap_.find(vtype);
if (iter != decoderMap_.end())
return iter->second;
VertexDecoder *dec = new VertexDecoder();
dec->SetVertexType(vtype, decOptions_, decJitCache_);
decoderMap_[vtype] = dec;
return dec;
}
void TransformDrawEngine::SetupVertexDecoder(u32 vertType) {
SetupVertexDecoderInternal(vertType);
}

View File

@ -111,8 +111,6 @@ public:
virtual ~TransformDrawEngine();
void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead);
void SubmitSpline(const void *control_points, const void *indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertType);
void SubmitBezier(const void *control_points, const void *indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType);
void SetShaderManager(ShaderManager *shaderManager) {
shaderManager_ = shaderManager;
@ -182,9 +180,10 @@ public:
bool IsCodePtrVertexDecoder(const u8 *ptr) const;
protected:
// Preprocessing for spline/bezier
virtual u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) override;
void DispatchFlush() override { Flush(); }
void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) override {
SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead);
}
private:
void DecodeVerts();
@ -203,8 +202,6 @@ private:
ReliableHashType ComputeHash(); // Reads deferred vertex data.
void MarkUnreliable(VertexArrayInfo *vai);
VertexDecoder *GetVertexDecoder(u32 vtype);
// Defer all vertex decoding to a Flush, so that we can hash and cache the
// generated buffers without having to redecode them every time.
struct DeferredDrawCall {
@ -223,10 +220,6 @@ private:
int decodedVerts_;
GEPrimitiveType prevPrim_;
// Cached vertex decoders
std::unordered_map<u32, VertexDecoder *> decoderMap_;
VertexDecoder *dec_;
VertexDecoderJitCache *decJitCache_;
u32 lastVType_;
TransformedVertex *transformed;
@ -234,9 +227,6 @@ private:
std::unordered_map<u32, VertexArrayInfo *> vai_;
// Fixed index buffer for easy quad generation from spline/bezier
u16 *quadIndices_;
// Vertex buffer objects
// Element buffer objects
std::vector<GLuint> bufferNameCache_;
@ -259,5 +249,4 @@ private:
UVScale *uvScale;
bool fboTexBound_;
VertexDecoderOptions decOptions_;
};

View File

@ -280,7 +280,6 @@
<ClCompile Include="Directx9\PixelShaderGeneratorDX9.cpp" />
<ClCompile Include="Directx9\FramebufferDX9.cpp" />
<ClCompile Include="Directx9\ShaderManagerDX9.cpp" />
<ClCompile Include="Directx9\SplineDX9.cpp" />
<ClCompile Include="Directx9\StateMappingDX9.cpp" />
<ClCompile Include="Directx9\StencilBufferDX9.cpp" />
<ClCompile Include="Directx9\TextureCacheDX9.cpp" />
@ -294,7 +293,6 @@
<ClCompile Include="GLES\Framebuffer.cpp" />
<ClCompile Include="GLES\GLES_GPU.cpp" />
<ClCompile Include="GLES\ShaderManager.cpp" />
<ClCompile Include="GLES\Spline.cpp" />
<ClCompile Include="GLES\StateMapping.cpp" />
<ClCompile Include="GLES\StencilBuffer.cpp" />
<ClCompile Include="GLES\TextureCache.cpp" />

View File

@ -251,9 +251,6 @@
<ClCompile Include="Directx9\StateMappingDX9.cpp">
<Filter>DirectX9</Filter>
</ClCompile>
<ClCompile Include="Directx9\SplineDX9.cpp">
<Filter>DirectX9</Filter>
</ClCompile>
<ClCompile Include="Directx9\ShaderManagerDX9.cpp">
<Filter>DirectX9</Filter>
</ClCompile>
@ -335,9 +332,6 @@
<ClCompile Include="Common\DrawEngineCommon.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="GLES\Spline.cpp">
<Filter>GLES</Filter>
</ClCompile>
<ClCompile Include="Common\SplineCommon.cpp">
<Filter>Common</Filter>
</ClCompile>

View File

@ -32,7 +32,6 @@ SOURCES += $$P/GPU/GeDisasm.cpp \ # GPU
$$P/GPU/GLES/Framebuffer.cpp \
$$P/GPU/GLES/GLES_GPU.cpp \
$$P/GPU/GLES/ShaderManager.cpp \
$$P/GPU/GLES/Spline.cpp \
$$P/GPU/GLES/StateMapping.cpp \
$$P/GPU/GLES/StencilBuffer.cpp \
$$P/GPU/GLES/TextureCache.cpp \

View File

@ -193,7 +193,6 @@ EXEC_AND_LIB_FILES := \
$(SRC)/GPU/GLES/FragmentShaderGenerator.cpp.arm \
$(SRC)/GPU/GLES/FragmentTestCache.cpp.arm \
$(SRC)/GPU/GLES/TextureScaler.cpp \
$(SRC)/GPU/GLES/Spline.cpp \
$(SRC)/GPU/Null/NullGpu.cpp \
$(SRC)/GPU/Software/Clipper.cpp \
$(SRC)/GPU/Software/Lighting.cpp \