Commit 62fcf62a by Qin Jiajia Committed by Commit Bot

ES31: Add DispatchComputeIndirect suport for OpenGL backend

BUG=angleproject:2270 TEST=dEQP-GLES31.functional.compute.indirect_dispatch.* Change-Id: Id062a80188b2a37f28833aaae8e6d31bac382276 Reviewed-on: https://chromium-review.googlesource.com/802763 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent c6faa974
......@@ -417,6 +417,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
mComputeDirtyBits.set(State::DIRTY_BIT_PROGRAM_EXECUTABLE);
mComputeDirtyBits.set(State::DIRTY_BIT_TEXTURE_BINDINGS);
mComputeDirtyBits.set(State::DIRTY_BIT_SAMPLER_BINDINGS);
mComputeDirtyBits.set(State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
handleError(mImplementation->initialize());
}
......@@ -4249,7 +4250,8 @@ void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGr
void Context::dispatchComputeIndirect(GLintptr indirect)
{
UNIMPLEMENTED();
ANGLE_CONTEXT_TRY(prepareForDispatch());
handleError(mImplementation->dispatchComputeIndirect(this, indirect));
}
void Context::texStorage2D(GLenum target,
......
......@@ -26,6 +26,7 @@ ERRMSG(CubemapIncomplete,
ERRMSG(DefaultFramebufferInvalidAttachment,
"Invalid attachment when the default framebuffer is bound.");
ERRMSG(DefaultFramebufferTarget, "It is invalid to change default FBO's attachments");
ERRMSG(DispatchIndirectBufferNotBound, "Dispatch indirect buffer must be bound.");
ERRMSG(DrawBufferTypeMismatch,
"Fragment shader output type does not match the bound framebuffer attachment type.");
ERRMSG(EnumNotSupported, "Enum is not currently supported.");
......@@ -129,12 +130,15 @@ ERRMSG(NegativePrimcount, "Primcount must be greater than or equal to zero.");
ERRMSG(NegativeSize, "Cannot have negative height or width.");
ERRMSG(NegativeStart, "Cannot have negative start.");
ERRMSG(NegativeStride, "Cannot have negative stride.");
ERRMSG(NoActiveProgramWithComputeShader, "No active program for the compute shader stage.");
ERRMSG(NoSuchPath, "No such path object.");
ERRMSG(NoTransformFeedbackOutputVariables,
"The active program has specified no output variables to record.");
ERRMSG(NoZeroDivisor, "At least one enabled attribute must have a divisor of zero.");
ERRMSG(ObjectNotGenerated, "Object cannot be used because it has not been generated.");
ERRMSG(OffsetMustBeMultipleOfType, "Offset must be a multiple of the passed in datatype.");
ERRMSG(OffsetMustBeMultipleOfUint,
"Offset must be a multiple of the size, in basic machine units, of uint");
ERRMSG(OutsideOfBounds, "Parameter outside of bounds.");
ERRMSG(ParamOverflow, "The provided parameters overflow with the provided buffer.");
ERRMSG(PixelDataNotNull, "Pixel data must be null.");
......
......@@ -161,6 +161,8 @@ class ContextImpl : public GLImplFactory
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ) = 0;
virtual gl::Error dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) = 0;
virtual gl::Error memoryBarrier(const gl::Context *context, GLbitfield barriers) = 0;
virtual gl::Error memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) = 0;
......
......@@ -321,6 +321,12 @@ gl::Error Context11::dispatchCompute(const gl::Context *context,
return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
}
gl::Error Context11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
UNIMPLEMENTED();
return gl::InternalError();
}
gl::Error Context11::triggerDrawCallProgramRecompilation(const gl::Context *context,
GLenum drawMode)
{
......
......@@ -141,6 +141,7 @@ class Context11 : public ContextImpl
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ) override;
gl::Error dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
gl::Error memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
gl::Error memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
......
......@@ -300,6 +300,12 @@ gl::Error Context9::dispatchCompute(const gl::Context *context,
return gl::InternalError() << "D3D9 doesn't support ES 3.1 DispatchCompute API";
}
gl::Error Context9::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
UNREACHABLE();
return gl::InternalError() << "D3D9 doesn't support ES 3.1 dispatchComputeIndirect API";
}
gl::Error Context9::memoryBarrier(const gl::Context *context, GLbitfield barriers)
{
UNREACHABLE();
......
......@@ -139,6 +139,8 @@ class Context9 : public ContextImpl
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ) override;
gl::Error dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
gl::Error memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
gl::Error memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
......
......@@ -420,6 +420,11 @@ gl::Error ContextGL::dispatchCompute(const gl::Context *context,
return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
}
gl::Error ContextGL::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
return mRenderer->dispatchComputeIndirect(context, indirect);
}
gl::Error ContextGL::memoryBarrier(const gl::Context *context, GLbitfield barriers)
{
return mRenderer->memoryBarrier(barriers);
......
......@@ -198,6 +198,8 @@ class ContextGL : public ContextImpl
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ) override;
gl::Error dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
gl::Error memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
gl::Error memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
......
......@@ -729,11 +729,18 @@ gl::Error RendererGL::dispatchCompute(const gl::Context *context,
GLuint numGroupsY,
GLuint numGroupsZ)
{
ANGLE_TRY(mStateManager->setDispatchComputeState(context));
ANGLE_TRY(mStateManager->setDispatchComputeState(context, false));
mFunctions->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
return gl::NoError();
}
gl::Error RendererGL::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
ANGLE_TRY(mStateManager->setDispatchComputeState(context, true));
mFunctions->dispatchComputeIndirect(indirect);
return gl::NoError();
}
gl::Error RendererGL::memoryBarrier(GLbitfield barriers)
{
mFunctions->memoryBarrier(barriers);
......
......@@ -177,6 +177,8 @@ class RendererGL : angle::NonCopyable
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ);
gl::Error dispatchComputeIndirect(const gl::Context *context, GLintptr indirect);
gl::Error memoryBarrier(GLbitfield barriers);
gl::Error memoryBarrierByRegion(GLbitfield barriers);
......
......@@ -168,7 +168,8 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mLocalDirtyBits(),
mMultiviewDirtyBits(),
mProgramTexturesAndSamplersDirty(true),
mProgramStorageBuffersDirty(true)
mProgramStorageBuffersDirty(true),
mProgramDispatchIndirectBufferDirty(false)
{
ASSERT(mFunctions);
ASSERT(extensions.maxViews >= 1u);
......@@ -760,9 +761,25 @@ gl::Error StateManagerGL::setDrawIndirectState(const gl::Context *context, GLenu
return setGenericDrawState(context);
}
gl::Error StateManagerGL::setDispatchComputeState(const gl::Context *context)
void StateManagerGL::updateProgramDispatchIndirectBufferBinding(const gl::Context *context)
{
gl::Buffer *dispatchIndirectBuffer =
context->getGLState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
ASSERT(dispatchIndirectBuffer);
const BufferGL *bufferGL = GetImplAs<BufferGL>(dispatchIndirectBuffer);
bindBuffer(gl::BufferBinding::DispatchIndirect, bufferGL->getBufferID());
}
gl::Error StateManagerGL::setDispatchComputeState(const gl::Context *context, bool isIndirect)
{
setGenericShaderState(context);
if (isIndirect && mProgramDispatchIndirectBufferDirty)
{
updateProgramDispatchIndirectBufferBinding(context);
mProgramDispatchIndirectBufferDirty = false;
}
return gl::NoError();
}
......@@ -1932,7 +1949,7 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt
// TODO: implement this
break;
case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
// TODO(jiajia.qin@intel.com): implement this
mProgramDispatchIndirectBufferDirty = true;
break;
case gl::State::DIRTY_BIT_PROGRAM_BINDING:
{
......
......@@ -168,7 +168,7 @@ class StateManagerGL final : angle::NonCopyable
const void **outIndices);
gl::Error setDrawIndirectState(const gl::Context *context, GLenum type);
gl::Error setDispatchComputeState(const gl::Context *context);
gl::Error setDispatchComputeState(const gl::Context *context, bool isIndirect);
void pauseTransformFeedback();
gl::Error pauseAllQueries();
......@@ -200,6 +200,7 @@ class StateManagerGL final : angle::NonCopyable
void updateProgramTextureAndSamplerBindings(const gl::Context *context);
void updateProgramStorageBufferBindings(const gl::Context *context);
void updateProgramDispatchIndirectBufferBinding(const gl::Context *context);
void syncTransformFeedbackState(const gl::Context *context);
......@@ -358,6 +359,7 @@ class StateManagerGL final : angle::NonCopyable
bool mProgramTexturesAndSamplersDirty;
bool mProgramStorageBuffersDirty;
bool mProgramDispatchIndirectBufferDirty;
};
}
......
......@@ -415,6 +415,11 @@ gl::Error ContextNULL::dispatchCompute(const gl::Context *context,
return gl::NoError();
}
gl::Error ContextNULL::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
return gl::NoError();
}
gl::Error ContextNULL::memoryBarrier(const gl::Context *context, GLbitfield barriers)
{
return gl::NoError();
......
......@@ -198,6 +198,8 @@ class ContextNULL : public ContextImpl
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ) override;
gl::Error dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
gl::Error memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
gl::Error memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
......
......@@ -884,6 +884,12 @@ gl::Error ContextVk::dispatchCompute(const gl::Context *context,
return gl::InternalError();
}
gl::Error ContextVk::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
UNIMPLEMENTED();
return gl::InternalError();
}
gl::Error ContextVk::memoryBarrier(const gl::Context *context, GLbitfield barriers)
{
UNIMPLEMENTED();
......
......@@ -153,6 +153,8 @@ class ContextVk : public ContextImpl, public ResourceVk
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ) override;
gl::Error dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
gl::Error memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
gl::Error memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
......
......@@ -1384,16 +1384,9 @@ bool ValidateDispatchCompute(Context *context,
const State &state = context->getGLState();
Program *program = state.getProgram();
if (program == nullptr)
if (program == nullptr || !program->hasLinkedComputeShader())
{
context->handleError(InvalidOperation()
<< "No active program object for the compute shader stage.");
return false;
}
if (!program->hasLinkedComputeShader())
{
context->handleError(InvalidOperation() << "Program contains no compute shaders.");
ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveProgramWithComputeShader);
return false;
}
......@@ -1425,8 +1418,50 @@ bool ValidateDispatchCompute(Context *context,
bool ValidateDispatchComputeIndirect(Context *context, GLintptr indirect)
{
UNIMPLEMENTED();
return false;
if (context->getClientVersion() < ES_3_1)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
return false;
}
const State &state = context->getGLState();
Program *program = state.getProgram();
if (program == nullptr || !program->hasLinkedComputeShader())
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveProgramWithComputeShader);
return false;
}
gl::Buffer *dispatchIndirectBuffer = state.getTargetBuffer(BufferBinding::DispatchIndirect);
if (!dispatchIndirectBuffer)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), DispatchIndirectBufferNotBound);
return false;
}
if (indirect < 0)
{
ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
return false;
}
if ((indirect & (sizeof(GLuint) - 1)) != 0)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfUint);
return false;
}
CheckedNumeric<GLuint64> checkedOffset(static_cast<GLuint64>(indirect));
auto checkedSum = checkedOffset + static_cast<GLuint64>(3 * sizeof(GLuint));
if (!checkedSum.IsValid() ||
checkedSum.ValueOrDie() > static_cast<GLuint64>(dispatchIndirectBuffer->getSize()))
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
return false;
}
return true;
}
bool ValidateBindImageTexture(Context *context,
......
......@@ -1127,7 +1127,6 @@
1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform_block.referenced_by.* = FAIL
1442 OPENGL : dEQP-GLES31.functional.compute.basic.copy_image_to_ssbo_large = FAIL
1442 OPENGL : dEQP-GLES31.functional.compute.basic.copy_ssbo_to_image_large = FAIL
2270 OPENGL : dEQP-GLES31.functional.compute.indirect_dispatch.* = FAIL
2272 WIN NVIDIA OPENGL : dEQP-GLES31.functional.ssbo.layout.2_level_unsized* = FAIL
2272 WIN NVIDIA OPENGL : dEQP-GLES31.functional.ssbo.layout.3_level_unsized* = FAIL
2272 WIN NVIDIA OPENGL : dEQP-GLES31.functional.ssbo.layout.random.arrays_of_arrays* = 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