Commit d9671226 by Jiajia Qin Committed by Commit Bot

Implement ES3.1 glDraw*Indirect entry points for OpenGL

BUG=angleproject:1595 TEST=dEQP-GLES31.functional.draw_indirect.* Change-Id: I82f5d0864e70d6e7abdccf5f10330ddfa099ec62 Reviewed-on: https://chromium-review.googlesource.com/417250 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 89c21ea8
...@@ -1670,6 +1670,18 @@ Error Context::drawRangeElements(GLenum mode, ...@@ -1670,6 +1670,18 @@ Error Context::drawRangeElements(GLenum mode,
return mImplementation->drawRangeElements(mode, start, end, count, type, indices, indexRange); return mImplementation->drawRangeElements(mode, start, end, count, type, indices, indexRange);
} }
void Context::drawArraysIndirect(GLenum mode, const GLvoid *indirect)
{
syncRendererState();
handleError(mImplementation->drawArraysIndirect(mode, indirect));
}
void Context::drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
{
syncRendererState();
handleError(mImplementation->drawElementsIndirect(mode, type, indirect));
}
Error Context::flush() Error Context::flush()
{ {
return mImplementation->flush(); return mImplementation->flush();
......
...@@ -310,6 +310,8 @@ class Context final : public ValidationContext ...@@ -310,6 +310,8 @@ class Context final : public ValidationContext
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
const IndexRange &indexRange); const IndexRange &indexRange);
void drawArraysIndirect(GLenum mode, const GLvoid *indirect);
void drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect);
void blitFramebuffer(GLint srcX0, void blitFramebuffer(GLint srcX0,
GLint srcY0, GLint srcY0,
......
...@@ -61,6 +61,9 @@ class ContextImpl : public GLImplFactory ...@@ -61,6 +61,9 @@ class ContextImpl : public GLImplFactory
const GLvoid *indices, const GLvoid *indices,
const gl::IndexRange &indexRange) = 0; const gl::IndexRange &indexRange) = 0;
virtual gl::Error drawArraysIndirect(GLenum mode, const GLvoid *indirect) = 0;
virtual gl::Error drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) = 0;
// CHROMIUM_path_rendering path drawing methods. // CHROMIUM_path_rendering path drawing methods.
virtual void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask); virtual void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask);
virtual void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask); virtual void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask);
......
...@@ -192,6 +192,18 @@ gl::Error Context11::drawRangeElements(GLenum mode, ...@@ -192,6 +192,18 @@ gl::Error Context11::drawRangeElements(GLenum mode,
return mRenderer->genericDrawElements(this, mode, count, type, indices, 0, indexRange); return mRenderer->genericDrawElements(this, mode, count, type, indices, 0, indexRange);
} }
gl::Error Context11::drawArraysIndirect(GLenum mode, const GLvoid *indirect)
{
UNIMPLEMENTED();
return gl::InternalError() << "DrawArraysIndirect hasn't been implemented for D3D11 backend.";
}
gl::Error Context11::drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
{
UNIMPLEMENTED();
return gl::InternalError() << "DrawElementsIndirect hasn't been implemented for D3D11 backend.";
}
GLenum Context11::getResetStatus() GLenum Context11::getResetStatus()
{ {
return mRenderer->getResetStatus(); return mRenderer->getResetStatus();
......
...@@ -88,6 +88,8 @@ class Context11 : public ContextImpl ...@@ -88,6 +88,8 @@ class Context11 : public ContextImpl
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
const gl::IndexRange &indexRange) override; const gl::IndexRange &indexRange) override;
gl::Error drawArraysIndirect(GLenum mode, const GLvoid *indirect) override;
gl::Error drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) override;
// Device loss // Device loss
GLenum getResetStatus() override; GLenum getResetStatus() override;
......
...@@ -178,6 +178,18 @@ gl::Error Context9::drawRangeElements(GLenum mode, ...@@ -178,6 +178,18 @@ gl::Error Context9::drawRangeElements(GLenum mode,
return mRenderer->genericDrawElements(this, mode, count, type, indices, 0, indexRange); return mRenderer->genericDrawElements(this, mode, count, type, indices, 0, indexRange);
} }
gl::Error Context9::drawArraysIndirect(GLenum mode, const GLvoid *indirect)
{
UNREACHABLE();
return gl::InternalError() << "D3D9 doesn't support ES 3.1 DrawArraysIndirect API";
}
gl::Error Context9::drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
{
UNREACHABLE();
return gl::InternalError() << "D3D9 doesn't support ES 3.1 DrawElementsIndirect API";
}
GLenum Context9::getResetStatus() GLenum Context9::getResetStatus()
{ {
return mRenderer->getResetStatus(); return mRenderer->getResetStatus();
......
...@@ -88,6 +88,8 @@ class Context9 : public ContextImpl ...@@ -88,6 +88,8 @@ class Context9 : public ContextImpl
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
const gl::IndexRange &indexRange) override; const gl::IndexRange &indexRange) override;
gl::Error drawArraysIndirect(GLenum mode, const GLvoid *indirect) override;
gl::Error drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) override;
// Device loss // Device loss
GLenum getResetStatus() override; GLenum getResetStatus() override;
......
...@@ -194,6 +194,16 @@ gl::Error ContextGL::drawRangeElements(GLenum mode, ...@@ -194,6 +194,16 @@ gl::Error ContextGL::drawRangeElements(GLenum mode,
return mRenderer->drawRangeElements(mState, mode, start, end, count, type, indices, indexRange); return mRenderer->drawRangeElements(mState, mode, start, end, count, type, indices, indexRange);
} }
gl::Error ContextGL::drawArraysIndirect(GLenum mode, const GLvoid *indirect)
{
return mRenderer->drawArraysIndirect(mState, mode, indirect);
}
gl::Error ContextGL::drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
{
return mRenderer->drawElementsIndirect(mState, mode, type, indirect);
}
void ContextGL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) void ContextGL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
{ {
mRenderer->stencilFillPath(mState, path, fillMode, mask); mRenderer->stencilFillPath(mState, path, fillMode, mask);
......
...@@ -96,6 +96,8 @@ class ContextGL : public ContextImpl ...@@ -96,6 +96,8 @@ class ContextGL : public ContextImpl
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
const gl::IndexRange &indexRange) override; const gl::IndexRange &indexRange) override;
gl::Error drawArraysIndirect(GLenum mode, const GLvoid *indirect) override;
gl::Error drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) override;
// CHROMIUM_path_rendering implementation // CHROMIUM_path_rendering implementation
void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override; void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override;
......
...@@ -274,6 +274,33 @@ gl::Error RendererGL::drawRangeElements(const gl::ContextState &data, ...@@ -274,6 +274,33 @@ gl::Error RendererGL::drawRangeElements(const gl::ContextState &data,
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
gl::Error RendererGL::drawArraysIndirect(const gl::ContextState &data,
GLenum mode,
const GLvoid *indirect)
{
ANGLE_TRY(mStateManager->setDrawIndirectState(data, GL_NONE));
if (!mSkipDrawCalls)
{
mFunctions->drawArraysIndirect(mode, indirect);
}
return gl::NoError();
}
gl::Error RendererGL::drawElementsIndirect(const gl::ContextState &data,
GLenum mode,
GLenum type,
const GLvoid *indirect)
{
ANGLE_TRY(mStateManager->setDrawIndirectState(data, type));
if (!mSkipDrawCalls)
{
mFunctions->drawElementsIndirect(mode, type, indirect);
}
return gl::NoError();
}
void RendererGL::stencilFillPath(const gl::ContextState &state, void RendererGL::stencilFillPath(const gl::ContextState &state,
const gl::Path *path, const gl::Path *path,
GLenum fillMode, GLenum fillMode,
......
...@@ -77,6 +77,11 @@ class RendererGL : angle::NonCopyable ...@@ -77,6 +77,11 @@ class RendererGL : angle::NonCopyable
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
const gl::IndexRange &indexRange); const gl::IndexRange &indexRange);
gl::Error drawArraysIndirect(const gl::ContextState &data, GLenum mode, const GLvoid *indirect);
gl::Error drawElementsIndirect(const gl::ContextState &data,
GLenum mode,
GLenum type,
const GLvoid *indirect);
// CHROMIUM_path_rendering implementation // CHROMIUM_path_rendering implementation
void stencilFillPath(const gl::ContextState &state, void stencilFillPath(const gl::ContextState &state,
......
...@@ -662,6 +662,25 @@ gl::Error StateManagerGL::setDrawElementsState(const gl::ContextState &data, ...@@ -662,6 +662,25 @@ gl::Error StateManagerGL::setDrawElementsState(const gl::ContextState &data,
return setGenericDrawState(data); return setGenericDrawState(data);
} }
gl::Error StateManagerGL::setDrawIndirectState(const gl::ContextState &data, GLenum type)
{
const gl::State &state = data.getState();
if (type != GL_NONE)
{
const gl::VertexArray *vao = state.getVertexArray();
const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
ANGLE_TRY(vaoGL->syncElementArrayState());
}
gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
ASSERT(drawIndirectBuffer);
const BufferGL *bufferGL = GetImplAs<BufferGL>(drawIndirectBuffer);
bindBuffer(GL_DRAW_INDIRECT_BUFFER, bufferGL->getBufferID());
return setGenericDrawState(data);
}
void StateManagerGL::pauseTransformFeedback() void StateManagerGL::pauseTransformFeedback()
{ {
if (mPrevDrawTransformFeedback != nullptr) if (mPrevDrawTransformFeedback != nullptr)
......
...@@ -149,6 +149,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -149,6 +149,7 @@ class StateManagerGL final : angle::NonCopyable
const GLvoid *indices, const GLvoid *indices,
GLsizei instanceCount, GLsizei instanceCount,
const GLvoid **outIndices); const GLvoid **outIndices);
gl::Error setDrawIndirectState(const gl::ContextState &data, GLenum type);
void pauseTransformFeedback(); void pauseTransformFeedback();
void pauseAllQueries(); void pauseAllQueries();
......
...@@ -97,6 +97,20 @@ gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeA ...@@ -97,6 +97,20 @@ gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeA
primitiveRestartEnabled, outIndices); primitiveRestartEnabled, outIndices);
} }
gl::Error VertexArrayGL::syncElementArrayState() const
{
gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
ASSERT(elementArrayBuffer);
if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
{
const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
mAppliedElementArrayBuffer.set(elementArrayBuffer);
}
return gl::NoError();
}
gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask, gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
GLint first, GLint first,
GLsizei count, GLsizei count,
...@@ -141,7 +155,7 @@ gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttribute ...@@ -141,7 +155,7 @@ gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttribute
return Error(GL_NO_ERROR); return Error(GL_NO_ERROR);
} }
Error VertexArrayGL::syncIndexData(GLsizei count, gl::Error VertexArrayGL::syncIndexData(GLsizei count,
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
bool primitiveRestartEnabled, bool primitiveRestartEnabled,
......
...@@ -36,6 +36,7 @@ class VertexArrayGL : public VertexArrayImpl ...@@ -36,6 +36,7 @@ class VertexArrayGL : public VertexArrayImpl
GLsizei instanceCount, GLsizei instanceCount,
bool primitiveRestartEnabled, bool primitiveRestartEnabled,
const GLvoid **outIndices) const; const GLvoid **outIndices) const;
gl::Error syncElementArrayState() const;
GLuint getVertexArrayID() const; GLuint getVertexArrayID() const;
GLuint getAppliedElementArrayBufferID() const; GLuint getAppliedElementArrayBufferID() const;
......
...@@ -101,6 +101,16 @@ gl::Error ContextNULL::drawRangeElements(GLenum mode, ...@@ -101,6 +101,16 @@ gl::Error ContextNULL::drawRangeElements(GLenum mode,
return gl::NoError(); return gl::NoError();
} }
gl::Error ContextNULL::drawArraysIndirect(GLenum mode, const GLvoid *indirect)
{
return gl::NoError();
}
gl::Error ContextNULL::drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
{
return gl::NoError();
}
void ContextNULL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) void ContextNULL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
{ {
} }
......
...@@ -52,6 +52,8 @@ class ContextNULL : public ContextImpl ...@@ -52,6 +52,8 @@ class ContextNULL : public ContextImpl
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
const gl::IndexRange &indexRange) override; const gl::IndexRange &indexRange) override;
gl::Error drawArraysIndirect(GLenum mode, const GLvoid *indirect) override;
gl::Error drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) override;
// CHROMIUM_path_rendering path drawing methods. // CHROMIUM_path_rendering path drawing methods.
void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override; void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override;
......
...@@ -106,6 +106,19 @@ gl::Error ContextVk::drawRangeElements(GLenum mode, ...@@ -106,6 +106,19 @@ gl::Error ContextVk::drawRangeElements(GLenum mode,
return gl::Error(GL_INVALID_OPERATION); return gl::Error(GL_INVALID_OPERATION);
} }
gl::Error ContextVk::drawArraysIndirect(GLenum mode, const GLvoid *indirect)
{
UNIMPLEMENTED();
return gl::InternalError() << "DrawArraysIndirect hasn't been implemented for vulkan backend.";
}
gl::Error ContextVk::drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
{
UNIMPLEMENTED();
return gl::InternalError()
<< "DrawElementsIndirect hasn't been implemented for vulkan backend.";
}
GLenum ContextVk::getResetStatus() GLenum ContextVk::getResetStatus()
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
......
...@@ -53,6 +53,8 @@ class ContextVk : public ContextImpl ...@@ -53,6 +53,8 @@ class ContextVk : public ContextImpl
GLenum type, GLenum type,
const GLvoid *indices, const GLvoid *indices,
const gl::IndexRange &indexRange) override; const gl::IndexRange &indexRange) override;
gl::Error drawArraysIndirect(GLenum mode, const GLvoid *indirect) override;
gl::Error drawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) override;
// Device loss // Device loss
GLenum getResetStatus() override; GLenum getResetStatus() override;
......
...@@ -3051,10 +3051,7 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context, ...@@ -3051,10 +3051,7 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
return true; return true;
} }
static bool ValidateDrawBase(ValidationContext *context, bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
GLenum mode,
GLsizei count,
GLsizei primcount)
{ {
switch (mode) switch (mode)
{ {
...@@ -3191,7 +3188,7 @@ bool ValidateDrawArrays(ValidationContext *context, ...@@ -3191,7 +3188,7 @@ bool ValidateDrawArrays(ValidationContext *context,
return false; return false;
} }
if (!ValidateDrawBase(context, mode, count, primcount)) if (!ValidateDrawBase(context, mode, count))
{ {
return false; return false;
} }
...@@ -3272,13 +3269,7 @@ bool ValidateDrawArraysInstancedANGLE(Context *context, ...@@ -3272,13 +3269,7 @@ bool ValidateDrawArraysInstancedANGLE(Context *context,
return ValidateDrawArraysInstanced(context, mode, first, count, primcount); return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
} }
bool ValidateDrawElements(ValidationContext *context, bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei primcount,
IndexRange *indexRangeOut)
{ {
switch (type) switch (type)
{ {
...@@ -3310,6 +3301,22 @@ bool ValidateDrawElements(ValidationContext *context, ...@@ -3310,6 +3301,22 @@ bool ValidateDrawElements(ValidationContext *context,
return false; return false;
} }
return true;
}
bool ValidateDrawElements(ValidationContext *context,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei primcount,
IndexRange *indexRangeOut)
{
if (!ValidateDrawElementsBase(context, type))
return false;
const State &state = context->getGLState();
// Check for mapped buffers // Check for mapped buffers
if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER)) if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
{ {
...@@ -3361,7 +3368,7 @@ bool ValidateDrawElements(ValidationContext *context, ...@@ -3361,7 +3368,7 @@ bool ValidateDrawElements(ValidationContext *context,
return false; return false;
} }
if (!ValidateDrawBase(context, mode, count, primcount)) if (!ValidateDrawBase(context, mode, count))
{ {
return false; return false;
} }
......
...@@ -221,6 +221,7 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context, ...@@ -221,6 +221,7 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
GLint border, GLint border,
Format *textureFormatOut); Format *textureFormatOut);
bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count);
bool ValidateDrawArrays(ValidationContext *context, bool ValidateDrawArrays(ValidationContext *context,
GLenum mode, GLenum mode,
GLint first, GLint first,
...@@ -229,6 +230,7 @@ bool ValidateDrawArrays(ValidationContext *context, ...@@ -229,6 +230,7 @@ bool ValidateDrawArrays(ValidationContext *context,
bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
bool ValidateDrawElementsBase(ValidationContext *context, GLenum type);
bool ValidateDrawElements(ValidationContext *context, bool ValidateDrawElements(ValidationContext *context,
GLenum mode, GLenum mode,
GLsizei count, GLsizei count,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/validationES.h" #include "libANGLE/validationES.h"
#include "libANGLE/validationES3.h" #include "libANGLE/validationES3.h"
#include "libANGLE/VertexArray.h"
using namespace angle; using namespace angle;
...@@ -64,4 +65,119 @@ bool ValidateGetBooleani_vRobustANGLE(Context *context, ...@@ -64,4 +65,119 @@ bool ValidateGetBooleani_vRobustANGLE(Context *context,
return true; return true;
} }
bool ValidateDrawIndirectBase(Context *context, GLenum mode, const GLvoid *indirect)
{
if (context->getClientVersion() < ES_3_1)
{
context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
return false;
}
// Here the third parameter 1 is only to pass the count validation.
if (!ValidateDrawBase(context, mode, 1))
{
return false;
}
const State &state = context->getGLState();
// An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
// DRAW_INDIRECT_BUFFER or to any enabled vertex array.
if (!state.getVertexArrayId())
{
context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to VERTEX_ARRAY_BINDING"));
return false;
}
gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
if (!drawIndirectBuffer)
{
context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to DRAW_INDIRECT_BUFFER"));
return false;
}
// An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
// machine units, of uint.
GLint64 offset = reinterpret_cast<GLint64>(indirect);
if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
{
context->handleError(
Error(GL_INVALID_VALUE,
"indirect is not a multiple of the size, in basic machine units, of uint"));
return false;
}
return true;
}
bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const GLvoid *indirect)
{
const State &state = context->getGLState();
gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
if (curTransformFeedback && curTransformFeedback->isActive() &&
!curTransformFeedback->isPaused())
{
// An INVALID_OPERATION error is generated if transform feedback is active and not paused.
context->handleError(
Error(GL_INVALID_OPERATION, "transform feedback is active and not paused."));
return false;
}
if (!ValidateDrawIndirectBase(context, mode, indirect))
return false;
gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
// In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
// which's size is 4 * sizeof(uint).
auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
if (!checkedSum.IsValid() ||
checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
{
context->handleError(
Error(GL_INVALID_OPERATION,
"the command would source data beyond the end of the buffer object."));
return false;
}
return true;
}
bool ValidateDrawElementsIndirect(Context *context,
GLenum mode,
GLenum type,
const GLvoid *indirect)
{
if (!ValidateDrawElementsBase(context, type))
return false;
const State &state = context->getGLState();
const VertexArray *vao = state.getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
if (!elementArrayBuffer)
{
context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to ELEMENT_ARRAY_BUFFER"));
return false;
}
if (!ValidateDrawIndirectBase(context, mode, indirect))
return false;
gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
// In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
// which's size is 5 * sizeof(uint).
auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
if (!checkedSum.IsValid() ||
checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
{
context->handleError(
Error(GL_INVALID_OPERATION,
"the command would source data beyond the end of the buffer object."));
return false;
}
return true;
}
} // namespace gl } // namespace gl
...@@ -23,6 +23,13 @@ bool ValidateGetBooleani_vRobustANGLE(Context *context, ...@@ -23,6 +23,13 @@ bool ValidateGetBooleani_vRobustANGLE(Context *context,
GLsizei *length, GLsizei *length,
GLboolean *data); GLboolean *data);
bool ValidateDrawIndirectBase(Context *context, GLenum mode, const GLvoid *indirect);
bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const GLvoid *indirect);
bool ValidateDrawElementsIndirect(Context *context,
GLenum mode,
GLenum type,
const GLvoid *indirect);
} // namespace gl } // namespace gl
#endif // LIBANGLE_VALIDATION_ES31_H_ #endif // LIBANGLE_VALIDATION_ES31_H_
...@@ -55,11 +55,12 @@ void GL_APIENTRY DrawArraysIndirect(GLenum mode, const void *indirect) ...@@ -55,11 +55,12 @@ void GL_APIENTRY DrawArraysIndirect(GLenum mode, const void *indirect)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!context->skipValidation()) if (!context->skipValidation() && !ValidateDrawArraysIndirect(context, mode, indirect))
{ {
context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented")); return;
} }
UNIMPLEMENTED();
context->drawArraysIndirect(mode, indirect);
} }
} }
...@@ -69,11 +70,13 @@ void GL_APIENTRY DrawElementsIndirect(GLenum mode, GLenum type, const void *indi ...@@ -69,11 +70,13 @@ void GL_APIENTRY DrawElementsIndirect(GLenum mode, GLenum type, const void *indi
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!context->skipValidation()) if (!context->skipValidation() &&
!ValidateDrawElementsIndirect(context, mode, type, indirect))
{ {
context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented")); return;
} }
UNIMPLEMENTED();
context->drawElementsIndirect(mode, type, indirect);
} }
} }
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
// 91532 MAC NVIDIA 0x0640 : tex_image_and_sub_image_2d_with_video = PASS FAIL // 91532 MAC NVIDIA 0x0640 : tex_image_and_sub_image_2d_with_video = PASS FAIL
// Crashing Tests // Crashing Tests
1659 NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.random.0 = SKIP
1659 NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.random.10 = SKIP
1659 NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.random.15 = SKIP
1659 NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.random.18 = SKIP
1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.image.image2d.vertex_binding_array = SKIP 1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.image.image2d.vertex_binding_array = SKIP
1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.image.image2d.vertex_binding_max_array = SKIP 1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.image.image2d.vertex_binding_max_array = SKIP
1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.image.image2d.fragment_binding_array = SKIP 1442 OPENGL D3D11 : dEQP-GLES31.functional.layout_binding.image.image2d.fragment_binding_array = SKIP
...@@ -46,6 +50,7 @@ ...@@ -46,6 +50,7 @@
1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP 1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP
// D3D11 Failing Tests // D3D11 Failing Tests
1442 D3D11 : dEQP-GLES31.functional.draw_indirect.* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_color_texture_samples_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_color_texture_samples_* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_depth_texture_samples_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_depth_texture_samples_* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_integer_samples_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_integer_samples_* = FAIL
...@@ -99,6 +104,10 @@ ...@@ -99,6 +104,10 @@
1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_9 = SKIP 1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_9 = SKIP
1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_10 = SKIP 1442 D3D11 : dEQP-GLES31.functional.debug.error_groups.case_10 = SKIP
// OPENGL Failing Tests
1663 OPENGL : dEQP-GLES31.functional.draw_indirect.compute_interop.* = FAIL
1665 WIN NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.negative.command_offset_not_in_buffer_unsigned32_wrap = FAIL
// OpenGL and D3D11 Failing Tests // OpenGL and D3D11 Failing Tests
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.num_work_groups = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.num_work_groups = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.work_group_size = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_var.compute.work_group_size = FAIL
...@@ -1119,8 +1128,6 @@ ...@@ -1119,8 +1128,6 @@
1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_multiple_groups = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_multiple_groups = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.shared_var.* = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.shared_var.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.indirect_dispatch.* = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.indirect_dispatch.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.draw_indirect.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.draw_indirect.negative.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.ssbo.* = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.ssbo.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.2_level_array.* = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.2_level_array.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.3_level_array.* = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.3_level_array.* = FAIL
......
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