Commit 6193fd69 by Alexey Knyazev Committed by Commit Bot

OpenGL: Implement OES_draw_buffers_indexed

OpenGL state sync issues as few GL commands as possible to update the blend state regardless of an application input. Enhanced ClearTestES3.MaskedIndexedClearMultipleAttachments regression test. Disabled OES_draw_buffers_indexed on Windows/AMD/OpenGL. Bug: angleproject:4394 Change-Id: I244ac2975678bc559634152cf4eb997d9dbe83d0 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2145874 Commit-Queue: Kenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 6e7d7296
...@@ -426,6 +426,12 @@ struct FeaturesGL : FeatureSetBase ...@@ -426,6 +426,12 @@ struct FeaturesGL : FeatureSetBase
"avoid_dxt1_srgb_texture_format", FeatureCategory::OpenGLWorkarounds, "avoid_dxt1_srgb_texture_format", FeatureCategory::OpenGLWorkarounds,
"Replaces DXT1 sRGB with DXT1 sRGB Alpha as a driver bug workaround.", &members}; "Replaces DXT1 sRGB with DXT1 sRGB Alpha as a driver bug workaround.", &members};
// Bugs exist in OpenGL AMD drivers on Windows that produce incorrect pipeline state for
// colorMaski calls.
Feature disableDrawBuffersIndexed = {"disable_draw_buffers_indexed",
FeatureCategory::OpenGLWorkarounds,
"Disable OES_draw_buffers_indexed extension.", &members};
// GL_EXT_semaphore_fd doesn't work properly with Mesa 19.3.4 and earlier versions. // GL_EXT_semaphore_fd doesn't work properly with Mesa 19.3.4 and earlier versions.
Feature disableSemaphoreFd = {"disable_semaphore_fd", FeatureCategory::OpenGLWorkarounds, Feature disableSemaphoreFd = {"disable_semaphore_fd", FeatureCategory::OpenGLWorkarounds,
"Disable GL_EXT_semaphore_fd extension", &members, "Disable GL_EXT_semaphore_fd extension", &members,
......
...@@ -388,6 +388,7 @@ void State::initialize(Context *context) ...@@ -388,6 +388,7 @@ void State::initialize(Context *context)
const Version &clientVersion = context->getClientVersion(); const Version &clientVersion = context->getClientVersion();
mMaxDrawBuffers = static_cast<GLuint>(caps.maxDrawBuffers); mMaxDrawBuffers = static_cast<GLuint>(caps.maxDrawBuffers);
mBlendStateExt = BlendStateExt(mMaxDrawBuffers);
mMaxCombinedTextureImageUnits = static_cast<GLuint>(caps.maxCombinedTextureImageUnits); mMaxCombinedTextureImageUnits = static_cast<GLuint>(caps.maxCombinedTextureImageUnits);
setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f); setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
...@@ -706,6 +707,8 @@ void State::setColorMask(bool red, bool green, bool blue, bool alpha) ...@@ -706,6 +707,8 @@ void State::setColorMask(bool red, bool green, bool blue, bool alpha)
blendState.colorMaskBlue = blue; blendState.colorMaskBlue = blue;
blendState.colorMaskAlpha = alpha; blendState.colorMaskAlpha = alpha;
} }
mBlendStateExt.setColorMask(red, green, blue, alpha);
mDirtyBits.set(DIRTY_BIT_COLOR_MASK); mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
} }
...@@ -716,6 +719,8 @@ void State::setColorMaskIndexed(bool red, bool green, bool blue, bool alpha, GLu ...@@ -716,6 +719,8 @@ void State::setColorMaskIndexed(bool red, bool green, bool blue, bool alpha, GLu
mBlendStateArray[index].colorMaskGreen = green; mBlendStateArray[index].colorMaskGreen = green;
mBlendStateArray[index].colorMaskBlue = blue; mBlendStateArray[index].colorMaskBlue = blue;
mBlendStateArray[index].colorMaskAlpha = alpha; mBlendStateArray[index].colorMaskAlpha = alpha;
mBlendStateExt.setColorMaskIndexed(index, red, green, blue, alpha);
mDirtyBits.set(DIRTY_BIT_COLOR_MASK); mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
} }
...@@ -814,7 +819,7 @@ void State::setBlend(bool enabled) ...@@ -814,7 +819,7 @@ void State::setBlend(bool enabled)
{ {
blendState.blend = enabled; blendState.blend = enabled;
} }
enabled ? mBlendEnabledDrawBuffers.set() : mBlendEnabledDrawBuffers.reset(); mBlendStateExt.setEnabled(enabled);
mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
} }
...@@ -822,7 +827,7 @@ void State::setBlendIndexed(bool enabled, GLuint index) ...@@ -822,7 +827,7 @@ void State::setBlendIndexed(bool enabled, GLuint index)
{ {
ASSERT(index < mBlendStateArray.size()); ASSERT(index < mBlendStateArray.size());
mBlendStateArray[index].blend = enabled; mBlendStateArray[index].blend = enabled;
mBlendEnabledDrawBuffers.set(index, enabled); mBlendStateExt.setEnabledIndexed(index, enabled);
mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
} }
...@@ -856,6 +861,8 @@ void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha ...@@ -856,6 +861,8 @@ void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha
mBlendFuncConstantAlphaDrawBuffers.reset(); mBlendFuncConstantAlphaDrawBuffers.reset();
} }
} }
mBlendStateExt.setFactors(sourceRGB, destRGB, sourceAlpha, destAlpha);
mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS); mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS);
} }
...@@ -876,6 +883,8 @@ void State::setBlendFactorsIndexed(GLenum sourceRGB, ...@@ -876,6 +883,8 @@ void State::setBlendFactorsIndexed(GLenum sourceRGB,
mBlendFuncConstantColorDrawBuffers.set(index, hasConstantColor(sourceRGB, destRGB)); mBlendFuncConstantColorDrawBuffers.set(index, hasConstantColor(sourceRGB, destRGB));
mBlendFuncConstantAlphaDrawBuffers.set(index, hasConstantAlpha(sourceRGB, destRGB)); mBlendFuncConstantAlphaDrawBuffers.set(index, hasConstantAlpha(sourceRGB, destRGB));
} }
mBlendStateExt.setFactorsIndexed(index, sourceRGB, destRGB, sourceAlpha, destAlpha);
mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS); mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS);
} }
...@@ -909,6 +918,8 @@ void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) ...@@ -909,6 +918,8 @@ void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
blendState.blendEquationRGB = rgbEquation; blendState.blendEquationRGB = rgbEquation;
blendState.blendEquationAlpha = alphaEquation; blendState.blendEquationAlpha = alphaEquation;
} }
mBlendStateExt.setEquations(rgbEquation, alphaEquation);
mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS); mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS);
} }
...@@ -917,6 +928,8 @@ void State::setBlendEquationIndexed(GLenum rgbEquation, GLenum alphaEquation, GL ...@@ -917,6 +928,8 @@ void State::setBlendEquationIndexed(GLenum rgbEquation, GLenum alphaEquation, GL
ASSERT(index < mBlendStateArray.size()); ASSERT(index < mBlendStateArray.size());
mBlendStateArray[index].blendEquationRGB = rgbEquation; mBlendStateArray[index].blendEquationRGB = rgbEquation;
mBlendStateArray[index].blendEquationAlpha = alphaEquation; mBlendStateArray[index].blendEquationAlpha = alphaEquation;
mBlendStateExt.setEquationsIndexed(index, rgbEquation, alphaEquation);
mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS); mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS);
} }
......
...@@ -172,7 +172,7 @@ class State : angle::NonCopyable ...@@ -172,7 +172,7 @@ class State : angle::NonCopyable
ASSERT(index < mBlendStateArray.size()); ASSERT(index < mBlendStateArray.size());
return mBlendStateArray[index].blend; return mBlendStateArray[index].blend;
} }
DrawBufferMask getBlendEnabledDrawBufferMask() const { return mBlendEnabledDrawBuffers; } DrawBufferMask getBlendEnabledDrawBufferMask() const { return mBlendStateExt.mEnabledMask; }
void setBlend(bool enabled); void setBlend(bool enabled);
void setBlendIndexed(bool enabled, GLuint index); void setBlendIndexed(bool enabled, GLuint index);
void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
...@@ -764,12 +764,12 @@ class State : angle::NonCopyable ...@@ -764,12 +764,12 @@ class State : angle::NonCopyable
bool hasConstantAlphaBlendFunc() const bool hasConstantAlphaBlendFunc() const
{ {
return (mBlendFuncConstantAlphaDrawBuffers & mBlendEnabledDrawBuffers).any(); return (mBlendFuncConstantAlphaDrawBuffers & mBlendStateExt.mEnabledMask).any();
} }
bool hasSimultaneousConstantColorAndAlphaBlendFunc() const bool hasSimultaneousConstantColorAndAlphaBlendFunc() const
{ {
return (mBlendFuncConstantColorDrawBuffers & mBlendEnabledDrawBuffers).any() && return (mBlendFuncConstantColorDrawBuffers & mBlendStateExt.mEnabledMask).any() &&
hasConstantAlphaBlendFunc(); hasConstantAlphaBlendFunc();
} }
...@@ -780,6 +780,8 @@ class State : angle::NonCopyable ...@@ -780,6 +780,8 @@ class State : angle::NonCopyable
bool isEarlyFragmentTestsOptimizationAllowed() const { return isSampleCoverageEnabled(); } bool isEarlyFragmentTestsOptimizationAllowed() const { return isSampleCoverageEnabled(); }
const BlendStateExt &getBlendStateExt() const { return mBlendStateExt; }
private: private:
friend class Context; friend class Context;
...@@ -875,6 +877,7 @@ class State : angle::NonCopyable ...@@ -875,6 +877,7 @@ class State : angle::NonCopyable
Rectangle mScissor; Rectangle mScissor;
BlendStateArray mBlendStateArray; BlendStateArray mBlendStateArray;
BlendStateExt mBlendStateExt;
ColorF mBlendColor; ColorF mBlendColor;
bool mSampleAlphaToCoverage; bool mSampleAlphaToCoverage;
bool mSampleCoverage; bool mSampleCoverage;
...@@ -1002,7 +1005,6 @@ class State : angle::NonCopyable ...@@ -1002,7 +1005,6 @@ class State : angle::NonCopyable
const OverlayType *mOverlay; const OverlayType *mOverlay;
// OES_draw_buffers_indexed // OES_draw_buffers_indexed
DrawBufferMask mBlendEnabledDrawBuffers;
DrawBufferMask mBlendFuncConstantAlphaDrawBuffers; DrawBufferMask mBlendFuncConstantAlphaDrawBuffers;
DrawBufferMask mBlendFuncConstantColorDrawBuffers; DrawBufferMask mBlendFuncConstantColorDrawBuffers;
bool mNoSimultaneousConstantColorAndAlphaBlendFunc; bool mNoSimultaneousConstantColorAndAlphaBlendFunc;
......
...@@ -89,12 +89,10 @@ class StateManagerGL final : angle::NonCopyable ...@@ -89,12 +89,10 @@ class StateManagerGL final : angle::NonCopyable
void setDepthRange(float near, float far); void setDepthRange(float near, float far);
void setBlendEnabled(bool enabled); void setBlendEnabled(bool enabled);
void setBlendEnabledIndexed(const gl::DrawBufferMask blendEnabledMask);
void setBlendColor(const gl::ColorF &blendColor); void setBlendColor(const gl::ColorF &blendColor);
void setBlendFuncs(GLenum sourceBlendRGB, void setBlendFuncs(const gl::BlendStateExt &blendStateExt);
GLenum destBlendRGB, void setBlendEquations(const gl::BlendStateExt &blendStateExt);
GLenum sourceBlendAlpha,
GLenum destBlendAlpha);
void setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha);
void setColorMask(bool red, bool green, bool blue, bool alpha); void setColorMask(bool red, bool green, bool blue, bool alpha);
void setSampleAlphaToCoverageEnabled(bool enabled); void setSampleAlphaToCoverageEnabled(bool enabled);
void setSampleCoverageEnabled(bool enabled); void setSampleCoverageEnabled(bool enabled);
...@@ -137,11 +135,8 @@ class StateManagerGL final : angle::NonCopyable ...@@ -137,11 +135,8 @@ class StateManagerGL final : angle::NonCopyable
void setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context, void setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
bool enabled, bool enabled,
const FramebufferGL *framebuffer); const FramebufferGL *framebuffer);
void setColorMaskForFramebuffer(bool red, void setColorMaskForFramebuffer(const gl::BlendStateExt &blendStateExt,
bool green, const bool disableAlpha);
bool blue,
bool alpha,
const FramebufferGL *framebuffer);
void setDitherEnabled(bool enabled); void setDitherEnabled(bool enabled);
...@@ -279,18 +274,10 @@ class StateManagerGL final : angle::NonCopyable ...@@ -279,18 +274,10 @@ class StateManagerGL final : angle::NonCopyable
float mNear; float mNear;
float mFar; float mFar;
bool mBlendEnabled;
gl::ColorF mBlendColor; gl::ColorF mBlendColor;
GLenum mSourceBlendRGB; gl::BlendStateExt mBlendStateExt;
GLenum mDestBlendRGB; const bool mIndependentBlendStates;
GLenum mSourceBlendAlpha;
GLenum mDestBlendAlpha;
GLenum mBlendEquationRGB;
GLenum mBlendEquationAlpha;
bool mColorMaskRed;
bool mColorMaskGreen;
bool mColorMaskBlue;
bool mColorMaskAlpha;
bool mSampleAlphaToCoverageEnabled; bool mSampleAlphaToCoverageEnabled;
bool mSampleCoverageEnabled; bool mSampleCoverageEnabled;
float mSampleCoverageValue; float mSampleCoverageValue;
......
...@@ -1162,7 +1162,16 @@ void GenerateCaps(const FunctionsGL *functions, ...@@ -1162,7 +1162,16 @@ void GenerateCaps(const FunctionsGL *functions,
extensions->drawBuffers = functions->isAtLeastGL(gl::Version(2, 0)) || extensions->drawBuffers = functions->isAtLeastGL(gl::Version(2, 0)) ||
functions->hasGLExtension("ARB_draw_buffers") || functions->hasGLExtension("ARB_draw_buffers") ||
functions->hasGLESExtension("GL_EXT_draw_buffers"); functions->hasGLESExtension("GL_EXT_draw_buffers");
extensions->textureStorage = functions->standard == STANDARD_GL_DESKTOP || extensions->drawBuffersIndexedEXT =
!features.disableDrawBuffersIndexed.enabled &&
(functions->isAtLeastGL(gl::Version(4, 0)) ||
(functions->hasGLExtension("GL_EXT_draw_buffers2") &&
functions->hasGLExtension("GL_ARB_draw_buffers_blend")) ||
functions->isAtLeastGLES(gl::Version(3, 2)) ||
functions->hasGLESExtension("GL_OES_draw_buffers_indexed") ||
functions->hasGLESExtension("GL_EXT_draw_buffers_indexed"));
extensions->drawBuffersIndexedOES = extensions->drawBuffersIndexedEXT;
extensions->textureStorage = functions->standard == STANDARD_GL_DESKTOP ||
functions->hasGLESExtension("GL_EXT_texture_storage"); functions->hasGLESExtension("GL_EXT_texture_storage");
extensions->textureFilterAnisotropic = extensions->textureFilterAnisotropic =
functions->hasGLExtension("GL_EXT_texture_filter_anisotropic") || functions->hasGLExtension("GL_EXT_texture_filter_anisotropic") ||
...@@ -1705,6 +1714,8 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature ...@@ -1705,6 +1714,8 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
// Workaround for incorrect sampling from DXT1 sRGB textures in Intel OpenGL on Windows. // Workaround for incorrect sampling from DXT1 sRGB textures in Intel OpenGL on Windows.
ANGLE_FEATURE_CONDITION(features, avoidDXT1sRGBTextureFormat, IsWindows() && isIntel); ANGLE_FEATURE_CONDITION(features, avoidDXT1sRGBTextureFormat, IsWindows() && isIntel);
ANGLE_FEATURE_CONDITION(features, disableDrawBuffersIndexed, IsWindows() && isAMD);
ANGLE_FEATURE_CONDITION( ANGLE_FEATURE_CONDITION(
features, disableSemaphoreFd, features, disableSemaphoreFd,
IsLinux() && isAMD && isMesa && mesaVersion < (std::array<int, 3>{19, 3, 5})); IsLinux() && isAMD && isMesa && mesaVersion < (std::array<int, 3>{19, 3, 5}));
......
...@@ -852,7 +852,7 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments) ...@@ -852,7 +852,7 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments)
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")); ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"));
constexpr uint32_t kSize = 16; constexpr uint32_t kSize = 16;
constexpr uint32_t kAttachmentCount = 2; constexpr uint32_t kAttachmentCount = 4;
std::vector<unsigned char> pixelData(kSize * kSize * 4, 255); std::vector<unsigned char> pixelData(kSize * kSize * 4, 255);
glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]); glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
...@@ -882,7 +882,8 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments) ...@@ -882,7 +882,8 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments)
// Block blue channel for all attachements // Block blue channel for all attachements
glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
// Unblock blue channel for attachement 1 // Unblock blue channel for attachments 0 and 1
glColorMaskiOES(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glColorMaskiOES(1, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMaskiOES(1, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
...@@ -895,12 +896,12 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments) ...@@ -895,12 +896,12 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments)
glReadBuffer(GL_COLOR_ATTACHMENT0 + i); glReadBuffer(GL_COLOR_ATTACHMENT0 + i);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
const GLColor attachementColor = (i == 1) ? clearColor : clearColorMasked; const GLColor attachmentColor = (i > 1) ? clearColorMasked : clearColor;
EXPECT_PIXEL_COLOR_EQ(0, 0, attachementColor); EXPECT_PIXEL_COLOR_EQ(0, 0, attachmentColor);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, attachementColor); EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, attachmentColor);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, attachementColor); EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, attachmentColor);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, attachementColor); EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, attachmentColor);
EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, attachementColor); EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, attachmentColor);
} }
} }
......
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