Skip to content

Commit

Permalink
Implement support for rendering to 32-bit float textures on ES3
Browse files Browse the repository at this point in the history
On ES2 with OES_texture_float/OES_texture_half_float support, it is only possible to render to 16-bit half float textures using EXT_color_buffer_half_float. There's no support for rendering to 32-bit float textures in ES2 extensions. On ES3, rendering to some 32-bit float texture formats is exposed with EXT_color_buffer_float, but one must use the sized internal formats specified in ES3 core to do that. To expose this, a new command buffer extension is added which enables clients to directly use the sized internal format GL_RGBA32F.

A similar extension is also added to expose GL_RGB32F on desktop GL platforms for the sake of consistency.

These extensions are available whenever rendering to float textures is available. To support the current version of ANGLE, format conversions back to unsized internal formats are added to ui/gl.

Tests are added to cover this functionality. The new tests also add coverage for the handling of 32-bit float formats on ES2 and on desktop GL that existed before this patch.

BUG=329605
TEST=gpu_unittests, WebGL conformance tests

Review URL: https://codereview.chromium.org/139013008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251329 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
oetuaho@nvidia.com committed Feb 14, 2014
1 parent 768b8dc commit 17a9611
Show file tree
Hide file tree
Showing 24 changed files with 678 additions and 151 deletions.
64 changes: 64 additions & 0 deletions gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgb.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
Name

CHROMIUM_color_buffer_float_rgb

Name Strings

GL_CHROMIUM_color_buffer_float_rgb

Version

Last Modifed Date: February 7, 2014

Dependencies

This extension is written against the OpenGL ES 2.0 specification.

OpenGL ES 2.0 is required.

OES_texture_float is required.

Overview

This extension implements a subset of ARB_color_buffer_float on top of
OpenGL ES 2.0.

This extension enables rendering to floating point RGB textures. When
this extension is enabled:

* The 32-bit floating point type GL_RGB32F becomes available as a
color-renderable internal format. Textures created with type = FLOAT,
and internal format GL_RGB32F, can be attached to framebuffer object
color attachments for rendering.

* GL_RGB / GL_RGB32F becomes an allowable format / internalformat parameter
pair for TexImage2D. The restriction in section 3.7.1 of the OpenGL ES
2.0 spec that the internalformat parameter and format parameter of
TexImage2D must match is lifted for this case.

Floating point RGB textures may still be created also with the unsized
GL_RGB internal format, but whether such textures are renderable is not
guaranteed.

New Tokens

Accepted by the <internalformat> parameter of TexImage2D:

GL_RGB32F 0x8815

New Procedures and Functions

None.

Errors

None.

New State

None.

Revision History

2/7/2014 Documented the extension

64 changes: 64 additions & 0 deletions gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgba.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
Name

CHROMIUM_color_buffer_float_rgba

Name Strings

GL_CHROMIUM_color_buffer_float_rgba

Version

Last Modifed Date: February 7, 2014

Dependencies

This extension is written against the OpenGL ES 2.0 specification.

OpenGL ES 2.0 is required.

OES_texture_float is required.

Overview

This extension implements a subset of EXT_color_buffer_float on top of
OpenGL ES 2.0.

This extension enables rendering to floating point RGBA textures. When
this extension is enabled:

* The 32-bit floating point type GL_RGBA32F becomes available as a
color-renderable internal format. Textures created with type = FLOAT,
and internal format GL_RGBA32F, can be attached to framebuffer object
color attachments for rendering.

* GL_RGBA / GL_RGBA32F becomes an allowable format / internalformat
parameter pair for TexImage2D. The restriction in section 3.7.1 of the
OpenGL ES 2.0 spec that the internalformat parameter and format parameter
of TexImage2D must match is lifted for this case.

Floating point RGBA textures may still be created also with the unsized
GL_RGBA internal format, but whether such textures are renderable is not
guaranteed.

New Tokens

Accepted by the <internalformat> parameter of TexImage2D:

GL_RGBA32F 0x8814

New Procedures and Functions

None.

Errors

None.

New State

None.

Revision History

2/7/2014 Documented the extension

14 changes: 14 additions & 0 deletions gpu/GLES2/gl2extchromium.h
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,20 @@ typedef GLuint (GL_APIENTRYP PFNGLINSERTSYNCPOINTCHROMIUMPROC) ();
typedef void (GL_APIENTRYP PFNGLWAITSYNCPOINTCHROMIUMPROC) (GLuint sync_point);
#endif /* GL_CHROMIUM_sync_point */

#ifndef GL_CHROMIUM_color_buffer_float_rgba
#define GL_CHROMIUM_color_buffer_float_rgba 1
#ifndef GL_RGBA32F
#define GL_RGBA32F 0x8814
#endif
#endif /* GL_CHROMIUM_color_buffer_float_rgba */

#ifndef GL_CHROMIUM_color_buffer_float_rgb
#define GL_CHROMIUM_color_buffer_float_rgb 1
#ifndef GL_RGB32F
#define GL_RGB32F 0x8815
#endif
#endif /* GL_CHROMIUM_color_buffer_float_rgb */

#ifdef __cplusplus
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions gpu/command_buffer/service/context_group_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ TEST_F(ContextGroupTest, Basic) {

TEST_F(ContextGroupTest, InitializeNoExtensions) {
TestHelper::SetupContextGroupInitExpectations(gl_.get(),
DisallowedFeatures(), "");
DisallowedFeatures(), "", "");
group_->Initialize(decoder_.get(), DisallowedFeatures());
EXPECT_EQ(static_cast<uint32>(TestHelper::kNumVertexAttribs),
group_->max_vertex_attribs());
Expand Down Expand Up @@ -106,7 +106,7 @@ TEST_F(ContextGroupTest, InitializeNoExtensions) {
TEST_F(ContextGroupTest, MultipleContexts) {
scoped_ptr<MockGLES2Decoder> decoder2_(new MockGLES2Decoder());
TestHelper::SetupContextGroupInitExpectations(gl_.get(),
DisallowedFeatures(), "");
DisallowedFeatures(), "", "");
group_->Initialize(decoder_.get(), DisallowedFeatures());
group_->Initialize(decoder2_.get(), DisallowedFeatures());

Expand Down
90 changes: 79 additions & 11 deletions gpu/command_buffer/service/feature_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <set>

#include "base/command_line.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
Expand Down Expand Up @@ -99,7 +100,9 @@ void StringToWorkarounds(
} // anonymous namespace.

FeatureInfo::FeatureFlags::FeatureFlags()
: chromium_framebuffer_multisample(false),
: chromium_color_buffer_float_rgba(false),
chromium_color_buffer_float_rgb(false),
chromium_framebuffer_multisample(false),
use_core_framebuffer_multisample(false),
multisampled_render_to_texture(false),
use_img_for_multisampled_render_to_texture(false),
Expand Down Expand Up @@ -437,26 +440,28 @@ void FeatureInfo::InitializeFeatures() {
bool enable_texture_half_float = false;
bool enable_texture_half_float_linear = false;

bool have_arb_texture_float = extensions.Contains("GL_ARB_texture_float");
bool may_enable_chromium_color_buffer_float = false;

if (have_arb_texture_float) {
if (extensions.Contains("GL_ARB_texture_float")) {
enable_texture_float = true;
enable_texture_float_linear = true;
enable_texture_half_float = true;
enable_texture_half_float_linear = true;
may_enable_chromium_color_buffer_float = true;
} else {
if (extensions.Contains("GL_OES_texture_float") || have_arb_texture_float) {
if (extensions.Contains("GL_OES_texture_float")) {
enable_texture_float = true;
if (extensions.Contains("GL_OES_texture_float_linear") ||
have_arb_texture_float) {
if (extensions.Contains("GL_OES_texture_float_linear")) {
enable_texture_float_linear = true;
}
if ((is_es3 && extensions.Contains("GL_EXT_color_buffer_float")) ||
feature_flags_.is_angle) {
may_enable_chromium_color_buffer_float = true;
}
}
if (extensions.Contains("GL_OES_texture_half_float") ||
have_arb_texture_float) {
if (extensions.Contains("GL_OES_texture_half_float")) {
enable_texture_half_float = true;
if (extensions.Contains("GL_OES_texture_half_float_linear") ||
have_arb_texture_float) {
if (extensions.Contains("GL_OES_texture_half_float_linear")) {
enable_texture_half_float_linear = true;
}
}
Expand Down Expand Up @@ -490,6 +495,62 @@ void FeatureInfo::InitializeFeatures() {
}
}

if (may_enable_chromium_color_buffer_float) {
COMPILE_ASSERT(GL_RGBA32F_ARB == GL_RGBA32F &&
GL_RGBA32F_EXT == GL_RGBA32F &&
GL_RGB32F_ARB == GL_RGB32F &&
GL_RGB32F_EXT == GL_RGB32F,
sized_float_internal_format_variations_must_match);
// We don't check extension support beyond ARB_texture_float on desktop GL,
// and format support varies between GL configurations. For example, spec
// prior to OpenGL 3.0 mandates framebuffer support only for one
// implementation-chosen format, and ES3.0 EXT_color_buffer_float does not
// support rendering to RGB32F. Check for framebuffer completeness with
// formats that the extensions expose, and only enable an extension when a
// framebuffer created with its texture format is reported as complete.
GLint fb_binding = 0;
GLint tex_binding = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb_binding);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex_binding);

GLuint tex_id = 0;
GLuint fb_id = 0;
GLsizei width = 16;

glGenTextures(1, &tex_id);
glGenFramebuffersEXT(1, &fb_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
// Nearest filter needed for framebuffer completeness on some drivers.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0, GL_RGBA,
GL_FLOAT, NULL);
glBindFramebufferEXT(GL_FRAMEBUFFER, fb_id);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, tex_id, 0);
GLenum statusRGBA = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0, GL_RGB,
GL_FLOAT, NULL);
GLenum statusRGB = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
glDeleteFramebuffersEXT(1, &fb_id);
glDeleteTextures(1, &tex_id);

glBindFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLuint>(fb_binding));
glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(tex_binding));

DCHECK(glGetError() == GL_NO_ERROR);

if (statusRGBA == GL_FRAMEBUFFER_COMPLETE) {
validators_.texture_internal_format.AddValue(GL_RGBA32F);
feature_flags_.chromium_color_buffer_float_rgba = true;
AddExtensionString("GL_CHROMIUM_color_buffer_float_rgba");
}
if (statusRGB == GL_FRAMEBUFFER_COMPLETE) {
validators_.texture_internal_format.AddValue(GL_RGB32F);
feature_flags_.chromium_color_buffer_float_rgb = true;
AddExtensionString("GL_CHROMIUM_color_buffer_float_rgb");
}
}

// Check for multisample support
if (!disallowed_features_.multisampling &&
!workarounds_.disable_framebuffer_multisample) {
Expand Down Expand Up @@ -719,7 +780,14 @@ void FeatureInfo::InitializeFeatures() {
}

void FeatureInfo::AddExtensionString(const std::string& str) {
if (extensions_.find(str) == std::string::npos) {
size_t pos = extensions_.find(str);
while (pos != std::string::npos &&
pos + str.length() < extensions_.length() &&
extensions_.substr(pos + str.length(), 1) != " ") {
// This extension name is a substring of another.
pos = extensions_.find(str, pos + str.length());
}
if (pos == std::string::npos) {
extensions_ += (extensions_.empty() ? "" : " ") + str;
}
}
Expand Down
2 changes: 2 additions & 0 deletions gpu/command_buffer/service/feature_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> {
struct FeatureFlags {
FeatureFlags();

bool chromium_color_buffer_float_rgba;
bool chromium_color_buffer_float_rgb;
bool chromium_framebuffer_multisample;
// Use glBlitFramebuffer() and glRenderbufferStorageMultisample() with
// GL_EXT_framebuffer_multisample-style semantics, since they are exposed
Expand Down
17 changes: 17 additions & 0 deletions gpu/command_buffer/service/feature_info_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ TEST_F(FeatureInfoTest, InitializeNoExtensions) {
GL_DEPTH24_STENCIL8));
EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid(
GL_DEPTH_STENCIL));
EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid(
GL_RGBA32F));
EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid(
GL_RGB32F));
EXPECT_FALSE(info_->validators()->texture_format.IsValid(
GL_DEPTH_STENCIL));
EXPECT_FALSE(info_->validators()->pixel_type.IsValid(
Expand Down Expand Up @@ -407,6 +411,19 @@ TEST_F(FeatureInfoTest, InitializeEXT_read_format_bgra) {
GL_BGRA8_EXT));
}

TEST_F(FeatureInfoTest, InitializeARB_texture_float) {
SetupInitExpectations("GL_ARB_texture_float");
EXPECT_TRUE(info_->feature_flags().chromium_color_buffer_float_rgba);
EXPECT_TRUE(info_->feature_flags().chromium_color_buffer_float_rgb);
std::string extensions = info_->extensions() + " ";
EXPECT_THAT(extensions, HasSubstr("GL_CHROMIUM_color_buffer_float_rgb "));
EXPECT_THAT(extensions, HasSubstr("GL_CHROMIUM_color_buffer_float_rgba"));
EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid(
GL_RGBA32F));
EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid(
GL_RGB32F));
}

TEST_F(FeatureInfoTest, InitializeOES_texture_floatGLES2) {
SetupInitExpectations("GL_OES_texture_float");
EXPECT_FALSE(info_->feature_flags().enable_texture_float_linear);
Expand Down
Loading

0 comments on commit 17a9611

Please sign in to comment.