Commit 43b00426 by Geoff Lang

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/199343Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 45c785d3
...@@ -2500,113 +2500,87 @@ void Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackA ...@@ -2500,113 +2500,87 @@ void Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackA
programBinary->applyUniforms(); programBinary->applyUniforms();
} }
bool Context::getCurrentTextureAndSamplerState(ProgramBinary *programBinary, SamplerType type, int index, Texture **outTexture, size_t Context::getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures,
TextureType *outTextureType, SamplerState *outSampler) TextureType *outTextureTypes, SamplerState *outSamplers)
{ {
int textureUnit = programBinary->getSamplerMapping(type, index); // OpenGL texture image unit index size_t samplerRange = programBinary->getUsedSamplerRange(type);
for (size_t i = 0; i < samplerRange; i++)
if (textureUnit != -1)
{ {
TextureType textureType = programBinary->getSamplerTextureType(type, index); outTextureTypes[i] = programBinary->getSamplerTextureType(type, i);
Texture *texture = getSamplerTexture(textureUnit, textureType); GLint textureUnit = programBinary->getSamplerMapping(type, i); // OpenGL texture image unit index
if (textureUnit != -1)
SamplerState samplerState;
texture->getSamplerState(&samplerState);
if (mState.samplers[textureUnit] != 0)
{ {
Sampler *samplerObject = getSampler(mState.samplers[textureUnit]); outTextures[i] = getSamplerTexture(textureUnit, outTextureTypes[i]);
samplerObject->getState(&samplerState); outTextures[i]->getSamplerState(&outSamplers[i]);
if (mState.samplers[textureUnit] != 0)
{
Sampler *samplerObject = getSampler(mState.samplers[textureUnit]);
samplerObject->getState(&outSamplers[i]);
}
}
else
{
outTextures[i] = NULL;
} }
*outTexture = texture;
*outTextureType = textureType;
*outSampler = samplerState;
return true;
}
else
{
return false;
} }
}
void Context::generateSwizzles(ProgramBinary *programBinary)
{
generateSwizzles(programBinary, SAMPLER_PIXEL);
if (mSupportsVertexTexture) return samplerRange;
{
generateSwizzles(programBinary, SAMPLER_VERTEX);
}
} }
void Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type) void Context::generateSwizzles(Texture *textures[], size_t count)
{ {
// Range of Direct3D samplers of given sampler type for (size_t i = 0; i < count; i++)
int samplerRange = programBinary->getUsedSamplerRange(type);
for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
{ {
Texture *texture = NULL; if (textures[i] && textures[i]->isSwizzled())
TextureType textureType;
SamplerState samplerState;
if (getCurrentTextureAndSamplerState(programBinary, type, samplerIndex, &texture, &textureType, &samplerState) && texture->isSwizzled())
{ {
mRenderer->generateSwizzle(texture); mRenderer->generateSwizzle(textures[i]);
} }
} }
} }
// Applies the textures and sampler states to the Direct3D 9 device
void Context::applyTextures(ProgramBinary *programBinary)
{
applyTextures(programBinary, SAMPLER_PIXEL);
if (mSupportsVertexTexture)
{
applyTextures(programBinary, SAMPLER_VERTEX);
}
}
// For each Direct3D sampler of either the pixel or vertex stage, // For each Direct3D sampler of either the pixel or vertex stage,
// looks up the corresponding OpenGL texture image unit and texture type, // looks up the corresponding OpenGL texture image unit and texture type,
// and sets the texture and its addressing/filtering state (or NULL when inactive). // 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 // Range of Direct3D samplers of given sampler type
int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits(); size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS
int samplerRange = programBinary->getUsedSamplerRange(type); : mRenderer->getMaxVertexTextureImageUnits();
for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) for (size_t samplerIndex = 0; samplerIndex < textureCount; samplerIndex++)
{ {
Texture *texture = NULL; Texture *texture = textures[samplerIndex];
TextureType textureType; const SamplerState &sampler = samplers[samplerIndex];
SamplerState samplerState; TextureType textureType = textureTypes[samplerIndex];
if (getCurrentTextureAndSamplerState(programBinary, type, samplerIndex, &texture, &textureType, &samplerState))
if (texture)
{ {
if (texture->isSamplerComplete(samplerState) && // TODO: std::binary_search may become unavailable using older versions of GCC
boundFramebufferTextures.find(texture->getTextureSerial()) == boundFramebufferTextures.end()) if (texture->isSamplerComplete(sampler) &&
!std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial()))
{ {
mRenderer->setSamplerState(type, samplerIndex, samplerState); mRenderer->setSamplerState(shaderType, samplerIndex, sampler);
mRenderer->setTexture(type, samplerIndex, texture); mRenderer->setTexture(shaderType, samplerIndex, texture);
texture->resetDirty(); texture->resetDirty();
} }
else else
{ {
mRenderer->setTexture(type, samplerIndex, getIncompleteTexture(textureType)); Texture *incompleteTexture = getIncompleteTexture(textureType);
mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture);
incompleteTexture->resetDirty();
} }
} }
else 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 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan ...@@ -2954,7 +2928,18 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
ProgramBinary *programBinary = getCurrentProgramBinary(); ProgramBinary *programBinary = getCurrentProgramBinary();
programBinary->applyUniforms(); 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)) if (!mRenderer->applyPrimitiveType(mode, count))
{ {
...@@ -2977,7 +2962,12 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan ...@@ -2977,7 +2962,12 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
bool transformFeedbackActive = applyTransformFeedbackBuffers(); bool transformFeedbackActive = applyTransformFeedbackBuffers();
applyShaders(programBinary, 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()) if (!applyUniformBuffers())
{ {
...@@ -3016,7 +3006,18 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid ...@@ -3016,7 +3006,18 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid
ProgramBinary *programBinary = getCurrentProgramBinary(); ProgramBinary *programBinary = getCurrentProgramBinary();
programBinary->applyUniforms(); 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)) if (!mRenderer->applyPrimitiveType(mode, count))
{ {
...@@ -3050,7 +3051,12 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid ...@@ -3050,7 +3051,12 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid
ASSERT(!transformFeedbackActive); ASSERT(!transformFeedbackActive);
applyShaders(programBinary, 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()) if (!applyUniformBuffers())
{ {
...@@ -3928,9 +3934,9 @@ const char *Context::getRendererString() const ...@@ -3928,9 +3934,9 @@ const char *Context::getRendererString() const
return mRendererString; return mRendererString;
} }
Context::FramebufferTextureSerialSet Context::getBoundFramebufferTextureSerials() size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray)
{ {
FramebufferTextureSerialSet set; size_t serialCount = 0;
Framebuffer *drawFramebuffer = getDrawFramebuffer(); Framebuffer *drawFramebuffer = getDrawFramebuffer();
for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
...@@ -3938,17 +3944,19 @@ Context::FramebufferTextureSerialSet Context::getBoundFramebufferTextureSerials( ...@@ -3938,17 +3944,19 @@ Context::FramebufferTextureSerialSet Context::getBoundFramebufferTextureSerials(
Renderbuffer *renderBuffer = drawFramebuffer->getColorbuffer(i); Renderbuffer *renderBuffer = drawFramebuffer->getColorbuffer(i);
if (renderBuffer && renderBuffer->getTextureSerial() != 0) if (renderBuffer && renderBuffer->getTextureSerial() != 0)
{ {
set.insert(renderBuffer->getTextureSerial()); (*outSerialArray)[serialCount++] = renderBuffer->getTextureSerial();
} }
} }
Renderbuffer *depthStencilBuffer = drawFramebuffer->getDepthOrStencilbuffer(); Renderbuffer *depthStencilBuffer = drawFramebuffer->getDepthOrStencilbuffer();
if (depthStencilBuffer && depthStencilBuffer->getTextureSerial() != 0) 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, void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <set> #include <set>
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <array>
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/RefCountObject.h" #include "common/RefCountObject.h"
...@@ -464,11 +465,15 @@ class Context ...@@ -464,11 +465,15 @@ class Context
private: private:
DISALLOW_COPY_AND_ASSIGN(Context); DISALLOW_COPY_AND_ASSIGN(Context);
// TODO: std::array may become unavailable using older versions of GCC
typedef std::array<unsigned int, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray;
bool applyRenderTarget(GLenum drawMode, bool ignoreViewport); bool applyRenderTarget(GLenum drawMode, bool ignoreViewport);
void applyState(GLenum drawMode); void applyState(GLenum drawMode);
void applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive); void applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive);
void applyTextures(ProgramBinary *programBinary); void applyTextures(SamplerType shaderType, Texture *textures[], TextureType *textureTypes, SamplerState *samplers,
void applyTextures(ProgramBinary *programBinary, SamplerType type); size_t textureCount, const FramebufferTextureSerialArray& framebufferSerials,
size_t framebufferSerialCount);
bool applyUniformBuffers(); bool applyUniformBuffers();
bool applyTransformFeedbackBuffers(); bool applyTransformFeedbackBuffers();
void markTransformFeedbackUsage(); void markTransformFeedbackUsage();
...@@ -481,10 +486,9 @@ class Context ...@@ -481,10 +486,9 @@ class Context
void detachTransformFeedback(GLuint transformFeedback); void detachTransformFeedback(GLuint transformFeedback);
void detachSampler(GLuint sampler); void detachSampler(GLuint sampler);
void generateSwizzles(ProgramBinary *programBinary); void generateSwizzles(Texture *textures[], size_t count);
void generateSwizzles(ProgramBinary *programBinary, SamplerType type); size_t getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures,
bool getCurrentTextureAndSamplerState(ProgramBinary *programBinary, SamplerType type, int index, Texture **outTexture, TextureType *outTextureTypes, SamplerState *outSamplers);
TextureType *outTextureType, SamplerState *outSampler);
Texture *getIncompleteTexture(TextureType type); Texture *getIncompleteTexture(TextureType type);
bool skipDraw(GLenum drawMode); bool skipDraw(GLenum drawMode);
...@@ -492,8 +496,7 @@ class Context ...@@ -492,8 +496,7 @@ class Context
void initExtensionString(); void initExtensionString();
void initRendererString(); void initRendererString();
typedef std::set<unsigned> FramebufferTextureSerialSet; size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray);
FramebufferTextureSerialSet getBoundFramebufferTextureSerials();
rx::Renderer *const mRenderer; rx::Renderer *const mRenderer;
......
...@@ -23,6 +23,7 @@ enum ...@@ -23,6 +23,7 @@ enum
IMPLEMENTATION_MAX_VARYING_VECTORS = 32, IMPLEMENTATION_MAX_VARYING_VECTORS = 32,
IMPLEMENTATION_MAX_DRAW_BUFFERS = 8, IMPLEMENTATION_MAX_DRAW_BUFFERS = 8,
IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS = IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, // 2 extra for depth and/or stencil buffers
IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16,
IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS = 16, IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS = 16,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment