From 03b9492f086e63bd96af8219fc4ab0d9d8d94f9e Mon Sep 17 00:00:00 2001 From: xebra Date: Sat, 21 Jul 2018 00:18:34 +0900 Subject: [PATCH] [spline/bezier]Sharing textures to avoid heavily textures creation/deletion in one frame. At least, it occurs about 1000 and very slow down in Pursuit Force. --- GPU/GLES/DrawEngineGLES.cpp | 40 +++++++++++++++++------------ GPU/GLES/DrawEngineGLES.h | 1 + ext/native/thin3d/GLQueueRunner.cpp | 36 ++++++++++++-------------- ext/native/thin3d/GLQueueRunner.h | 26 +++++++++---------- ext/native/thin3d/GLRenderManager.h | 25 +++++++++--------- 5 files changed, 67 insertions(+), 61 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 5dde8b1eb9..749dae8780 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -669,13 +669,14 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p // Removed the 1D texture support, it's unlikely to be relevant for performance. // Control Points - if (data_tex[0]) - renderManager_->DeleteTexture(data_tex[0]); - data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D); - renderManager_->TextureImage(data_tex[0], 0, size, 3, GL_RGBA32F, GL_RGBA, GL_FLOAT, (u8 *)nullptr, GLRAllocType::NONE, false); - renderManager_->FinalizeTexture(data_tex[0], 0, false); + if (prevSize < size) { + prevSize = size; + if (!data_tex[0]) + data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D); + renderManager_->TextureImage(data_tex[0], 0, size, 3, GL_RGBA32F, GL_RGBA, GL_FLOAT, nullptr, GLRAllocType::NONE, false); + renderManager_->FinalizeTexture(data_tex[0], 0, false); + } renderManager_->BindTexture(TEX_SLOT_SPLINE_POINTS, data_tex[0]); - // Position renderManager_->TextureSubImage(data_tex[0], 0, 0, 0, size, 1, GL_RGBA, GL_FLOAT, (u8 *)pos, GLRAllocType::NEW); // Texcoord @@ -686,20 +687,26 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p renderManager_->TextureSubImage(data_tex[0], 0, 0, 2, size, 1, GL_RGBA, GL_FLOAT, (u8 *)col, GLRAllocType::NEW); // Weight U - if (data_tex[1]) - renderManager_->DeleteTexture(data_tex[1]); - data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D); - renderManager_->TextureImage(data_tex[1], 0, weights.size_u * 2, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, (uint8_t *)weights.u, GLRAllocType::NONE, false); - renderManager_->FinalizeTexture(data_tex[1], 0, false); + if (prevSizeWU < weights.size_u) { + prevSizeWU = weights.size_u; + if (!data_tex[1]) + data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D); + renderManager_->TextureImage(data_tex[1], 0, weights.size_u * 2, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, nullptr, GLRAllocType::NONE, false); + renderManager_->FinalizeTexture(data_tex[1], 0, false); + } renderManager_->BindTexture(TEX_SLOT_SPLINE_WEIGHTS_U, data_tex[1]); + renderManager_->TextureSubImage(data_tex[1], 0, 0, 0, weights.size_u * 2, 1, GL_RGBA, GL_FLOAT, (u8 *)weights.u, GLRAllocType::NONE); // Weight V - if (data_tex[2]) - renderManager_->DeleteTexture(data_tex[2]); - data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D); - renderManager_->TextureImage(data_tex[2], 0, weights.size_v * 2, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, (uint8_t *)weights.v, GLRAllocType::NONE, false); - renderManager_->FinalizeTexture(data_tex[2], 0, false); + if (prevSizeWV < weights.size_v) { + prevSizeWV = weights.size_v; + if (!data_tex[2]) + data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D); + renderManager_->TextureImage(data_tex[2], 0, weights.size_v * 2, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, nullptr, GLRAllocType::NONE, false); + renderManager_->FinalizeTexture(data_tex[2], 0, false); + } renderManager_->BindTexture(TEX_SLOT_SPLINE_WEIGHTS_V, data_tex[2]); + renderManager_->TextureSubImage(data_tex[2], 0, 0, 0, weights.size_v * 2, 1, GL_RGBA, GL_FLOAT, (u8 *)weights.v, GLRAllocType::NONE); } void TessellationDataTransferGLES::EndFrame() { @@ -709,4 +716,5 @@ void TessellationDataTransferGLES::EndFrame() { data_tex[i] = nullptr; } } + prevSize = prevSizeWU = prevSizeWV = 0; } diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 52605374d9..9870adacd2 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -113,6 +113,7 @@ public: class TessellationDataTransferGLES : public TessellationDataTransfer { private: GLRTexture *data_tex[3]{}; + int prevSize = 0, prevSizeWU = 0, prevSizeWV = 0; GLRenderManager *renderManager_; public: TessellationDataTransferGLES(GLRenderManager *renderManager) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index d12ba97d49..5db058262a 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -328,26 +328,6 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps, bool ski CHECK_GL_ERROR_IF_DEBUG(); break; } - case GLRInitStepType::TEXTURE_SUBIMAGE: - { - GLRTexture *tex = step.texture_subimage.texture; - CHECK_GL_ERROR_IF_DEBUG(); - if (boundTexture != tex->texture) { - glBindTexture(tex->target, tex->texture); - boundTexture = tex->texture; - } - if (!step.texture_subimage.data) - Crash(); - // For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage. - glTexSubImage2D(tex->target, step.texture_subimage.level, step.texture_subimage.x, step.texture_subimage.y, step.texture_subimage.width, step.texture_subimage.height, step.texture_subimage.format, step.texture_subimage.type, step.texture_subimage.data); - if (step.texture_subimage.allocType == GLRAllocType::ALIGNED) { - FreeAlignedMemory(step.texture_subimage.data); - } else if (step.texture_subimage.allocType == GLRAllocType::NEW) { - delete[] step.texture_subimage.data; - } - CHECK_GL_ERROR_IF_DEBUG(); - break; - } case GLRInitStepType::TEXTURE_FINALIZE: { CHECK_GL_ERROR_IF_DEBUG(); @@ -1033,6 +1013,22 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; } + case GLRRenderCommand::TEXTURE_SUBIMAGE: + { + GLRTexture *tex = c.texture_subimage.texture; + // TODO: Need bind? + if (!c.texture_subimage.data) + Crash(); + // For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage. + glTexSubImage2D(tex->target, c.texture_subimage.level, c.texture_subimage.x, c.texture_subimage.y, c.texture_subimage.width, c.texture_subimage.height, c.texture_subimage.format, c.texture_subimage.type, c.texture_subimage.data); + if (c.texture_subimage.allocType == GLRAllocType::ALIGNED) { + FreeAlignedMemory(c.texture_subimage.data); + } else if (c.texture_subimage.allocType == GLRAllocType::NEW) { + delete[] c.texture_subimage.data; + } + CHECK_GL_ERROR_IF_DEBUG(); + break; + } case GLRRenderCommand::RASTER: if (c.raster.cullEnable) { if (!cullEnabled) { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 03420f6689..b7a1586d59 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -58,6 +58,7 @@ enum class GLRRenderCommand : uint8_t { DRAW, DRAW_INDEXED, PUSH_CONSTANTS, + TEXTURE_SUBIMAGE, }; // TODO: Bloated since the biggest struct decides the size. Will need something more efficient (separate structs with shared @@ -139,6 +140,18 @@ struct GLRRenderData { int slot; GLRTexture *texture; } texture; + struct { + GLRTexture *texture; + GLenum format; + GLenum type; + int level; + int x; + int y; + int width; + int height; + GLRAllocType allocType; + uint8_t *data; // owned, delete[]-d + } texture_subimage; struct { int slot; GLRFramebuffer *framebuffer; @@ -197,7 +210,6 @@ enum class GLRInitStepType : uint8_t { CREATE_FRAMEBUFFER, TEXTURE_IMAGE, - TEXTURE_SUBIMAGE, TEXTURE_FINALIZE, BUFFER_SUBDATA, }; @@ -252,18 +264,6 @@ struct GLRInitStep { bool linearFilter; uint8_t *data; // owned, delete[]-d } texture_image; - struct { - GLRTexture *texture; - GLenum format; - GLenum type; - int level; - int x; - int y; - int width; - int height; - GLRAllocType allocType; - uint8_t *data; // owned, delete[]-d - } texture_subimage; struct { GLRTexture *texture; int maxLevel; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 12bfea9dd7..9cc4ca4f7d 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -531,18 +531,19 @@ public: } void TextureSubImage(GLRTexture *texture, int level, int x, int y, int width, int height, GLenum format, GLenum type, uint8_t *data, GLRAllocType allocType = GLRAllocType::NEW) { - GLRInitStep step{ GLRInitStepType::TEXTURE_SUBIMAGE }; - step.texture_subimage.texture = texture; - step.texture_subimage.data = data; - step.texture_subimage.format = format; - step.texture_subimage.type = type; - step.texture_subimage.level = level; - step.texture_subimage.x = x; - step.texture_subimage.y = y; - step.texture_subimage.width = width; - step.texture_subimage.height = height; - step.texture_subimage.allocType = allocType; - initSteps_.push_back(step); + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData _data{ GLRRenderCommand::TEXTURE_SUBIMAGE }; + _data.texture_subimage.texture = texture; + _data.texture_subimage.data = data; + _data.texture_subimage.format = format; + _data.texture_subimage.type = type; + _data.texture_subimage.level = level; + _data.texture_subimage.x = x; + _data.texture_subimage.y = y; + _data.texture_subimage.width = width; + _data.texture_subimage.height = height; + _data.texture_subimage.allocType = allocType; + curRenderStep_->commands.push_back(_data); } void FinalizeTexture(GLRTexture *texture, int maxLevels, bool genMips) {