[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.

This commit is contained in:
xebra 2018-07-21 00:18:34 +09:00
parent 453e274fbe
commit 03b9492f08
5 changed files with 67 additions and 61 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -328,26 +328,6 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &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) {

View File

@ -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;

View File

@ -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) {