Optimize texture application in draw calls.
Gather all bound textures and samplers first and then pass them to
generateSwizzles and applyTextures to reduce redundant get calls.
BUG=260069
Change-Id: I5b10dddb01a6bfd756c58b76218838cfc1fd59b6
Reviewed-on: https://chromium-review.googlesource.com/199343
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 8f8666e..7242a11 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -2500,113 +2500,87 @@
programBinary->applyUniforms();
}
-bool Context::getCurrentTextureAndSamplerState(ProgramBinary *programBinary, SamplerType type, int index, Texture **outTexture,
- TextureType *outTextureType, SamplerState *outSampler)
+size_t Context::getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures,
+ TextureType *outTextureTypes, SamplerState *outSamplers)
{
- int textureUnit = programBinary->getSamplerMapping(type, index); // OpenGL texture image unit index
-
- if (textureUnit != -1)
+ size_t samplerRange = programBinary->getUsedSamplerRange(type);
+ for (size_t i = 0; i < samplerRange; i++)
{
- TextureType textureType = programBinary->getSamplerTextureType(type, index);
- Texture *texture = getSamplerTexture(textureUnit, textureType);
-
- SamplerState samplerState;
- texture->getSamplerState(&samplerState);
-
- if (mState.samplers[textureUnit] != 0)
+ outTextureTypes[i] = programBinary->getSamplerTextureType(type, i);
+ GLint textureUnit = programBinary->getSamplerMapping(type, i); // OpenGL texture image unit index
+ if (textureUnit != -1)
{
- Sampler *samplerObject = getSampler(mState.samplers[textureUnit]);
- samplerObject->getState(&samplerState);
+ outTextures[i] = getSamplerTexture(textureUnit, outTextureTypes[i]);
+ outTextures[i]->getSamplerState(&outSamplers[i]);
+ if (mState.samplers[textureUnit] != 0)
+ {
+ Sampler *samplerObject = getSampler(mState.samplers[textureUnit]);
+ samplerObject->getState(&outSamplers[i]);
+ }
}
-
- *outTexture = texture;
- *outTextureType = textureType;
- *outSampler = samplerState;
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void Context::generateSwizzles(ProgramBinary *programBinary)
-{
- generateSwizzles(programBinary, SAMPLER_PIXEL);
-
- if (mSupportsVertexTexture)
- {
- generateSwizzles(programBinary, SAMPLER_VERTEX);
- }
-}
-
-void Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type)
-{
- // Range of Direct3D samplers of given sampler type
- int samplerRange = programBinary->getUsedSamplerRange(type);
- for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
- {
- Texture *texture = NULL;
- TextureType textureType;
- SamplerState samplerState;
- if (getCurrentTextureAndSamplerState(programBinary, type, samplerIndex, &texture, &textureType, &samplerState) && texture->isSwizzled())
+ else
{
- mRenderer->generateSwizzle(texture);
+ outTextures[i] = NULL;
}
}
+
+ return samplerRange;
}
-// Applies the textures and sampler states to the Direct3D 9 device
-void Context::applyTextures(ProgramBinary *programBinary)
+void Context::generateSwizzles(Texture *textures[], size_t count)
{
- applyTextures(programBinary, SAMPLER_PIXEL);
-
- if (mSupportsVertexTexture)
+ for (size_t i = 0; i < count; i++)
{
- applyTextures(programBinary, SAMPLER_VERTEX);
+ if (textures[i] && textures[i]->isSwizzled())
+ {
+ mRenderer->generateSwizzle(textures[i]);
+ }
}
}
// For each Direct3D sampler of either the pixel or vertex stage,
// looks up the corresponding OpenGL texture image unit and texture type,
// and sets the texture and its addressing/filtering state (or NULL when inactive).
-void Context::applyTextures(ProgramBinary *programBinary, SamplerType type)
+void Context::applyTextures(SamplerType shaderType, Texture *textures[], TextureType *textureTypes, SamplerState *samplers,
+ size_t textureCount, const FramebufferTextureSerialArray& framebufferSerials,
+ size_t framebufferSerialCount)
{
- FramebufferTextureSerialSet boundFramebufferTextures = getBoundFramebufferTextureSerials();
-
// Range of Direct3D samplers of given sampler type
- int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits();
- int samplerRange = programBinary->getUsedSamplerRange(type);
+ size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS
+ : mRenderer->getMaxVertexTextureImageUnits();
- for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+ for (size_t samplerIndex = 0; samplerIndex < textureCount; samplerIndex++)
{
- Texture *texture = NULL;
- TextureType textureType;
- SamplerState samplerState;
- if (getCurrentTextureAndSamplerState(programBinary, type, samplerIndex, &texture, &textureType, &samplerState))
+ Texture *texture = textures[samplerIndex];
+ const SamplerState &sampler = samplers[samplerIndex];
+ TextureType textureType = textureTypes[samplerIndex];
+
+ if (texture)
{
- if (texture->isSamplerComplete(samplerState) &&
- boundFramebufferTextures.find(texture->getTextureSerial()) == boundFramebufferTextures.end())
+ // TODO: std::binary_search may become unavailable using older versions of GCC
+ if (texture->isSamplerComplete(sampler) &&
+ !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial()))
{
- mRenderer->setSamplerState(type, samplerIndex, samplerState);
- mRenderer->setTexture(type, samplerIndex, texture);
+ mRenderer->setSamplerState(shaderType, samplerIndex, sampler);
+ mRenderer->setTexture(shaderType, samplerIndex, texture);
texture->resetDirty();
}
else
{
- mRenderer->setTexture(type, samplerIndex, getIncompleteTexture(textureType));
+ Texture *incompleteTexture = getIncompleteTexture(textureType);
+ mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture);
+ incompleteTexture->resetDirty();
}
}
else
{
- mRenderer->setTexture(type, samplerIndex, NULL);
+ mRenderer->setTexture(shaderType, samplerIndex, NULL);
}
}
- for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
+ for (size_t samplerIndex = textureCount; samplerIndex < samplerCount; samplerIndex++)
{
- mRenderer->setTexture(type, samplerIndex, NULL);
+ mRenderer->setTexture(shaderType, samplerIndex, NULL);
}
}
@@ -2954,7 +2928,18 @@
ProgramBinary *programBinary = getCurrentProgramBinary();
programBinary->applyUniforms();
- generateSwizzles(programBinary);
+ Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ SamplerState vsSamplers[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ size_t vsTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers);
+
+ Texture *psTextures[MAX_TEXTURE_IMAGE_UNITS];
+ TextureType psTextureTypes[MAX_TEXTURE_IMAGE_UNITS];
+ SamplerState psSamplers[MAX_TEXTURE_IMAGE_UNITS];
+ size_t psTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers);
+
+ generateSwizzles(vsTextures, vsTextureCount);
+ generateSwizzles(psTextures, psTextureCount);
if (!mRenderer->applyPrimitiveType(mode, count))
{
@@ -2977,7 +2962,12 @@
bool transformFeedbackActive = applyTransformFeedbackBuffers();
applyShaders(programBinary, transformFeedbackActive);
- applyTextures(programBinary);
+
+ FramebufferTextureSerialArray frameBufferSerials;
+ size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials);
+
+ applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount);
+ applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount);
if (!applyUniformBuffers())
{
@@ -3016,7 +3006,18 @@
ProgramBinary *programBinary = getCurrentProgramBinary();
programBinary->applyUniforms();
- generateSwizzles(programBinary);
+ Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ SamplerState vsSamplers[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ size_t vsTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers);
+
+ Texture *psTextures[MAX_TEXTURE_IMAGE_UNITS];
+ TextureType psTextureTypes[MAX_TEXTURE_IMAGE_UNITS];
+ SamplerState psSamplers[MAX_TEXTURE_IMAGE_UNITS];
+ size_t psTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers);
+
+ generateSwizzles(vsTextures, vsTextureCount);
+ generateSwizzles(psTextures, psTextureCount);
if (!mRenderer->applyPrimitiveType(mode, count))
{
@@ -3050,7 +3051,12 @@
ASSERT(!transformFeedbackActive);
applyShaders(programBinary, transformFeedbackActive);
- applyTextures(programBinary);
+
+ FramebufferTextureSerialArray frameBufferSerials;
+ size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials);
+
+ applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount);
+ applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount);
if (!applyUniformBuffers())
{
@@ -3928,9 +3934,9 @@
return mRendererString;
}
-Context::FramebufferTextureSerialSet Context::getBoundFramebufferTextureSerials()
+size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray)
{
- FramebufferTextureSerialSet set;
+ size_t serialCount = 0;
Framebuffer *drawFramebuffer = getDrawFramebuffer();
for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
@@ -3938,17 +3944,19 @@
Renderbuffer *renderBuffer = drawFramebuffer->getColorbuffer(i);
if (renderBuffer && renderBuffer->getTextureSerial() != 0)
{
- set.insert(renderBuffer->getTextureSerial());
+ (*outSerialArray)[serialCount++] = renderBuffer->getTextureSerial();
}
}
Renderbuffer *depthStencilBuffer = drawFramebuffer->getDepthOrStencilbuffer();
if (depthStencilBuffer && depthStencilBuffer->getTextureSerial() != 0)
{
- set.insert(depthStencilBuffer->getTextureSerial());
+ (*outSerialArray)[serialCount++] = depthStencilBuffer->getTextureSerial();
}
- return set;
+ std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount);
+
+ return serialCount;
}
void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,