Use parameter cache to skip passing IndexRange.
For DrawElements et al., we can use a simple design to store
entry point parameters and compute index ranges lazily. This allows
us to compute the index range outside of the validation layer.
Fixing this will let us implement a few things, such as the no error
extension. It will also allow auto-generation of the entry points,
since we won't have to have special cases for certain entry
points. It will also help fix the syncState layering problem. Now the
cached parameter helper (which is owned by the Context) can make the
impl layer calls, instead of the validation layer calling the impl
directly.
We use a small array in Context to gather parameters in a generic
way without reallocation on call. We also check type safety by storing
a type info struct which can handle inheritance between type classes.
Optional variables for the cache determine when to re-compute values.
The intent with gatherParams is to call this in every entry point, and
have in most cases be a no-op. In some cases like for IndexRange, we
store some parameters for later use. The inheritance scheme enables
auto-generation of the entry points by keeping signatures similar.
BUG=angleproject:747
Change-Id: I871e99e1334cf6e61ef8da62fde3ced094903f8a
Reviewed-on: https://chromium-review.googlesource.com/474119
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index c118d8a..a85f29e 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -1820,13 +1820,12 @@
return (width > 0 && height > 0);
}
-bool ValidateDrawElementsInstancedBase(Context *context,
+bool ValidateDrawElementsInstancedBase(ValidationContext *context,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut)
+ GLsizei primcount)
{
if (primcount < 0)
{
@@ -1834,7 +1833,7 @@
return false;
}
- if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
+ if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
{
return false;
}
@@ -1864,7 +1863,7 @@
return (primcount > 0);
}
-bool ValidateDrawInstancedANGLEAndWebGL(Context *context)
+bool ValidateDrawInstancedANGLEAndWebGL(ValidationContext *context)
{
// Verify there is at least one active attribute with a divisor of zero
const State &state = context->getGLState();
@@ -3955,13 +3954,12 @@
return true;
}
-bool ValidateDrawElements(ValidationContext *context,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut)
+bool ValidateDrawElementsCommon(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei primcount)
{
if (!ValidateDrawElementsBase(context, type))
return false;
@@ -4067,60 +4065,49 @@
return false;
}
- // Use max index to validate if our vertex buffers are large enough for the pull.
+ // Use the parameter buffer to retrieve and cache the index range.
// TODO: offer fast path, with disabled index validation.
// TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
- if (elementArrayBuffer)
+ const auto ¶ms = context->getParams<HasIndexRange>();
+ const auto &indexRangeOpt = params.getIndexRange();
+ if (!indexRangeOpt.valid())
{
- uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
- Error error =
- elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
- state.isPrimitiveRestartEnabled(), indexRangeOut);
- if (error.isError())
- {
- context->handleError(error);
- return false;
- }
- }
- else
- {
- *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
+ // Unexpected error.
+ return false;
}
// If we use an index greater than our maximum supported index range, return an error.
// The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
// return an error if possible here.
- if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
+ if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
{
context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
return false;
}
- if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
- static_cast<GLint>(indexRangeOut->vertexCount())))
+ if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
+ static_cast<GLint>(indexRangeOpt.value().vertexCount())))
{
return false;
}
// No op if there are no real indices in the index data (all are primitive restart).
- return (indexRangeOut->vertexIndexCount > 0);
+ return (indexRangeOpt.value().vertexIndexCount > 0);
}
-bool ValidateDrawElementsInstanced(Context *context,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut)
+bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei primcount)
{
if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
{
return false;
}
- return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
- indexRangeOut);
+ return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
}
bool ValidateDrawElementsInstancedANGLE(Context *context,
@@ -4128,16 +4115,14 @@
GLsizei count,
GLenum type,
const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut)
+ GLsizei primcount)
{
if (!ValidateDrawInstancedANGLEAndWebGL(context))
{
return false;
}
- return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
- indexRangeOut);
+ return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
}
bool ValidateFramebufferTextureBase(Context *context,