More work on indexed draws. Not combining yet.

This commit is contained in:
Henrik Rydgard 2012-12-21 19:16:17 +01:00
parent 2e9daa5f89
commit 3b114eb24a
7 changed files with 115 additions and 33 deletions

View file

@ -182,6 +182,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
sprintf(stats,
"Frames: %i\n"
"Draw calls: %i\n"
"Draw flushes: %i\n"
"Vertices Transformed: %i\n"
"Textures active: %i\n"
"Vertex shaders loaded: %i\n"
@ -189,6 +190,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
"Combined shaders loaded: %i\n",
gpuStats.numFrames,
gpuStats.numDrawCalls,
gpuStats.numFlushes,
gpuStats.numVertsTransformed,
gpuStats.numTextures,
gpuStats.numVertexShaders,

View file

@ -54,6 +54,7 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight)
renderHeightFactor_ = (float)renderHeight / 272.0f;
shaderManager_ = &shaderManager;
TextureCache_Init();
InitTransform();
// Sanity check gstate
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
ERROR_LOG(G3D, "gstate has drifted out of sync!");
@ -113,6 +114,7 @@ void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format)
void GLES_GPU::CopyDisplayToOutput()
{
Flush();
if (!g_Config.bBufferedRendering)
return;

View file

@ -22,11 +22,11 @@
#include "../GPUInterface.h"
#include "Framebuffer.h"
#include "VertexDecoder.h"
#include "gfx_es2/fbo.h"
class ShaderManager;
class LinkedShader;
struct DecVtxFormat;
class GLES_GPU : public GPUInterface
{
@ -52,10 +52,11 @@ public:
private:
// TransformPipeline.cpp
void InitTransform();
void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead = 0);
//void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV);
void ApplyDrawState();
void Flush(int prim);
void Flush();
void UpdateViewportAndProjection();
void DrawBezier(int ucount, int vcount);
void DoBlockTransfer();

View file

@ -25,13 +25,14 @@ const u8 indexedPrimitiveType[7] = {
GE_PRIM_TRIANGLES,
GE_PRIM_TRIANGLES,
GE_PRIM_TRIANGLES,
GE_PRIM_TRIANGLES,
GE_PRIM_RECTANGLES,
};
void IndexGenerator::Reset() {
prim_ = -1;
inds_ = 0;
count_ = 0;
index_ = 0;
this->inds_ = indsBase_;
}
bool IndexGenerator::PrimCompatible(int prim) {
@ -40,12 +41,10 @@ bool IndexGenerator::PrimCompatible(int prim) {
return indexedPrimitiveType[prim] == indexedPrimitiveType[prim_];
}
void IndexGenerator::Start(u16 *inds, int baseIndex, int prim)
void IndexGenerator::Setup(u16 *inds)
{
count_ = 0;
this->inds_ = inds;
index_ = baseIndex;
prim_ = indexedPrimitiveType[prim];
this->indsBase_ = inds;
Reset();
}
void IndexGenerator::AddPoints(int numVerts)
@ -58,6 +57,7 @@ void IndexGenerator::AddPoints(int numVerts)
// ignore overflow verts
index_ += numVerts;
count_ += numVerts;
prim_ = GE_PRIM_POINTS;
}
void IndexGenerator::AddList(int numVerts)
@ -74,6 +74,7 @@ void IndexGenerator::AddList(int numVerts)
// ignore overflow verts
index_ += numVerts;
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
}
void IndexGenerator::AddStrip(int numVerts)
@ -89,6 +90,7 @@ void IndexGenerator::AddStrip(int numVerts)
}
index_ += numVerts;
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
}
void IndexGenerator::AddFan(int numVerts)
@ -102,6 +104,7 @@ void IndexGenerator::AddFan(int numVerts)
}
index_ += numVerts;
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
}
void IndexGenerator::TranslatePoints(int numVerts, const u8 *inds, int offset)
@ -112,6 +115,7 @@ void IndexGenerator::TranslatePoints(int numVerts, const u8 *inds, int offset)
}
index_ += numVerts;
count_ += numVerts;
prim_ = GE_PRIM_POINTS;
}
void IndexGenerator::TranslatePoints(int numVerts, const u16 *inds, int offset)
@ -122,6 +126,7 @@ void IndexGenerator::TranslatePoints(int numVerts, const u16 *inds, int offset)
}
index_ += numVerts;
count_ += numVerts;
prim_ = GE_PRIM_POINTS;
}
void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset)
@ -135,6 +140,7 @@ void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset)
}
index_ += numVerts;
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
}
void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset)
@ -150,6 +156,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset)
}
index_ += numVerts;
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
}
void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset)
@ -164,6 +171,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset)
}
index_ += numVerts;
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
}
void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset)
@ -177,6 +185,7 @@ void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset)
}
index_ += numVerts;
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
}
void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset)
@ -192,6 +201,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset)
}
index_ += numVerts;
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
}
void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset)
@ -206,6 +216,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset)
}
index_ += numVerts;
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
}
//Lines
@ -219,6 +230,7 @@ void IndexGenerator::AddLineList(int numVerts)
}
index_ += numVerts;
count_ += numLines * 2;
prim_ = GE_PRIM_LINES;
}
void IndexGenerator::AddLineStrip(int numVerts)
@ -231,6 +243,20 @@ void IndexGenerator::AddLineStrip(int numVerts)
}
index_ += numVerts;
count_ += numLines * 2;
prim_ = GE_PRIM_LINES;
}
void IndexGenerator::AddRectangles(int numVerts)
{
int numRects = numVerts / 2;
for (int i = 0; i < numRects; i++)
{
*inds_++ = index_ + i*2;
*inds_++ = index_ + i*2+1;
}
index_ += numVerts;
count_ += numRects * 2;
prim_ = GE_PRIM_RECTANGLES;
}
void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset)
@ -243,6 +269,7 @@ void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset)
}
index_ += numVerts;
count_ += numLines * 2;
prim_ = GE_PRIM_LINES;
}
void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset)
@ -255,6 +282,7 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset
}
index_ += numVerts;
count_ += numLines * 2;
prim_ = GE_PRIM_LINES;
}
void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset)
@ -267,6 +295,7 @@ void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset
}
index_ += numVerts;
count_ += numLines * 2;
prim_ = GE_PRIM_LINES;
}
void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offset)
@ -279,4 +308,31 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offse
}
index_ += numVerts;
count_ += numLines * 2;
}
prim_ = GE_PRIM_LINES;
}
void IndexGenerator::TranslateRectangles(int numVerts, const u8 *inds, int offset)
{
int numRects = numVerts / 2;
for (int i = 0; i < numRects; i++)
{
*inds_++ = index_ + i*2;
*inds_++ = index_ + i*2+1;
}
index_ += numVerts;
count_ += numRects * 2;
prim_ = GE_PRIM_RECTANGLES;
}
void IndexGenerator::TranslateRectangles(int numVerts, const u16 *inds, int offset)
{
int numRects = numVerts / 2;
for (int i = 0; i < numRects; i++)
{
*inds_++ = index_ + i*2;
*inds_++ = index_ + i*2+1;
}
index_ += numVerts;
count_ += numRects * 2;
prim_ = GE_PRIM_RECTANGLES;
}

View file

@ -24,9 +24,10 @@
class IndexGenerator
{
public:
void Setup(u16 *indexptr);
void Reset();
void Start(u16 *indexptr, int baseIndex, int prim);
bool PrimCompatible(int prim);
int Prim() const { return prim_; }
// Points (why index these? code simplicity)
void AddPoints(int numVerts);
@ -37,15 +38,21 @@ public:
// Lines
void AddLineList(int numVerts);
void AddLineStrip(int numVerts);
// Rectangles
void AddRectangles(int numVerts);
void TranslatePoints(int numVerts, const u8 *inds, int offset);
void TranslatePoints(int numVerts, const u16 *inds, int offset);
// Translates already indexed lists
void TranslateLineList(int numVerts, const u8 *inds, int offset);
void TranslateLineStrip(int numVerts, const u8 *inds, int offset);
void TranslateLineList(int numVerts, const u16 *inds, int offset);
void TranslateLineStrip(int numVerts, const u8 *inds, int offset);
void TranslateLineStrip(int numVerts, const u16 *inds, int offset);
void TranslateRectangles(int numVerts, const u8 *inds, int offset);
void TranslateRectangles(int numVerts, const u16 *inds, int offset);
void TranslateList(int numVerts, const u8 *inds, int offset);
void TranslateStrip(int numVerts, const u8 *inds, int offset);
void TranslateFan(int numVerts, const u8 *inds, int offset);
@ -56,7 +63,10 @@ public:
int MaxIndex() { return index_; }
int VertexCount() { return count_; }
bool Empty() { return index_ == 0; }
private:
u16 *indsBase_;
u16 *inds_;
int index_;
int count_;

View file

@ -43,7 +43,10 @@ const GLuint glprim[8] = {
};
u8 decoded[65536 * 32];
VertexDecoder dec;
uint16_t decIndex[65536]; // Unused
int numVerts;
int numInds;
IndexGenerator indexGen;
@ -265,7 +268,7 @@ static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decF
// Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for
// GL_TRIANGLES. Still need to sw transform to compute the extra two corners though.
void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex, float *customUV)
void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex)
{
/*
DEBUG_LOG(G3D, "View matrix:");
@ -418,10 +421,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount,
}
}
if (customUV) {
uv[0] = customUV[index * 2 + 0]*gstate_c.uScale + gstate_c.uOff;
uv[1] = customUV[index * 2 + 1]*gstate_c.vScale + gstate_c.vOff;
} else if (reader.hasUV()) {
if (reader.hasUV()) {
float ruv[2];
reader.ReadUV(ruv);
// Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights.
@ -575,22 +575,27 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount,
if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1);
}
void GLES_GPU::InitTransform() {
indexGen.Setup(decIndex);
}
void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead)
{
// For the future
if (!indexGen.PrimCompatible(prim))
Flush(prim);
Flush();
gpuStats.numDrawCalls++;
gpuStats.numVertsTransformed += vertexCount;
int indexLowerBound, indexUpperBound;
// First, decode the verts and apply morphing
VertexDecoder dec;
dec.SetVertexType(gstate.vertType);
dec.DecodeVerts(decoded, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound);
if (bytesRead)
*bytesRead = vertexCount * dec.VertexSize();
indexGen.Start(decIndex, 0, prim);
int indexType = (gstate.vertType & GE_VTYPE_IDX_MASK);
if (forceIndexType != -1) indexType = forceIndexType;
switch (indexType) {
@ -602,7 +607,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
case GE_PRIM_TRIANGLES: indexGen.AddList(vertexCount); break;
case GE_PRIM_TRIANGLE_STRIP: indexGen.AddStrip(vertexCount); break;
case GE_PRIM_TRIANGLE_FAN: indexGen.AddFan(vertexCount); break;
case GE_PRIM_RECTANGLES: indexGen.AddLineList(vertexCount); break; // Same
case GE_PRIM_RECTANGLES: indexGen.AddRectangles(vertexCount); break; // Same
}
break;
@ -614,7 +619,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
case GE_PRIM_TRIANGLES: indexGen.TranslateList(vertexCount, (const u8 *)inds, -indexLowerBound); break;
case GE_PRIM_TRIANGLE_STRIP: indexGen.TranslateStrip(vertexCount, (const u8 *)inds, -indexLowerBound); break;
case GE_PRIM_TRIANGLE_FAN: indexGen.TranslateFan(vertexCount, (const u8 *)inds, -indexLowerBound); break;
case GE_PRIM_RECTANGLES: indexGen.TranslateLineList(vertexCount, (const u8 *)inds, -indexLowerBound); break; // Same
case GE_PRIM_RECTANGLES: indexGen.TranslateRectangles(vertexCount, (const u8 *)inds, -indexLowerBound); break; // Same
}
break;
@ -626,12 +631,18 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
case GE_PRIM_TRIANGLES: indexGen.TranslateList(vertexCount, (const u16 *)inds, -indexLowerBound); break;
case GE_PRIM_TRIANGLE_STRIP: indexGen.TranslateStrip(vertexCount, (const u16 *)inds, -indexLowerBound); break;
case GE_PRIM_TRIANGLE_FAN: indexGen.TranslateFan(vertexCount, (const u16 *)inds, -indexLowerBound); break;
case GE_PRIM_RECTANGLES: indexGen.TranslateLineList(vertexCount, (const u16 *)inds, -indexLowerBound); break; // Same
case GE_PRIM_RECTANGLES: indexGen.TranslateRectangles(vertexCount, (const u16 *)inds, -indexLowerBound); break; // Same
}
break;
}
indexType = GE_VTYPE_IDX_16BIT;
Flush();
}
void GLES_GPU::Flush()
{
if (indexGen.Empty())
return;
// From here on out, the index type is ALWAYS 16-bit. Deal with it.
// And here we should return, having collected the morphed but untransformed vertices.
@ -654,12 +665,13 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
}
gstate_c.textureChanged = false;
}
gpuStats.numDrawCalls++;
gpuStats.numVertsTransformed += vertexCount;
gpuStats.numFlushes++;
// TODO: This should not be done on every drawcall, we should collect vertex data
// until critical state changes. That's when we draw (flush).
int prim = indexGen.Prim();
ApplyDrawState();
UpdateViewportAndProjection();
@ -670,11 +682,9 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
glDrawElements(glprim[prim], indexGen.VertexCount(), GL_UNSIGNED_SHORT, (GLvoid *)decIndex);
DesetupDecFmtForDraw(program, dec.GetDecVtxFmt());
} else {
SoftwareTransformAndDraw(prim, program, indexGen.VertexCount(), (void *)decIndex, indexType, dec.GetDecVtxFmt(),
indexGen.MaxIndex(), customUV);
SoftwareTransformAndDraw(prim, program, indexGen.VertexCount(), (void *)decIndex, GE_VTYPE_IDX_16BIT, dec.GetDecVtxFmt(),
indexGen.MaxIndex());
}
}
void GLES_GPU::Flush(int prim) {
// TODO
}
indexGen.Reset();
}

View file

@ -263,6 +263,7 @@ struct GPUStatistics
// Per frame statistics
int numDrawCalls;
int numFlushes;
int numVertsTransformed;
int numTextureSwitches;
int numShaderSwitches;