mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Use a VAO for all drawing, and VBOs throughout.
This commit is contained in:
parent
b71061b1ef
commit
164594b044
@ -506,11 +506,18 @@ void FramebufferManager::DrawPlainColor(u32 color) {
|
||||
|
||||
glsl_bind(program);
|
||||
glUniform4fv(plainColorLoc_, 1, col);
|
||||
glstate.arrayBuffer.unbind();
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices);
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
transformDraw_->BindBuffer(pos, sizeof(pos));
|
||||
transformDraw_->BindElementBuffer(indices, sizeof(indices));
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, 0);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0);
|
||||
} else {
|
||||
glstate.arrayBuffer.unbind();
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices);
|
||||
}
|
||||
glDisableVertexAttribArray(program->a_position);
|
||||
|
||||
glsl_unbind();
|
||||
@ -525,7 +532,7 @@ void FramebufferManager::DrawActiveTexture(GLuint texture, float x, float y, flo
|
||||
u0,v1,
|
||||
};
|
||||
|
||||
static const GLushort indices[4] = {0,1,3,2};
|
||||
static const GLubyte indices[4] = {0,1,3,2};
|
||||
|
||||
if (uvRotation != ROTATION_LOCKED_HORIZONTAL) {
|
||||
float temp[8];
|
||||
@ -582,13 +589,21 @@ void FramebufferManager::DrawActiveTexture(GLuint texture, float x, float y, flo
|
||||
glsl_bind(program);
|
||||
}
|
||||
|
||||
glstate.arrayBuffer.unbind();
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, texCoords);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices);
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
transformDraw_->BindBuffer(pos, sizeof(pos), texCoords, sizeof(texCoords));
|
||||
transformDraw_->BindElementBuffer(indices, sizeof(indices));
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, 0);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, (void *)sizeof(pos));
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0);
|
||||
} else {
|
||||
glstate.arrayBuffer.unbind();
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, texCoords);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices);
|
||||
}
|
||||
glDisableVertexAttribArray(program->a_position);
|
||||
glDisableVertexAttribArray(program->a_texcoord0);
|
||||
|
||||
|
@ -411,6 +411,7 @@ GLES_GPU::GLES_GPU()
|
||||
textureCache_.SetFramebufferManager(&framebufferManager_);
|
||||
textureCache_.SetDepalShaderCache(&depalShaderCache_);
|
||||
textureCache_.SetShaderManager(shaderManager_);
|
||||
textureCache_.SetTransformDrawEngine(&transformDraw_);
|
||||
fragmentTestCache_.SetTextureCache(&textureCache_);
|
||||
|
||||
// Sanity check gstate
|
||||
@ -452,6 +453,7 @@ GLES_GPU::GLES_GPU()
|
||||
|
||||
// Some of our defaults are different from hw defaults, let's assert them.
|
||||
// We restore each frame anyway, but here is convenient for tests.
|
||||
transformDraw_.RestoreVAO();
|
||||
glstate.Restore();
|
||||
}
|
||||
|
||||
@ -503,6 +505,9 @@ void GLES_GPU::CheckGPUFeatures() {
|
||||
if (gl_extensions.NV_framebuffer_blit) {
|
||||
features |= GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT;
|
||||
}
|
||||
if (gl_extensions.ARB_vertex_array_object) {
|
||||
features |= GPU_SUPPORTS_VAO;
|
||||
}
|
||||
|
||||
bool useCPU = false;
|
||||
if (!gl_extensions.IsGLES) {
|
||||
@ -693,6 +698,7 @@ void GLES_GPU::UpdateCmdInfo() {
|
||||
}
|
||||
|
||||
void GLES_GPU::ReapplyGfxStateInternal() {
|
||||
transformDraw_.RestoreVAO();
|
||||
glstate.Restore();
|
||||
GPUCommon::ReapplyGfxStateInternal();
|
||||
}
|
||||
@ -708,6 +714,7 @@ void GLES_GPU::BeginFrameInternal() {
|
||||
|
||||
textureCache_.StartFrame();
|
||||
transformDraw_.DecimateTrackedVertexArrays();
|
||||
transformDraw_.DecimateBuffers();
|
||||
depalShaderCache_.Decimate();
|
||||
fragmentTestCache_.Decimate();
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "GPU/GLES/FragmentShaderGenerator.h"
|
||||
#include "GPU/GLES/DepalettizeShader.h"
|
||||
#include "GPU/GLES/ShaderManager.h"
|
||||
#include "GPU/GLES/TransformPipeline.h"
|
||||
#include "GPU/Common/TextureDecoder.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Host.h"
|
||||
@ -1112,8 +1113,13 @@ void TextureCache::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuf
|
||||
glUseProgram(depal->program);
|
||||
|
||||
// Restore will rebind all of the state below.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
transformDraw_->BindBuffer(pos, sizeof(pos), uv, sizeof(uv));
|
||||
transformDraw_->BindElementBuffer(indices, sizeof(indices));
|
||||
} else {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
glEnableVertexAttribArray(depal->a_position);
|
||||
glEnableVertexAttribArray(depal->a_texcoord0);
|
||||
|
||||
@ -1136,9 +1142,15 @@ void TextureCache::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuf
|
||||
#endif
|
||||
glViewport(0, 0, framebuffer->renderWidth, framebuffer->renderHeight);
|
||||
|
||||
glVertexAttribPointer(depal->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos);
|
||||
glVertexAttribPointer(depal->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, uv);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices);
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
glVertexAttribPointer(depal->a_position, 3, GL_FLOAT, GL_FALSE, 12, 0);
|
||||
glVertexAttribPointer(depal->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, (void *)sizeof(pos));
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0);
|
||||
} else {
|
||||
glVertexAttribPointer(depal->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos);
|
||||
glVertexAttribPointer(depal->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, uv);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices);
|
||||
}
|
||||
glDisableVertexAttribArray(depal->a_position);
|
||||
glDisableVertexAttribArray(depal->a_texcoord0);
|
||||
|
||||
|
@ -32,6 +32,7 @@ struct VirtualFramebuffer;
|
||||
class FramebufferManager;
|
||||
class DepalShaderCache;
|
||||
class ShaderManager;
|
||||
class TransformDrawEngine;
|
||||
|
||||
enum FramebufferNotification {
|
||||
NOTIFY_FB_CREATED,
|
||||
@ -75,6 +76,9 @@ public:
|
||||
void SetShaderManager(ShaderManager *sm) {
|
||||
shaderManager_ = sm;
|
||||
}
|
||||
void SetTransformDrawEngine(TransformDrawEngine *td) {
|
||||
transformDraw_ = td;
|
||||
}
|
||||
|
||||
size_t NumLoadedTextures() const {
|
||||
return cache.size();
|
||||
@ -164,6 +168,7 @@ private:
|
||||
FramebufferManager *framebufferManager_;
|
||||
DepalShaderCache *depalShaderCache_;
|
||||
ShaderManager *shaderManager_;
|
||||
TransformDrawEngine *transformDraw_;
|
||||
};
|
||||
|
||||
GLenum getClutDestFormat(GEPaletteFormat format);
|
||||
|
@ -161,10 +161,27 @@ TransformDrawEngine::~TransformDrawEngine() {
|
||||
delete [] uvScale;
|
||||
}
|
||||
|
||||
void TransformDrawEngine::RestoreVAO() {
|
||||
if (sharedVao_ != 0) {
|
||||
glBindVertexArray(sharedVao_);
|
||||
} else if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
// Note: this is here because, InitDeviceObjects() is called before GPU_SUPPORTS_VAO is setup.
|
||||
// So, this establishes it if Supports() returns true and there isn't one yet.
|
||||
glGenVertexArrays(1, &sharedVao_);
|
||||
glBindVertexArray(sharedVao_);
|
||||
}
|
||||
}
|
||||
|
||||
void TransformDrawEngine::InitDeviceObjects() {
|
||||
if (bufferNameCache_.empty()) {
|
||||
bufferNameCache_.resize(VERTEXCACHE_NAME_CACHE_SIZE);
|
||||
glGenBuffers(VERTEXCACHE_NAME_CACHE_SIZE, &bufferNameCache_[0]);
|
||||
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
glGenVertexArrays(1, &sharedVao_);
|
||||
} else {
|
||||
sharedVao_ = 0;
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG(G3D, "Device objects already initialized!");
|
||||
}
|
||||
@ -176,6 +193,10 @@ void TransformDrawEngine::DestroyDeviceObjects() {
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
glDeleteBuffers((GLsizei)bufferNameCache_.size(), &bufferNameCache_[0]);
|
||||
bufferNameCache_.clear();
|
||||
|
||||
if (sharedVao_ != 0) {
|
||||
glDeleteVertexArrays(1, &sharedVao_);
|
||||
}
|
||||
}
|
||||
ClearTrackedVertexArrays();
|
||||
}
|
||||
@ -763,6 +784,13 @@ rotateVBO:
|
||||
prim = indexGen.Prim();
|
||||
}
|
||||
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO) && vbo == 0) {
|
||||
vbo = BindBuffer(decoded, dec_->GetDecVtxFmt().stride * indexGen.MaxIndex());
|
||||
if (useElements) {
|
||||
ebo = BindElementBuffer(decIndex, sizeof(short) * indexGen.VertexCount());
|
||||
}
|
||||
}
|
||||
|
||||
VERBOSE_LOG(G3D, "Flush prim %i! %i verts in one go", prim, vertexCount);
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
if (gstate.isModeThrough()) {
|
||||
@ -818,13 +846,25 @@ rotateVBO:
|
||||
const int vertexSize = sizeof(transformed[0]);
|
||||
|
||||
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
glstate.arrayBuffer.unbind();
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
glVertexAttribPointer(ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer);
|
||||
|
||||
const uint8_t *bufferStart = (const uint8_t *)drawBuffer;
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
bufferStart = 0;
|
||||
BindBuffer(drawBuffer, vertexSize * maxIndex);
|
||||
if (drawIndexed) {
|
||||
BindElementBuffer(inds, sizeof(short) * numTrans);
|
||||
inds = 0;
|
||||
}
|
||||
} else {
|
||||
glstate.arrayBuffer.unbind();
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
}
|
||||
|
||||
glVertexAttribPointer(ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, bufferStart);
|
||||
int attrMask = program->attrMask;
|
||||
if (attrMask & (1 << ATTR_TEXCOORD)) glVertexAttribPointer(ATTR_TEXCOORD, doTextureProjection ? 3 : 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + offsetof(TransformedVertex, u));
|
||||
if (attrMask & (1 << ATTR_COLOR0)) glVertexAttribPointer(ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + offsetof(TransformedVertex, color0));
|
||||
if (attrMask & (1 << ATTR_COLOR1)) glVertexAttribPointer(ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + offsetof(TransformedVertex, color1));
|
||||
if (attrMask & (1 << ATTR_TEXCOORD)) glVertexAttribPointer(ATTR_TEXCOORD, doTextureProjection ? 3 : 2, GL_FLOAT, GL_FALSE, vertexSize, bufferStart + offsetof(TransformedVertex, u));
|
||||
if (attrMask & (1 << ATTR_COLOR0)) glVertexAttribPointer(ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, bufferStart + offsetof(TransformedVertex, color0));
|
||||
if (attrMask & (1 << ATTR_COLOR1)) glVertexAttribPointer(ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, bufferStart + offsetof(TransformedVertex, color1));
|
||||
if (drawIndexed) {
|
||||
glDrawElements(glprim[prim], numTrans, GL_UNSIGNED_SHORT, inds);
|
||||
} else {
|
||||
@ -912,6 +952,46 @@ void TransformDrawEngine::Resized() {
|
||||
}
|
||||
}
|
||||
|
||||
GLuint TransformDrawEngine::BindBuffer(const void *p, size_t sz) {
|
||||
// Get a new buffer each time we need one.
|
||||
GLuint buf = AllocateBuffer();
|
||||
glstate.arrayBuffer.bind(buf);
|
||||
|
||||
// These aren't used more than once per frame, so let's use GL_STREAM_DRAW.
|
||||
glBufferData(GL_ARRAY_BUFFER, sz, p, GL_STREAM_DRAW);
|
||||
buffersThisFrame_.push_back(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
GLuint TransformDrawEngine::BindBuffer(const void *p1, size_t sz1, const void *p2, size_t sz2) {
|
||||
GLuint buf = AllocateBuffer();
|
||||
glstate.arrayBuffer.bind(buf);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sz1 + sz2, nullptr, GL_STREAM_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sz1, p1);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, sz1, sz2, p2);
|
||||
buffersThisFrame_.push_back(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
GLuint TransformDrawEngine::BindElementBuffer(const void *p, size_t sz) {
|
||||
GLuint buf = AllocateBuffer();
|
||||
glstate.elementArrayBuffer.bind(buf);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sz, p, GL_STREAM_DRAW);
|
||||
buffersThisFrame_.push_back(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void TransformDrawEngine::DecimateBuffers() {
|
||||
for (GLuint buf : buffersThisFrame_) {
|
||||
FreeBuffer(buf);
|
||||
}
|
||||
buffersThisFrame_.clear();
|
||||
}
|
||||
|
||||
bool TransformDrawEngine::IsCodePtrVertexDecoder(const u8 *ptr) const {
|
||||
return decJitCache_->IsInSpace(ptr);
|
||||
}
|
||||
|
@ -127,6 +127,7 @@ public:
|
||||
void SetFragmentTestCache(FragmentTestCache *testCache) {
|
||||
fragmentTestCache_ = testCache;
|
||||
}
|
||||
void RestoreVAO();
|
||||
void InitDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
void GLLost() override;
|
||||
@ -188,6 +189,11 @@ public:
|
||||
SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead);
|
||||
}
|
||||
|
||||
GLuint BindBuffer(const void *p, size_t sz);
|
||||
GLuint BindBuffer(const void *p1, size_t sz1, const void *p2, size_t sz2);
|
||||
GLuint BindElementBuffer(const void *p, size_t sz);
|
||||
void DecimateBuffers();
|
||||
|
||||
private:
|
||||
void DecodeVerts();
|
||||
void DecodeVertsStep();
|
||||
@ -232,6 +238,8 @@ private:
|
||||
// Vertex buffer objects
|
||||
// Element buffer objects
|
||||
std::vector<GLuint> bufferNameCache_;
|
||||
std::vector<GLuint> buffersThisFrame_;
|
||||
GLuint sharedVao_;
|
||||
|
||||
// Other
|
||||
ShaderManager *shaderManager_;
|
||||
|
@ -454,6 +454,7 @@ enum {
|
||||
GPU_SUPPORTS_BLEND_MINMAX = FLAG_BIT(4),
|
||||
GPU_SUPPORTS_LOGIC_OP = FLAG_BIT(5),
|
||||
GPU_USE_DEPTH_RANGE_HACK = FLAG_BIT(6),
|
||||
GPU_SUPPORTS_VAO = FLAG_BIT(18),
|
||||
GPU_SUPPORTS_ANY_COPY_IMAGE = FLAG_BIT(19),
|
||||
GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH = FLAG_BIT(20),
|
||||
GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT = FLAG_BIT(22),
|
||||
|
Loading…
Reference in New Issue
Block a user