Commit 2b39659d by Xinghua Cao Committed by Commit Bot

ES31: Implement glDispatchCompute for OpenGL backend

This patch refers to https://chromium-review.googlesource.com/c/380639/ BUG=angleproject:1955 TESTCASE=angle_end2end_tests Change-Id: Iafd7a6ba2d71c0b332d9267a1260d9dbd9800c02 Reviewed-on: https://chromium-review.googlesource.com/462089 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarYunchao He <yunchao.he@intel.com> Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent e918de22
...@@ -4037,4 +4037,14 @@ Error Context::getScratchBuffer(size_t requestedSize, angle::MemoryBuffer **scra ...@@ -4037,4 +4037,14 @@ Error Context::getScratchBuffer(size_t requestedSize, angle::MemoryBuffer **scra
return gl::NoError(); return gl::NoError();
} }
void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
{
if (numGroupsX == 0u || numGroupsY == 0u || numGroupsZ == 0u)
{
return;
}
mImplementation->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
}
} // namespace gl } // namespace gl
...@@ -697,6 +697,8 @@ class Context final : public ValidationContext ...@@ -697,6 +697,8 @@ class Context final : public ValidationContext
Error getScratchBuffer(size_t requestedSize, angle::MemoryBuffer **scratchBufferOut) const; Error getScratchBuffer(size_t requestedSize, angle::MemoryBuffer **scratchBufferOut) const;
void dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
private: private:
void syncRendererState(); void syncRendererState();
void syncRendererState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask); void syncRendererState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask);
......
...@@ -138,6 +138,8 @@ class ContextImpl : public GLImplFactory ...@@ -138,6 +138,8 @@ class ContextImpl : public GLImplFactory
virtual const gl::Extensions &getNativeExtensions() const = 0; virtual const gl::Extensions &getNativeExtensions() const = 0;
virtual const gl::Limitations &getNativeLimitations() const = 0; virtual const gl::Limitations &getNativeLimitations() const = 0;
virtual gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) = 0;
const gl::ContextState &getContextState() { return mState; } const gl::ContextState &getContextState() { return mState; }
int getClientMajorVersion() const { return mState.getClientMajorVersion(); } int getClientMajorVersion() const { return mState.getClientMajorVersion(); }
int getClientMinorVersion() const { return mState.getClientMinorVersion(); } int getClientMinorVersion() const { return mState.getClientMinorVersion(); }
......
...@@ -280,4 +280,10 @@ const gl::Limitations &Context11::getNativeLimitations() const ...@@ -280,4 +280,10 @@ const gl::Limitations &Context11::getNativeLimitations() const
return mRenderer->getNativeLimitations(); return mRenderer->getNativeLimitations();
} }
gl::Error Context11::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
{
UNIMPLEMENTED();
return gl::NoError();
}
} // namespace rx } // namespace rx
...@@ -121,6 +121,8 @@ class Context11 : public ContextImpl ...@@ -121,6 +121,8 @@ class Context11 : public ContextImpl
Renderer11 *getRenderer() const { return mRenderer; } Renderer11 *getRenderer() const { return mRenderer; }
gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
private: private:
Renderer11 *mRenderer; Renderer11 *mRenderer;
}; };
......
...@@ -267,4 +267,10 @@ const gl::Limitations &Context9::getNativeLimitations() const ...@@ -267,4 +267,10 @@ const gl::Limitations &Context9::getNativeLimitations() const
return mRenderer->getNativeLimitations(); return mRenderer->getNativeLimitations();
} }
gl::Error Context9::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
{
UNREACHABLE();
return gl::InternalError() << "D3D9 doesn't support ES 3.1 DispatchCompute API";
}
} // namespace rx } // namespace rx
...@@ -119,6 +119,8 @@ class Context9 : public ContextImpl ...@@ -119,6 +119,8 @@ class Context9 : public ContextImpl
const gl::Extensions &getNativeExtensions() const override; const gl::Extensions &getNativeExtensions() const override;
const gl::Limitations &getNativeLimitations() const override; const gl::Limitations &getNativeLimitations() const override;
gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
private: private:
Renderer9 *mRenderer; Renderer9 *mRenderer;
}; };
......
...@@ -384,4 +384,9 @@ const WorkaroundsGL &ContextGL::getWorkaroundsGL() const ...@@ -384,4 +384,9 @@ const WorkaroundsGL &ContextGL::getWorkaroundsGL() const
return mRenderer->getWorkarounds(); return mRenderer->getWorkarounds();
} }
gl::Error ContextGL::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
{
return mRenderer->dispatchCompute(mState, numGroupsX, numGroupsY, numGroupsZ);
}
} // namespace rx } // namespace rx
...@@ -176,6 +176,8 @@ class ContextGL : public ContextImpl ...@@ -176,6 +176,8 @@ class ContextGL : public ContextImpl
StateManagerGL *getStateManager(); StateManagerGL *getStateManager();
const WorkaroundsGL &getWorkaroundsGL() const; const WorkaroundsGL &getWorkaroundsGL() const;
gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
private: private:
RendererGL *mRenderer; RendererGL *mRenderer;
}; };
......
...@@ -603,4 +603,14 @@ const gl::Limitations &RendererGL::getNativeLimitations() const ...@@ -603,4 +603,14 @@ const gl::Limitations &RendererGL::getNativeLimitations() const
return mNativeLimitations; return mNativeLimitations;
} }
gl::Error RendererGL::dispatchCompute(const gl::ContextState &data,
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ)
{
ANGLE_TRY(mStateManager->setDispatchComputeState(data));
mFunctions->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
return gl::NoError();
}
} // namespace rx } // namespace rx
...@@ -166,6 +166,11 @@ class RendererGL : angle::NonCopyable ...@@ -166,6 +166,11 @@ class RendererGL : angle::NonCopyable
const gl::Extensions &getNativeExtensions() const; const gl::Extensions &getNativeExtensions() const;
const gl::Limitations &getNativeLimitations() const; const gl::Limitations &getNativeLimitations() const;
gl::Error dispatchCompute(const gl::ContextState &data,
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ);
private: private:
void ensureCapsInitialized() const; void ensureCapsInitialized() const;
void generateCaps(gl::Caps *outCaps, void generateCaps(gl::Caps *outCaps,
......
...@@ -683,6 +683,12 @@ gl::Error StateManagerGL::setDrawIndirectState(const gl::ContextState &data, GLe ...@@ -683,6 +683,12 @@ gl::Error StateManagerGL::setDrawIndirectState(const gl::ContextState &data, GLe
return setGenericDrawState(data); return setGenericDrawState(data);
} }
gl::Error StateManagerGL::setDispatchComputeState(const gl::ContextState &data)
{
setGenericShaderState(data);
return gl::NoError();
}
void StateManagerGL::pauseTransformFeedback() void StateManagerGL::pauseTransformFeedback()
{ {
if (mPrevDrawTransformFeedback != nullptr) if (mPrevDrawTransformFeedback != nullptr)
...@@ -1805,9 +1811,4 @@ void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled) ...@@ -1805,9 +1811,4 @@ void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
} }
} }
GLuint StateManagerGL::getBoundBuffer(GLenum type)
{
ASSERT(mBuffers.find(type) != mBuffers.end());
return mBuffers[type];
}
} }
...@@ -153,6 +153,8 @@ class StateManagerGL final : angle::NonCopyable ...@@ -153,6 +153,8 @@ class StateManagerGL final : angle::NonCopyable
const GLvoid **outIndices); const GLvoid **outIndices);
gl::Error setDrawIndirectState(const gl::ContextState &data, GLenum type); gl::Error setDrawIndirectState(const gl::ContextState &data, GLenum type);
gl::Error setDispatchComputeState(const gl::ContextState &data);
void pauseTransformFeedback(); void pauseTransformFeedback();
void pauseAllQueries(); void pauseAllQueries();
void pauseQuery(GLenum type); void pauseQuery(GLenum type);
...@@ -162,8 +164,6 @@ class StateManagerGL final : angle::NonCopyable ...@@ -162,8 +164,6 @@ class StateManagerGL final : angle::NonCopyable
void syncState(const gl::ContextState &data, const gl::State::DirtyBits &glDirtyBits); void syncState(const gl::ContextState &data, const gl::State::DirtyBits &glDirtyBits);
GLuint getBoundBuffer(GLenum type);
private: private:
// Set state that's common among draw commands and compute invocations. // Set state that's common among draw commands and compute invocations.
void setGenericShaderState(const gl::ContextState &data); void setGenericShaderState(const gl::ContextState &data);
......
...@@ -363,4 +363,9 @@ std::vector<PathImpl *> ContextNULL::createPaths(GLsizei range) ...@@ -363,4 +363,9 @@ std::vector<PathImpl *> ContextNULL::createPaths(GLsizei range)
return result; return result;
} }
gl::Error ContextNULL::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
{
return gl::NoError();
}
} // namespace rx } // namespace rx
...@@ -178,6 +178,8 @@ class ContextNULL : public ContextImpl ...@@ -178,6 +178,8 @@ class ContextNULL : public ContextImpl
std::vector<PathImpl *> createPaths(GLsizei range) override; std::vector<PathImpl *> createPaths(GLsizei range) override;
gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
private: private:
gl::Caps mCaps; gl::Caps mCaps;
gl::TextureCapsMap mTextureCaps; gl::TextureCapsMap mTextureCaps;
......
...@@ -552,4 +552,10 @@ void ContextVk::invalidateCurrentPipeline() ...@@ -552,4 +552,10 @@ void ContextVk::invalidateCurrentPipeline()
mRenderer->enqueueGarbageOrDeleteNow(*this, mCurrentPipeline); mRenderer->enqueueGarbageOrDeleteNow(*this, mCurrentPipeline);
} }
gl::Error ContextVk::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION);
}
} // namespace rx } // namespace rx
...@@ -131,6 +131,8 @@ class ContextVk : public ContextImpl, public ResourceVk ...@@ -131,6 +131,8 @@ class ContextVk : public ContextImpl, public ResourceVk
// TODO(jmadill): Use pipeline cache. // TODO(jmadill): Use pipeline cache.
void invalidateCurrentPipeline(); void invalidateCurrentPipeline();
gl::Error dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) override;
private: private:
gl::Error initPipeline(); gl::Error initPipeline();
......
...@@ -769,4 +769,62 @@ bool ValidateGetProgramResourceName(Context *context, ...@@ -769,4 +769,62 @@ bool ValidateGetProgramResourceName(Context *context,
return true; return true;
} }
bool ValidateDispatchCompute(Context *context,
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ)
{
if (context->getClientVersion() < ES_3_1)
{
context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
return false;
}
const State &state = context->getGLState();
Program *program = state.getProgram();
if (program == nullptr)
{
context->handleError(
Error(GL_INVALID_OPERATION, "No active program object for the compute shader stage."));
return false;
}
if (program->isLinked() == false || program->getAttachedComputeShader() == nullptr)
{
context->handleError(Error(
GL_INVALID_OPERATION,
"Program has not been successfully linked, or program contains no compute shaders."));
return false;
}
const Caps &caps = context->getCaps();
if (numGroupsX > caps.maxComputeWorkGroupCount[0])
{
context->handleError(
Error(GL_INVALID_VALUE,
"num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0](%u).",
caps.maxComputeWorkGroupCount[0]));
return false;
}
if (numGroupsY > caps.maxComputeWorkGroupCount[1])
{
context->handleError(
Error(GL_INVALID_VALUE,
"num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1](%u).",
caps.maxComputeWorkGroupCount[1]));
return false;
}
if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
{
context->handleError(
Error(GL_INVALID_VALUE,
"num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2](%u).",
caps.maxComputeWorkGroupCount[2]));
return false;
}
return true;
}
} // namespace gl } // namespace gl
...@@ -85,6 +85,11 @@ bool ValidateVertexAttribBinding(ValidationContext *context, ...@@ -85,6 +85,11 @@ bool ValidateVertexAttribBinding(ValidationContext *context,
GLuint bindingIndex); GLuint bindingIndex);
bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor); bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor);
bool ValidateDispatchCompute(Context *context,
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ);
} // namespace gl } // namespace gl
#endif // LIBANGLE_VALIDATION_ES31_H_ #endif // LIBANGLE_VALIDATION_ES31_H_
...@@ -30,11 +30,13 @@ void GL_APIENTRY DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint nu ...@@ -30,11 +30,13 @@ void GL_APIENTRY DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint nu
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!context->skipValidation()) if (!context->skipValidation() &&
!ValidateDispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ))
{ {
context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented")); return;
} }
UNIMPLEMENTED();
context->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
} }
} }
......
...@@ -21,6 +21,12 @@ class ComputeShaderTest : public ANGLETest ...@@ -21,6 +21,12 @@ class ComputeShaderTest : public ANGLETest
ComputeShaderTest() {} ComputeShaderTest() {}
}; };
class DispatchComputeTest : public ANGLETest
{
protected:
DispatchComputeTest() {}
};
class ComputeShaderTestES3 : public ANGLETest class ComputeShaderTestES3 : public ANGLETest
{ {
protected: protected:
...@@ -225,6 +231,25 @@ TEST_P(ComputeShaderTest, AccessPartSpecialVariables) ...@@ -225,6 +231,25 @@ TEST_P(ComputeShaderTest, AccessPartSpecialVariables)
ANGLE_GL_COMPUTE_PROGRAM(program, csSource); ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
} }
// TODO(Xinghua): A temporary test for glDispatchCompute, remove and merge it
// ComputeShaderTest after implementing this API on D3D backend.
TEST_P(DispatchComputeTest, DispatchCompute)
{
const std::string csSource =
"#version 310 es\n"
"layout(local_size_x=4, local_size_y=3, local_size_z=2) in;\n"
"void main()\n"
"{\n"
" uvec3 temp1 = gl_NumWorkGroups;\n"
"}\n";
ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
glUseProgram(program.get());
glDispatchCompute(8, 4, 2);
EXPECT_GL_NO_ERROR();
}
// Check that it is not possible to create a compute shader when the context does not support ES // Check that it is not possible to create a compute shader when the context does not support ES
// 3.10 // 3.10
TEST_P(ComputeShaderTestES3, NotSupported) TEST_P(ComputeShaderTestES3, NotSupported)
...@@ -235,6 +260,7 @@ TEST_P(ComputeShaderTestES3, NotSupported) ...@@ -235,6 +260,7 @@ TEST_P(ComputeShaderTestES3, NotSupported)
} }
ANGLE_INSTANTIATE_TEST(ComputeShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11()); ANGLE_INSTANTIATE_TEST(ComputeShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
ANGLE_INSTANTIATE_TEST(DispatchComputeTest, ES31_OPENGL(), ES31_OPENGLES());
ANGLE_INSTANTIATE_TEST(ComputeShaderTestES3, ES3_OPENGL(), ES3_OPENGLES()); ANGLE_INSTANTIATE_TEST(ComputeShaderTestES3, ES3_OPENGL(), ES3_OPENGLES());
} // namespace } // namespace
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