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