Commit 16e28fd3 by Jamie Madill Committed by Commit Bot

More micro-optimization for draw call validation.

Mostly inlining checks on the hot draw call path. Slight increase in draw call validation performance. (Up to 13%) Bug: angleproject:2747 Change-Id: I34c4d7f412c3bca5e559e9bfb5689c0618bb7536 Reviewed-on: https://chromium-review.googlesource.com/1171506Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 526a6f6b
......@@ -359,6 +359,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
mWebGLContext(GetWebGLContext(attribs)),
mExtensionsEnabled(GetExtensionsEnabled(attribs, mWebGLContext)),
mMemoryProgramCache(memoryProgramCache),
mStateCache(this),
mVertexArrayObserverBinding(this, kVertexArraySubjectIndex),
mDrawFramebufferObserverBinding(this, kDrawFramebufferSubjectIndex),
mReadFramebufferObserverBinding(this, kReadFramebufferSubjectIndex),
......@@ -7790,12 +7791,13 @@ GLenum ErrorSet::popError()
}
// StateCache implementation.
StateCache::StateCache()
StateCache::StateCache(Context *context)
: mCachedHasAnyEnabledClientAttrib(false),
mCachedNonInstancedVertexElementLimit(0),
mCachedInstancedVertexElementLimit(0),
mCachedBasicDrawStatesError(kInvalidPointer)
{
updateValidDrawModes(context);
}
StateCache::~StateCache() = default;
......
......@@ -86,7 +86,7 @@ class ErrorSet : angle::NonCopyable
class StateCache final : angle::NonCopyable
{
public:
StateCache();
StateCache(Context *context);
~StateCache();
// Places that can trigger updateActiveAttribsMask:
......
......@@ -79,17 +79,11 @@ bool DifferenceCanOverflow(GLint a, GLint b)
return !checkedA.IsValid();
}
bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
bool ValidateDrawAttribsImpl(Context *context, GLint primcount, GLint maxVertex)
{
// If we're drawing zero vertices, we have enough data.
ASSERT(primcount > 0);
if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
(primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
{
return true;
}
// An overflow can happen when adding the offset. Check against a special constant.
if (context->getStateCache().getNonInstancedVertexElementLimit() ==
VertexAttribute::kIntegerOverflow ||
......@@ -106,6 +100,19 @@ bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
return false;
}
ANGLE_INLINE bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
{
if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
(primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
{
return true;
}
else
{
return ValidateDrawAttribsImpl(context, primcount, maxVertex);
}
}
bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
{
switch (type)
......@@ -2752,7 +2759,7 @@ const char *ValidateDrawStates(Context *context)
return nullptr;
}
bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
bool ValidateDrawMode(Context *context, PrimitiveMode mode)
{
const Extensions &extensions = context->getExtensions();
......@@ -2782,14 +2789,43 @@ bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
return false;
}
// If we are running GLES1, there is no current program.
if (context->getClientVersion() >= Version(2, 0))
{
const State &state = context->getGLState();
Program *program = state.getProgram();
ASSERT(program);
// Do geometry shader specific validations
if (program->hasLinkedShaderStage(ShaderType::Geometry))
{
if (!IsCompatibleDrawModeWithGeometryShader(
mode, program->getGeometryShaderInputPrimitiveType()))
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(),
IncompatibleDrawModeAgainstGeometryShader);
return false;
}
}
}
return true;
}
bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
{
if (!context->getStateCache().isValidDrawMode(mode))
{
return ValidateDrawMode(context, mode);
}
if (count < 0)
{
ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
return false;
}
const State &state = context->getGLState();
intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
if (drawStatesError)
{
......@@ -2804,25 +2840,6 @@ bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
return false;
}
// If we are running GLES1, there is no current program.
if (context->getClientVersion() >= Version(2, 0))
{
Program *program = state.getProgram();
ASSERT(program);
// Do geometry shader specific validations
if (program->hasLinkedShaderStage(ShaderType::Geometry))
{
if (!IsCompatibleDrawModeWithGeometryShader(
mode, program->getGeometryShaderInputPrimitiveType()))
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(),
IncompatibleDrawModeAgainstGeometryShader);
return false;
}
}
}
return true;
}
......@@ -2838,6 +2855,12 @@ bool ValidateDrawArraysCommon(Context *context,
return false;
}
if (count < 0)
{
ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
return false;
}
const State &state = context->getGLState();
TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
if (curTransformFeedback && curTransformFeedback->isActive() &&
......@@ -2857,8 +2880,22 @@ bool ValidateDrawArraysCommon(Context *context,
}
}
if (!ValidateDrawBase(context, mode, count))
if (!context->getStateCache().isValidDrawMode(mode))
{
return ValidateDrawMode(context, mode);
}
intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
if (drawStatesError)
{
const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
// All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
// Incomplete.
GLenum errorCode =
(errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
: GL_INVALID_OPERATION);
context->handleError(Error(errorCode, errorMessage));
return false;
}
......
......@@ -5823,11 +5823,6 @@ bool ValidateViewport(Context *context, GLint x, GLint y, GLsizei width, GLsizei
return true;
}
bool ValidateDrawArrays(Context *context, PrimitiveMode mode, GLint first, GLsizei count)
{
return ValidateDrawArraysCommon(context, mode, first, count, 1);
}
bool ValidateDrawElements(Context *context,
PrimitiveMode mode,
GLsizei count,
......
......@@ -10,6 +10,7 @@
#define LIBANGLE_VALIDATION_ES2_H_
#include "common/PackedEnums.h"
#include "libANGLE/validationES.h"
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
......@@ -582,7 +583,10 @@ bool ValidateDrawElements(Context *context,
GLenum type,
const void *indices);
bool ValidateDrawArrays(Context *context, PrimitiveMode mode, GLint first, GLsizei count);
inline bool ValidateDrawArrays(Context *context, PrimitiveMode mode, GLint first, GLsizei count)
{
return ValidateDrawArraysCommon(context, mode, first, count, 1);
}
bool ValidateGetFramebufferAttachmentParameteriv(Context *context,
GLenum target,
......
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