Commit 32f0dd6a by Geoff Lang Committed by Commit Bot

Add Queries and Setters for resource initialization state.

There are cases where we know that the next draw operation will fully initialize a texture/renderbuffer and we can save the robust resource init cost. Default all resource init state to Initialized, any redefinition will set it back to MayNeedInit. After setting an individual texture image to initialized, check if all images are now initialized and update the TextureState::mInitState to match. The cost of this check is only performed after initializing an image and allows future init checks to be faster. Bug: chromium:1132514 Change-Id: Ia23664ae162559d1614f1eb5643e24a491d87f7f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2475456 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent ed876984
......@@ -4,7 +4,7 @@ Name
Name Strings
GL_ANGLE_robust_resource_intialization
GL_ANGLE_robust_resource_initialization
Contributors
......@@ -59,6 +59,14 @@ New Tokens
ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x93A7
Accepted by the <pname> parameter of GetTexParameteriv,
GetTexParameterfv, GetTexLevelParameteriv, GetTexLevelParameterfv,
GetRenderbufferParameteriv, GetBufferParameteriv and
GetBufferParameteri64v:
RESOURCE_INITIALIZED_ANGLE 0x969F
Additions to Chapter 6 of the OpenGL ES 3.1 Specification (Buffer
Objects)
......@@ -70,6 +78,12 @@ Objects)
Otherwise, the contents of the buffer object's data store are
undefined.
Add to Table 6.2: Buffer object parameters and their values:
Name Type Initial Value Legal Values
---- ---- ------------- ------------
RESOURCE_INITIALIZED_ANGLE boolean TRUE TRUE, FALSE
Additions to Chapter 8 of the OpenGL ES 3.1 Specification (Textures and
Samplers)
......@@ -107,6 +121,17 @@ Samplers)
as for a call to the appropriate TexSubImage* call for <target>.
Otherwise, the contents of texels are undefined.
Add to Table 8.20: Texture parameters and their values:
Name Type Legal Values
---- ---- ------------
RESOURCE_INITIALIZED_ANGLE boolean TRUE, FALSE
Add to the end of section 8.10.3 "Texture Level Parameter Queries":
Queries of pname RESOURCE_INITIALIZED_ANGLE return the initialization
state of the image.
Additions to Chapter 9 of the OpenGL ES 3.1 Specification (Framebuffers
and Framebuffer Objects)
......@@ -120,6 +145,11 @@ and Framebuffer Objects)
channel of each sample; otherwise, the contents of the data store
are undefined.
Add to the end of section 9.2.6 "Renderbuffer Object Queries":
If pname is RESOURCE_INITIALIZED_ANGLE then params will contain the
initialization state of the renderbuffer currently bound to target.
Interactions with EGL_ANGLE_create_context_robust_resource_initialization
If the EGL window-system binding API is used to create a context,
......@@ -133,6 +163,40 @@ Interactions with EGL_ANGLE_create_context_robust_resource_initialization
query will return GL_TRUE as described above in section 2.6.1.1.
Otherwise queries will return GL_FALSE.
New State
(add to Table 20.4: Buffer Object State)
Initial
Get Value Type Get Command Value Description Sec.
---------------------- ---- ------------------- ------ --------------------------- ------
RESOURCE_INITIALIZED_ANGLE B GetBufferParameteriv TRUE Buffer data has been 6.6
initialized
(add to Table 20.9: Textures (state per texture object))
Initial
Get Value Type Get Command Value Description Sec.
---------------------- ---- ------------------- ------ --------------------------- ------
RESOURCE_INITIALIZED_ANGLE B GetTexParameteriv TRUE All specified images have 8.10.2
been initialized
(add to Table 20.10 Textures (state per texture image))
Initial
Get Value Type Get Command Value Description Sec.
---------------------- ---- ------------------- ------ --------------------------- ------
RESOURCE_INITIALIZED_ANGLE B GetTexLevelParameteriv TRUE Image data has been 8.10.3
initialized
(add to Table 20.16: Renderbuffer (state per renderbuffer object))
Initial
Get Value Type Get Command Value Description Sec.
---------------------- ---- ------------------- ------ --------------------------- ------
RESOURCE_INITIALIZED_ANGLE B GetRenderbufferParameteriv TRUE Renderbuffer data has been 9.2.6
initialized
Issues
None
......@@ -142,3 +206,4 @@ Revision History
Version 1, 2015/01/07 - first draft.
Version 2, 2017/03/07 - fixed EGL naming and added IsEnabled.
Version 3, 2017/09/19 - name cleanup.
Version 4, 2020/10/12 - Add RESOURCE_INITIALIZED_ANGLE queries.
......@@ -31,6 +31,7 @@ GL_APICALL void GL_APIENTRY glRequestExtensionANGLE (const GLchar *name);
#ifndef GL_ANGLE_robust_resource_initialization
#define GL_ANGLE_robust_resource_initialization 1
#define GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x93AB
#define GL_RESOURCE_INITIALIZED_ANGLE 0x969F
#endif /* GL_ANGLE_robust_resource_initialization */
#ifndef GL_ANGLE_provoking_vertex
......
......@@ -18,6 +18,7 @@
#include "libANGLE/IndexRangeCache.h"
#include "libANGLE/Observer.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/angletypes.h"
namespace rx
{
......@@ -135,6 +136,9 @@ class Buffer final : public RefCountObject<BufferID>,
GLboolean isImmutable() const { return mState.mImmutable; }
GLbitfield getStorageExtUsageFlags() const { return mState.mStorageExtUsageFlags; }
// Buffers are always initialized immediately when allocated
InitState initState() const { return InitState::Initialized; }
rx::BufferImpl *getImplementation() const { return mImpl; }
ANGLE_INLINE bool isBound() const { return mState.mBindingCount > 0; }
......
......@@ -428,6 +428,7 @@ MSG kRenderableInternalFormat = "SizedInternalformat must be color-renderable, d
MSG kRenderbufferNotBound = "A renderbuffer must be bound.";
MSG kResourceMaxRenderbufferSize = "Desired resource size is greater than max renderbuffer size.";
MSG kResourceMaxTextureSize = "Desired resource size is greater than max texture size.";
MSG kRobustResourceInitializationExtensionRequired = "EGL_ANGLE_robust_resource_initialization not enabled.";
MSG kSamplerFormatMismatch = "Mismatch between texture format and sampler type (signed/unsigned/float/shadow).";
MSG kSamplerUniformValueOutOfRange = "Sampler uniform value out of range.";
MSG kSamplesOutOfRange = "Samples must not be greater than maximum supported value for the format.";
......
......@@ -15,6 +15,7 @@
#include "libANGLE/Error.h"
#include "libANGLE/ImageIndex.h"
#include "libANGLE/Observer.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
......@@ -43,12 +44,6 @@ class FramebufferAttachmentObject;
class Renderbuffer;
class Texture;
enum class InitState
{
MayNeedInit,
Initialized,
};
// FramebufferAttachment implements a GL framebuffer attachment.
// Attachments are "light" containers, which store pointers to ref-counted GL objects.
// We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments.
......
......@@ -51,7 +51,7 @@ class ImageIndex
static ImageIndex Make2DArray(GLint levelIndex, GLint layerIndex = kEntireLevel);
static ImageIndex Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint layerCount);
static ImageIndex Make3D(GLint levelIndex, GLint layerIndex = kEntireLevel);
static ImageIndex MakeFromTarget(TextureTarget target, GLint levelIndex, GLint depth);
static ImageIndex MakeFromTarget(TextureTarget target, GLint levelIndex, GLint depth = 0);
static ImageIndex MakeFromType(TextureType type,
GLint levelIndex,
GLint layerIndex = kEntireLevel,
......
......@@ -34,7 +34,7 @@ RenderbufferState::RenderbufferState()
mFormat(GL_RGBA4),
mSamples(0),
mMultisamplingMode(MultisamplingMode::Regular),
mInitState(InitState::MayNeedInit)
mInitState(InitState::Initialized)
{}
RenderbufferState::~RenderbufferState() {}
......
......@@ -134,7 +134,7 @@ TextureState::TextureState(TextureType type)
mImageDescs((IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) * (type == TextureType::CubeMap ? 6 : 1)),
mCropRect(0, 0, 0, 0),
mGenerateMipmapHint(GL_FALSE),
mInitState(InitState::MayNeedInit),
mInitState(InitState::Initialized),
mCachedSamplerFormat(SamplerFormat::InvalidEnum),
mCachedSamplerCompareMode(GL_NONE),
mCachedSamplerFormatValid(false)
......@@ -554,7 +554,7 @@ GLuint TextureState::getEnabledLevelCount() const
}
ImageDesc::ImageDesc()
: ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::MayNeedInit)
: ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized)
{}
ImageDesc::ImageDesc(const Extents &size, const Format &format, const InitState initState)
......@@ -601,6 +601,27 @@ void TextureState::setImageDesc(TextureTarget target, size_t level, const ImageD
{
mInitState = InitState::MayNeedInit;
}
else
{
// Scan for any uninitialized images. If there are none, set the init state of the entire
// texture to initialized. The cost of the scan is only paid after doing image
// initialization which is already very expensive.
bool allImagesInitialized = true;
for (const ImageDesc &desc : mImageDescs)
{
if (desc.initState == InitState::MayNeedInit)
{
allImagesInitialized = false;
break;
}
}
if (allImagesInitialized)
{
mInitState = InitState::Initialized;
}
}
}
// Note that an ImageIndex that represents an entire level of a cube map corresponds to 6
......@@ -1951,6 +1972,19 @@ void Texture::setInitState(const ImageIndex &imageIndex, InitState initState)
}
}
void Texture::setInitState(InitState initState)
{
for (ImageDesc &imageDesc : mState.mImageDescs)
{
// Only modifiy defined images, undefined images will remain in the initialized state
if (!imageDesc.size.empty())
{
imageDesc.initState = initState;
}
}
mState.mInitState = initState;
}
bool Texture::doesSubImageNeedInit(const Context *context,
const ImageIndex &imageIndex,
const Box &area) const
......
......@@ -503,6 +503,7 @@ class Texture final : public RefCountObject<TextureID>,
InitState initState(const ImageIndex &imageIndex) const override;
InitState initState() const { return mState.mInitState; }
void setInitState(const ImageIndex &imageIndex, InitState initState) override;
void setInitState(InitState initState);
bool isBoundToFramebuffer(rx::Serial framebufferSerial) const
{
......
......@@ -43,6 +43,12 @@ enum class Command
Other
};
enum class InitState
{
MayNeedInit,
Initialized,
};
struct Rectangle
{
Rectangle() : x(0), y(0), width(0), height(0) {}
......
......@@ -212,6 +212,11 @@ void QueryTexLevelParameterBase(const Texture *texture,
*params =
CastFromStateValue<ParamType>(pname, texture->getLevelMemorySize(target, level));
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
*params = CastFromGLintStateValue<ParamType>(
pname, texture->initState(ImageIndex::MakeFromTarget(target, level)) ==
InitState::Initialized);
break;
default:
UNREACHABLE();
break;
......@@ -344,6 +349,10 @@ void QueryTexParameterBase(const Context *context,
*params =
CastFromGLintStateValue<ParamType>(pname, GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE);
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
*params = CastFromGLintStateValue<ParamType>(
pname, texture->initState() == InitState::Initialized);
break;
default:
UNREACHABLE();
break;
......@@ -450,6 +459,10 @@ void SetTexParameterBase(Context *context, Texture *texture, GLenum pname, const
case GL_TEXTURE_BORDER_COLOR:
texture->setBorderColor(context, ConvertToColor<isPureInteger>(params));
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
texture->setInitState(ConvertToBool(params[0]) ? InitState::Initialized
: InitState::MayNeedInit);
break;
default:
UNREACHABLE();
break;
......@@ -646,6 +659,10 @@ void QueryBufferParameterBase(const Buffer *buffer, GLenum pname, ParamType *par
case GL_BUFFER_STORAGE_FLAGS_EXT:
*params = CastFromGLintStateValue<ParamType>(pname, buffer->getStorageExtUsageFlags());
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
*params = CastFromStateValue<ParamType>(
pname, ConvertToGLBoolean(buffer->initState() == InitState::Initialized));
break;
default:
UNREACHABLE();
break;
......@@ -1377,6 +1394,9 @@ void QueryRenderbufferiv(const Context *context,
case GL_IMPLEMENTATION_COLOR_READ_TYPE:
*params = static_cast<GLint>(renderbuffer->getImplementationColorReadType(context));
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
*params = (renderbuffer->initState(ImageIndex()) == InitState::Initialized);
break;
default:
UNREACHABLE();
break;
......
......@@ -5293,6 +5293,15 @@ bool ValidateGetBufferParameterBase(const Context *context,
}
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
if (!context->getExtensions().robustResourceInitialization)
{
context->validationError(GL_INVALID_ENUM,
kRobustResourceInitializationExtensionRequired);
return false;
}
break;
default:
context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
return false;
......@@ -5368,6 +5377,15 @@ bool ValidateGetRenderbufferParameterivBase(const Context *context,
}
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
if (!context->getExtensions().robustResourceInitialization)
{
context->validationError(GL_INVALID_ENUM,
kRobustResourceInitializationExtensionRequired);
return false;
}
break;
default:
context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
return false;
......@@ -5595,6 +5613,15 @@ bool ValidateGetTexParameterBase(const Context *context,
}
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
if (!context->getExtensions().robustResourceInitialization)
{
context->validationError(GL_INVALID_ENUM,
kRobustResourceInitializationExtensionRequired);
return false;
}
break;
default:
context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
return false;
......@@ -6288,6 +6315,16 @@ bool ValidateTexParameterBase(const Context *context,
}
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
if (!context->getExtensions().robustResourceInitialization)
{
context->validationError(GL_INVALID_ENUM,
kRobustResourceInitializationExtensionRequired);
return false;
}
break;
default:
context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
return false;
......@@ -6811,7 +6848,6 @@ bool ValidateGetTexLevelParameterBase(const Context *context,
case GL_TEXTURE_BLUE_TYPE:
case GL_TEXTURE_ALPHA_TYPE:
case GL_TEXTURE_DEPTH_TYPE:
break;
case GL_TEXTURE_RED_SIZE:
case GL_TEXTURE_GREEN_SIZE:
case GL_TEXTURE_BLUE_SIZE:
......@@ -6819,17 +6855,24 @@ bool ValidateGetTexLevelParameterBase(const Context *context,
case GL_TEXTURE_DEPTH_SIZE:
case GL_TEXTURE_STENCIL_SIZE:
case GL_TEXTURE_SHARED_SIZE:
break;
case GL_TEXTURE_INTERNAL_FORMAT:
case GL_TEXTURE_WIDTH:
case GL_TEXTURE_HEIGHT:
case GL_TEXTURE_DEPTH:
break;
case GL_TEXTURE_SAMPLES:
case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
break;
case GL_TEXTURE_COMPRESSED:
break;
case GL_RESOURCE_INITIALIZED_ANGLE:
if (!context->getExtensions().robustResourceInitialization)
{
context->validationError(GL_INVALID_ENUM,
kRobustResourceInitializationExtensionRequired);
return false;
}
break;
default:
context->validationError(GL_INVALID_ENUM, kInvalidPname);
return false;
......
......@@ -331,6 +331,30 @@ TEST_P(RobustResourceInitTest, Queries)
EXPECT_GL_TRUE(glIsEnabled(GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE));
EXPECT_GL_NO_ERROR();
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
// Can't verify the init state after glTexImage2D, the implementation is free to initialize
// any time before the resource is read.
{
// Force to uninitialized
glTexParameteri(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, GL_FALSE);
GLint initState = 0;
glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
EXPECT_GL_FALSE(initState);
}
{
// Force to initialized
glTexParameteri(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, GL_TRUE);
GLint initState = 0;
glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
EXPECT_GL_TRUE(initState);
}
}
else
{
......@@ -384,6 +408,11 @@ TEST_P(RobustResourceInitTest, BufferData)
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
actual.data());
EXPECT_EQ(expected, actual);
GLint initState = 0;
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
EXPECT_GL_TRUE(initState);
}
// Regression test for passing a zero size init buffer with the extension.
......@@ -973,6 +1002,11 @@ TEST_P(RobustResourceInitTest, Texture)
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
GLint initState = 0;
glBindTexture(GL_TEXTURE_2D, texture);
glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
EXPECT_GL_TRUE(initState);
}
// Test that uploading texture data with an unpack state set correctly initializes the texture and
......@@ -1040,6 +1074,20 @@ void RobustResourceInitTestES3::testIntegerTextureInit(const char *samplerType,
// Blit from the texture to the framebuffer.
drawQuad(program, "position", 0.5f);
// Verify both textures have been initialized
{
GLint initState = 0;
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
EXPECT_GL_TRUE(initState);
}
{
GLint initState = 0;
glBindTexture(GL_TEXTURE_2D, texture);
glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
EXPECT_GL_TRUE(initState);
}
std::array<PixelT, kWidth * kHeight * 4> data;
glReadPixels(0, 0, kWidth, kHeight, GL_RGBA_INTEGER, type, data.data());
......@@ -1881,6 +1929,10 @@ TEST_P(RobustResourceInitTest, ClearWithScissor)
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::transparentBlack);
GLint initState = 0;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
EXPECT_GL_TRUE(initState);
}
// Tests that surfaces are initialized when they are created
......
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