Commit c87e0053 by shrekshao Committed by Commit Bot

add ext_float_blend feature and test

Bug: chromium:930993 Change-Id: I8edbd01c5c9f1ed63243cc4a42f6de44c92db8bd Reviewed-on: https://chromium-review.googlesource.com/c/1481242 Commit-Queue: Shrek Shao <shrekshao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@google.com>
parent dbbdf563
...@@ -255,6 +255,7 @@ Extensions::Extensions() ...@@ -255,6 +255,7 @@ Extensions::Extensions()
multiviewMultisample(false), multiviewMultisample(false),
blendFuncExtended(false), blendFuncExtended(false),
maxDualSourceDrawBuffers(0), maxDualSourceDrawBuffers(0),
floatBlend(false),
memorySize(false), memorySize(false),
textureMultisample(false), textureMultisample(false),
multiDraw(false) multiDraw(false)
...@@ -909,6 +910,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -909,6 +910,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_OES_texture_storage_multisample_2d_array"] = enableableExtension(&Extensions::textureStorageMultisample2DArray); map["GL_OES_texture_storage_multisample_2d_array"] = enableableExtension(&Extensions::textureStorageMultisample2DArray);
map["GL_ANGLE_multiview_multisample"] = enableableExtension(&Extensions::multiviewMultisample); map["GL_ANGLE_multiview_multisample"] = enableableExtension(&Extensions::multiviewMultisample);
map["GL_EXT_blend_func_extended"] = enableableExtension(&Extensions::blendFuncExtended); map["GL_EXT_blend_func_extended"] = enableableExtension(&Extensions::blendFuncExtended);
map["GL_EXT_float_blend"] = enableableExtension(&Extensions::floatBlend);
map["GL_ANGLE_texture_multisample"] = enableableExtension(&Extensions::textureMultisample); map["GL_ANGLE_texture_multisample"] = enableableExtension(&Extensions::textureMultisample);
map["GL_ANGLE_multi_draw"] = enableableExtension(&Extensions::multiDraw); map["GL_ANGLE_multi_draw"] = enableableExtension(&Extensions::multiDraw);
map["GL_ANGLE_provoking_vertex"] = enableableExtension(&Extensions::provokingVertex); map["GL_ANGLE_provoking_vertex"] = enableableExtension(&Extensions::provokingVertex);
......
...@@ -466,6 +466,9 @@ struct Extensions ...@@ -466,6 +466,9 @@ struct Extensions
bool blendFuncExtended; bool blendFuncExtended;
GLuint maxDualSourceDrawBuffers; GLuint maxDualSourceDrawBuffers;
// GL_EXT_float_blend
bool floatBlend;
// GL_ANGLE_memory_size // GL_ANGLE_memory_size
bool memorySize; bool memorySize;
......
...@@ -474,6 +474,7 @@ MSG kUnimplementedComputeShaderPrecision = "Compute shader precision not yet imp ...@@ -474,6 +474,7 @@ MSG kUnimplementedComputeShaderPrecision = "Compute shader precision not yet imp
MSG kUnknownParameter = "Unknown parameter value."; MSG kUnknownParameter = "Unknown parameter value.";
MSG kUnsizedInternalFormatUnsupported = "Internalformat is one of the unsupported unsized base internalformats."; MSG kUnsizedInternalFormatUnsupported = "Internalformat is one of the unsupported unsized base internalformats.";
MSG kUnsupportedDrawModeForTransformFeedback = "The draw command is unsupported when transform feedback is active and not paused."; MSG kUnsupportedDrawModeForTransformFeedback = "The draw command is unsupported when transform feedback is active and not paused.";
MSG kUnsupportedFloatBlending = "GL_BLEND with floating-point color attachments requires the EXT_float_blend extension.";
MSG kVertexArrayNoBuffer = "An enabled vertex array has no buffer."; MSG kVertexArrayNoBuffer = "An enabled vertex array has no buffer.";
MSG kVertexArrayNoBufferPointer = "An enabled vertex array has no buffer and no pointer."; MSG kVertexArrayNoBufferPointer = "An enabled vertex array has no buffer and no pointer.";
MSG kVertexBufferBoundForTransformFeedback = "It is undefined behavior to use a vertex buffer that is bound for transform feedback."; MSG kVertexBufferBoundForTransformFeedback = "It is undefined behavior to use a vertex buffer that is bound for transform feedback.";
......
...@@ -1758,6 +1758,16 @@ void Framebuffer::setAttachmentImpl(const Context *context, ...@@ -1758,6 +1758,16 @@ void Framebuffer::setAttachmentImpl(const Context *context,
textureIndex, resource, numViews, baseViewIndex, multiviewLayout, textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
viewportOffsets); viewportOffsets);
if (!resource)
{
mFloat32ColorAttachmentBits.reset(colorIndex);
}
else
{
updateFloat32ColorAttachmentBits(
colorIndex, resource->getAttachmentFormat(binding, textureIndex).info);
}
// TODO(jmadill): ASSERT instead of checking the attachment exists in // TODO(jmadill): ASSERT instead of checking the attachment exists in
// formsRenderingFeedbackLoopWith // formsRenderingFeedbackLoopWith
bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE); bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
...@@ -1829,6 +1839,15 @@ void Framebuffer::onSubjectStateChange(const Context *context, ...@@ -1829,6 +1839,15 @@ void Framebuffer::onSubjectStateChange(const Context *context,
// Mark the appropriate init flag. // Mark the appropriate init flag.
mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit); mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
// Update mFloat32ColorAttachmentBits Cache
if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
{
ASSERT(index != DIRTY_BIT_DEPTH_ATTACHMENT);
ASSERT(index != DIRTY_BIT_STENCIL_ATTACHMENT);
updateFloat32ColorAttachmentBits(index - DIRTY_BIT_COLOR_ATTACHMENT_0,
attachment->getFormat().info);
}
} }
FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index) FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
......
...@@ -337,6 +337,11 @@ class Framebuffer final : public angle::ObserverInterface, ...@@ -337,6 +337,11 @@ class Framebuffer final : public angle::ObserverInterface,
using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
bool hasAnyDirtyBit() const { return mDirtyBits.any(); } bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
bool hasActiveFloat32ColorAttachment() const
{
return (mFloat32ColorAttachmentBits & getDrawBufferMask()).any();
}
bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); } bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); }
angle::Result syncState(const Context *context); angle::Result syncState(const Context *context);
...@@ -418,6 +423,12 @@ class Framebuffer final : public angle::ObserverInterface, ...@@ -418,6 +423,12 @@ class Framebuffer final : public angle::ObserverInterface,
FramebufferAttachment *getAttachmentFromSubjectIndex(angle::SubjectIndex index); FramebufferAttachment *getAttachmentFromSubjectIndex(angle::SubjectIndex index);
ANGLE_INLINE void updateFloat32ColorAttachmentBits(size_t index,
const gl::InternalFormat *format)
{
mFloat32ColorAttachmentBits.set(index, format->type == GL_FLOAT);
}
FramebufferState mState; FramebufferState mState;
rx::FramebufferImpl *mImpl; rx::FramebufferImpl *mImpl;
...@@ -427,6 +438,7 @@ class Framebuffer final : public angle::ObserverInterface, ...@@ -427,6 +438,7 @@ class Framebuffer final : public angle::ObserverInterface,
angle::ObserverBinding mDirtyStencilAttachmentBinding; angle::ObserverBinding mDirtyStencilAttachmentBinding;
DirtyBits mDirtyBits; DirtyBits mDirtyBits;
DrawBufferMask mFloat32ColorAttachmentBits;
// The dirty bits guard is checked when we get a dependent state change message. We verify that // The dirty bits guard is checked when we get a dependent state change message. We verify that
// we don't set a dirty bit that isn't already set, when inside the dirty bits syncState. // we don't set a dirty bit that isn't already set, when inside the dirty bits syncState.
......
...@@ -1345,6 +1345,11 @@ void GenerateCaps(const FunctionsGL *functions, ...@@ -1345,6 +1345,11 @@ void GenerateCaps(const FunctionsGL *functions,
extensions->maxDualSourceDrawBuffers = 1; extensions->maxDualSourceDrawBuffers = 1;
} }
// EXT_float_blend
// Assume all desktop driver supports this by default.
extensions->floatBlend = functions->standard == STANDARD_GL_DESKTOP ||
functions->hasGLESExtension("GL_EXT_float_blend");
// GL_CHROMIUM_compressed_texture_etc // GL_CHROMIUM_compressed_texture_etc
// Expose this extension only when we support the formats or we're running on top of a native // Expose this extension only when we support the formats or we're running on top of a native
// ES driver. // ES driver.
......
...@@ -2623,6 +2623,12 @@ const char *ValidateDrawStates(Context *context) ...@@ -2623,6 +2623,12 @@ const char *ValidateDrawStates(Context *context)
} }
} }
if (!extensions.floatBlend && context->getState().isBlendEnabled() &&
framebuffer->hasActiveFloat32ColorAttachment())
{
return kUnsupportedFloatBlending;
}
if (!framebuffer->isComplete(context)) if (!framebuffer->isComplete(context))
{ {
// Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION. // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
......
...@@ -171,7 +171,7 @@ TEST_P(BlendMinMaxTest, RGBA8) ...@@ -171,7 +171,7 @@ TEST_P(BlendMinMaxTest, RGBA8)
TEST_P(BlendMinMaxTest, RGBA32F) TEST_P(BlendMinMaxTest, RGBA32F)
{ {
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 || ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 || !extensionEnabled("GL_EXT_float_blend") ||
!extensionEnabled("GL_EXT_color_buffer_float")); !extensionEnabled("GL_EXT_color_buffer_float"));
// Ignore SDK layers messages on D3D11 FL 9.3 (http://anglebug.com/1284) // Ignore SDK layers messages on D3D11 FL 9.3 (http://anglebug.com/1284)
......
...@@ -43,6 +43,7 @@ constexpr const char *FloatingPointTextureExtensions[] = { ...@@ -43,6 +43,7 @@ constexpr const char *FloatingPointTextureExtensions[] = {
"GL_OES_texture_float", "GL_OES_texture_float",
"GL_OES_texture_float_linear", "GL_OES_texture_float_linear",
"GL_EXT_color_buffer_float", "GL_EXT_color_buffer_float",
"GL_EXT_float_blend",
"GL_CHROMIUM_color_buffer_float_rgba", "GL_CHROMIUM_color_buffer_float_rgba",
"GL_CHROMIUM_color_buffer_float_rgb", "GL_CHROMIUM_color_buffer_float_rgb",
}; };
...@@ -213,6 +214,49 @@ class WebGLCompatibilityTest : public ANGLETest ...@@ -213,6 +214,49 @@ class WebGLCompatibilityTest : public ANGLETest
0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f); 0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f);
} }
void TestExtFloatBlend(bool shouldBlend)
{
constexpr char kVS[] =
"void main()\n"
"{\n"
" gl_Position = vec4(0, 0, 0, 1);\n"
"}\n";
constexpr char kFS[] =
"void main()\n"
"{\n"
" gl_FragColor = vec4(0, 1, 0, 1);\n"
"}\n";
ANGLE_GL_PROGRAM(program, kVS, kFS);
glUseProgram(program);
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
EXPECT_GL_NO_ERROR();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
ASSERT_EGLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glDisable(GL_BLEND);
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_NO_ERROR();
glEnable(GL_BLEND);
glDrawArrays(GL_POINTS, 0, 1);
if (shouldBlend)
{
EXPECT_GL_NO_ERROR();
}
else
{
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
}
void TestDifferentStencilMaskAndRef(GLenum errIfMismatch); void TestDifferentStencilMaskAndRef(GLenum errIfMismatch);
// Called from RenderingFeedbackLoopWithDrawBuffersEXT. // Called from RenderingFeedbackLoopWithDrawBuffersEXT.
...@@ -2861,6 +2905,234 @@ TEST_P(WebGLCompatibilityTest, RGBA32FTextures) ...@@ -2861,6 +2905,234 @@ TEST_P(WebGLCompatibilityTest, RGBA32FTextures)
} }
} }
// Test that has float color attachment caching works when color attachments change, by calling draw
// command when blending is enabled
TEST_P(WebGLCompatibilityTest, FramebufferFloatColorAttachment)
{
if (getClientMajorVersion() >= 3)
{
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_EXT_color_buffer_float"));
}
else
{
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_OES_texture_float"));
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"));
}
constexpr char kVS[] =
"void main()\n"
"{\n"
" gl_Position = vec4(0, 0, 0, 1);\n"
"}\n";
constexpr char kFS[] =
"void main()\n"
"{\n"
" gl_FragColor = vec4(0, 1, 0, 1);\n"
"}\n";
ANGLE_GL_PROGRAM(program, kVS, kFS);
glUseProgram(program);
glEnable(GL_BLEND);
GLTexture texture1;
glBindTexture(GL_TEXTURE_2D, texture1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
EXPECT_GL_NO_ERROR();
GLTexture texture2;
glBindTexture(GL_TEXTURE_2D, texture2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
EXPECT_GL_NO_ERROR();
GLFramebuffer fbo1;
glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
GLFramebuffer fbo2;
glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glDisable(GL_BLEND);
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_NO_ERROR();
glEnable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
glDrawArrays(GL_POINTS, 0, 1);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0,
0); // test unbind
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glDisable(GL_BLEND);
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_NO_ERROR();
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, texture2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_NO_ERROR();
}
// Test that has float color attachment caching works with multiple color attachments bound to a
// Framebuffer
TEST_P(WebGLCompatibilityTest, FramebufferFloatColorAttachmentMRT)
{
bool isWebGL2 = getClientMajorVersion() >= 3;
if (isWebGL2)
{
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_EXT_color_buffer_float"));
constexpr char kVS[] =
"#version 300 es\n"
"void main()\n"
"{\n"
" gl_Position = vec4(0, 0, 0, 1);\n"
"}\n";
constexpr char kFS[] =
"#version 300 es\n"
"precision lowp float;\n"
"layout(location = 0) out vec4 o_color0;\n"
"layout(location = 1) out vec4 o_color1;\n"
"void main()\n"
"{\n"
" o_color0 = vec4(1, 0, 0, 1);\n"
" o_color1 = vec4(0, 1, 0, 1);\n"
"}\n";
ANGLE_GL_PROGRAM(program, kVS, kFS);
glUseProgram(program);
}
else
{
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_OES_texture_float"));
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"));
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_EXT_draw_buffers"));
constexpr char kVS[] =
"void main()\n"
"{\n"
" gl_Position = vec4(0, 0, 0, 1);\n"
"}\n";
constexpr char kFS[] =
"#extension GL_EXT_draw_buffers : require\n"
"precision lowp float;\n"
"void main()\n"
"{\n"
" gl_FragData[0] = vec4(1, 0, 0, 1);\n"
" gl_FragData[1] = vec4(0, 1, 0, 1);\n"
"}\n";
ANGLE_GL_PROGRAM(program, kVS, kFS);
glUseProgram(program);
}
glEnable(GL_BLEND);
GLTexture texture1;
glBindTexture(GL_TEXTURE_2D, texture1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
EXPECT_GL_NO_ERROR();
GLTexture texture2;
glBindTexture(GL_TEXTURE_2D, texture2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
EXPECT_GL_NO_ERROR();
GLTexture textureF1;
glBindTexture(GL_TEXTURE_2D, textureF1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
EXPECT_GL_NO_ERROR();
GLTexture textureF2;
glBindTexture(GL_TEXTURE_2D, textureF2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
EXPECT_GL_NO_ERROR();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2, 0);
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
if (isWebGL2)
{
glDrawBuffers(2, drawbuffers);
}
else
{
glDrawBuffersEXT(2, drawbuffers);
}
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_NO_ERROR();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureF1, 0);
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textureF2, 0);
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
if (isWebGL2)
{
// WebGL 1 will report a FRAMEBUFFER_UNSUPPORTED for one unsigned_byte and one float
// attachment bound to one FBO at the same time
glDrawBuffers(1, drawbuffers);
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_NO_ERROR();
glDrawBuffers(2, drawbuffers);
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2, 0);
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_NO_ERROR();
}
// Test if blending of float32 color attachment generates GL_INVALID_OPERATION when
// GL_EXT_float_blend is not enabled
TEST_P(WebGLCompatibilityTest, FloatBlend)
{
ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_EXT_float_blend"));
if (getClientMajorVersion() >= 3)
{
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_EXT_color_buffer_float"));
}
else
{
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_OES_texture_float"));
ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"));
}
TestExtFloatBlend(false);
glRequestExtensionANGLE("GL_EXT_float_blend");
ASSERT_GL_NO_ERROR();
TestExtFloatBlend(true);
}
TEST_P(WebGLCompatibilityTest, R16FTextures) TEST_P(WebGLCompatibilityTest, R16FTextures)
{ {
constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f}; constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f};
......
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