diff --git a/extensions/ANGLE_shader_pixel_local_storage.txt b/extensions/ANGLE_shader_pixel_local_storage.txt index 486ed6014..e5c226827 100644 --- a/extensions/ANGLE_shader_pixel_local_storage.txt +++ b/extensions/ANGLE_shader_pixel_local_storage.txt @@ -134,9 +134,9 @@ New Procedures and Functions void FramebufferPixelLocalClearValue{f,i,ui}vANGLE(int plane, const T value[4]) - void BeginPixelLocalStorageANGLE(sizei planes, const enum loadops[]) + void BeginPixelLocalStorageANGLE(sizei n, const enum loadops[]) - void EndPixelLocalStorageANGLE() + void EndPixelLocalStorageANGLE(sizei n, const enum storeops[]) void PixelLocalStorageBarrierANGLE() @@ -207,23 +207,20 @@ Additions to the OpenGL ES Specification, Version 3.0.6 Pixel local storage is activated and deactivated for the current draw framebuffer using the commands: - void BeginPixelLocalStorageANGLE(sizei planes, const enum loadops[]) + void BeginPixelLocalStorageANGLE(sizei n, const enum loadops[]) - void EndPixelLocalStorageANGLE() + void EndPixelLocalStorageANGLE(sizei n, const enum storeops[]) Parameters: - * specifies the number of pixel local storage planes to activate. - Specifically, the pixel local storage planes indexed in the - range [0, planes - 1] on the current draw framebuffer will be - activated. + * specifies the length of the or array. - * specifies an array of pixel local storage "Load Operations", - whose length is equal to , and whose ith element - describes the Load Operation to perform on the ith pixel local - storage plane. Possible Load Operations are listed in Table - X.1. Load Operations are performed on the entire area of each - plane, irrespective of scissor or viewport state. + * specifies an array of pixel local storage "Load + Operations", whose ith element describes the Load Operation to + perform on the ith pixel local storage plane. Supported Load + Operations are listed in Table X.1. Load Operations are + performed on the entire area of each plane, irrespective of + scissor or viewport state. Load Operation Description ----------------------------------------------------------------------- @@ -257,10 +254,28 @@ Additions to the OpenGL ES Specification, Version 3.0.6 DISABLE_ANGLE Leave this plane disabled. Note that all pixel local storage planes on or after - index are disabled implicitly. + index are disabled implicitly. Table X.1: Pixel local storage Load Operations. + * specifies an array of pixel local storage "Store + Operations", whose ith element describes the Store Operation + to perform on the backing texture of the ith pixel local + storage plane. The store operation is ignored if its plane is + memoryless or disabled. Supported Store Operations are listed + in Table X.2. + + Store Operation Description + ----------------------------------------------------------------------- + KEEP Update the the bound texture image to reflect the + pixel local storage contents. + + DONT_CARE Leave the bound texture image contents undefined, + with the caveat that they are either unchanged, or + not leaked from outside the current draw framebuffer. + + Table X.2: Pixel local storage Store Operations. + Errors generated by BeginPixelLocalStorageANGLE(): * INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer @@ -281,7 +296,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * INVALID_OPERATION is generated if SAMPLE_COVERAGE is enabled. * INVALID_VALUE is generated if - < 1 or > MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. + < 1 or > MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. * INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to any color attachment point on or after: @@ -293,20 +308,19 @@ Additions to the OpenGL ES Specification, Version 3.0.6 an image attached to any color attachment point on or after: COLOR_ATTACHMENT0 + - MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - - + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - * INVALID_VALUE is generated if is NULL. - * INVALID_ENUM is generated if [0..-1] is not one of the - Load Operations enumerated in Table X.1. + * INVALID_ENUM is generated if [0..-1] is not one of the Load + Operations enumerated in Table X.1. - * INVALID_OPERATION is generated if [0..-1] is not + * INVALID_OPERATION is generated if [0..-1] is not DISABLE_ANGLE, and the pixel local storage plane at that same index is in a deinitialized state. - * INVALID_OPERATION is generated if [0..-1] is KEEP and - the pixel local storage plane at that same index is memoryless. + * INVALID_OPERATION is generated if [0..-1] is KEEP and the + pixel local storage plane at that same index is memoryless. * INVALID_OPERATION is generated if all enabled, texture-backed pixel local storage planes do not have the same width and height. @@ -335,16 +349,25 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is zero. - After a successful call to BeginPixelLocalStorageANGLE(), - PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is equal to , and the - specified pixel local storage planes are fully initialized and available for - fragment shaders to read and write. This data will persist across all - fragment invocations and across all draws issued until the application calls - EndPixelLocalStorageANGLE(), even if the application binds different shader - programs. In order to make this guarantee, the the OpenGL ES API only allows - a limited set of commands while PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is - nonzero. All other commands generate INVALID_OPERATION. Valid commands while - pixel local storage is active are listed in Table X.2. + * INVALID_VALUE is generated if + != PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE. + + * INVALID_ENUM is generated if + [0..PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE-1] is not one of + the Store Operations enumerated in Table X.2. + + After a successful call to BeginPixelLocalStorageANGLE(), the pixel local + storage planes indexed in the range [0..-1] (except those whose Load + Operation was GL_DISABLE_ANGLE) are fully activated, initialized and + available for fragment shaders to read and write. + PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is also updated to equal . Pixel + local storage data will persist across all fragment invocations and across + all draws issued until the application calls EndPixelLocalStorageANGLE(), + even if the application binds different shader programs. In order to make + this guarantee, the the OpenGL ES API only allows a limited set of commands + while PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is nonzero. All other commands + generate INVALID_OPERATION. Valid commands while pixel local storage is + active are listed in Table X.3. ActiveTexture DepthMask MapBufferRange BindBuffer DepthRangef PixelLocalStorageBarrierANGLE @@ -365,7 +388,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 CullFace Is* DepthFunc Viewport - Table X.2: Valid commands while PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE + Table X.3: Valid commands while PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is nonzero. Additional restrictions also go into effect when @@ -419,7 +442,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 shader that has a pixel local storage uniform whose format layout qualifier does not identically match the internalformat of its associated pixel local storage plane on the current draw framebuffer, as - enumerated in Table X.3. + enumerated in Table X.4. Because of the "implementation-dependent" clause of the framebuffer completeness test, and because a pixel local storage implementation may add @@ -487,7 +510,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 * identifies the pixel local storage plane index. - * selects the data format, as enumerated in Table X.3. + * selects the data format, as enumerated in Table X.4. internalformat Clear Value Type Pixel Local Type format qualifier ----------------------------------------------------------------------- @@ -497,7 +520,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 R32F FLOAT pixelLocalANGLE r32f R32UI UNSIGNED_INT upixelLocalANGLE r32ui - Table X.3: Supported pixel local storage internalformats, with the Clear + Table X.4: Supported pixel local storage internalformats, with the Clear Value Type used by BeginPixelLocalStorageANGLE(), and their required corresponding GLSL Pixel Local Type and format layout qualifier. @@ -519,7 +542,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 < 0 or >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. * INVALID_ENUM is generated if is not one of the - acceptable values in Table X.3, or NONE. + acceptable values in Table X.4, or NONE. If is NONE, the pixel local storage plane at index is deinitialized and any internal storage is released. @@ -568,7 +591,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 - Zero if is a GL_TEXTURE_2D - The Cube Map Face to bind if is a - GL_TEXTURE_CUBE_MAP, as enumerated in Table X.3 + GL_TEXTURE_CUBE_MAP, as enumerated in Table X.4 Cube Map Face -------------------------------------- @@ -579,7 +602,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 4 TEXTURE_CUBE_MAP_POSITIVE_Z 5 TEXTURE_CUBE_MAP_NEGATIVE_Z - Table X.3: numbers of cube map texture faces. The layers are + Table X.4: numbers of cube map texture faces. The layers are numbered in the same sequence as the cube map face token values. - The array index to bind if is a GL_TEXTURE_2D_ARRAY @@ -616,7 +639,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 >= the immutable number of texture layers in . * INVALID_ENUM is generated if is nonzero and its - internalformat is not one of the acceptable values in Table X.3. + internalformat is not one of the acceptable values in Table X.4. If is 0, and are ignored and the pixel local storage plane is deinitialized. @@ -635,7 +658,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 clear values: a 4-component vector of type FLOAT, INT, and UNSIGNED_INT. When the Load Operation CLEAR_ANGLE is executed, a pixel local storage plane is cleared to the value whose type corresponds to its internalformat. (See - Table X.3.) Clear values are set with the commands: + Table X.4.) Clear values are set with the commands: void FramebufferPixelLocalClearValuefvANGLE(int plane, const float value[4]) @@ -693,7 +716,7 @@ Additions to the OpenGL ES Specification, Version 3.0.6 Description: * If is PIXEL_LOCAL_FORMAT_ANGLE, will contain the - internalformat of the plane from Table X.3, or NONE if the selected + internalformat of the plane from Table X.4, or NONE if the selected pixel local storage plane is in a deinitialized state. * If is PIXEL_LOCAL_TEXTURE_NAME_ANGLE, will contain the @@ -901,12 +924,12 @@ Additions to the OpenGL ES Shading Language Specification, Version 3.00 binding = - Accepable identifiers for are enumerated in Table X.3. + Accepable identifiers for are enumerated in Table X.4. It is a compile-time error to declare a pixel local storage uniform that does not specify both of these layout qualifiers, or to specify a format layout qualifier on any type other than that format's corresponding "Pixel - Local Type", as enumerated in Table X.3. + Local Type", as enumerated in Table X.4. Modify Section 8 "Built-in Functions" diff --git a/include/GLES2/gl2ext_angle.h b/include/GLES2/gl2ext_angle.h index fbd325794..0c0b032bc 100644 --- a/include/GLES2/gl2ext_angle.h +++ b/include/GLES2/gl2ext_angle.h @@ -603,8 +603,8 @@ typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREPIXELLOCALSTORAGEANGLEPROC) (G typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALCLEARVALUEFVANGLEPROC) (GLint plane, const GLfloat value[4]); typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALCLEARVALUEIVANGLEPROC) (GLint plane, const GLint value[4]); typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALCLEARVALUEUIVANGLEPROC) (GLint plane, const GLuint value[4]); -typedef void (GL_APIENTRYP PFNGLBEGINPIXELLOCALSTORAGEANGLEPROC) (GLsizei planes, const GLenum loadops[]); -typedef void (GL_APIENTRYP PFNGLENDPIXELLOCALSTORAGEANGLEPROC) (void); +typedef void (GL_APIENTRYP PFNGLBEGINPIXELLOCALSTORAGEANGLEPROC) (GLsizei n, const GLenum loadops[]); +typedef void (GL_APIENTRYP PFNGLENDPIXELLOCALSTORAGEANGLEPROC) (GLsizei n, const GLenum storeops[]); typedef void (GL_APIENTRYP PFNGLPIXELLOCALSTORAGEBARRIERANGLEPROC) (void); typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERFVANGLEPROC) (GLint plane, GLenum pname, GLfloat* params); typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGEPARAMETERIVANGLEPROC) (GLint plane, GLenum pname, GLint* params); @@ -614,8 +614,8 @@ GL_APICALL void GL_APIENTRY glFramebufferTexturePixelLocalStorageANGLE (GLint pl GL_APICALL void GL_APIENTRY glFramebufferPixelLocalClearValuefvANGLE (GLint plane, const GLfloat value[4]); GL_APICALL void GL_APIENTRY glFramebufferPixelLocalClearValueivANGLE (GLint plane, const GLint value[4]); GL_APICALL void GL_APIENTRY glFramebufferPixelLocalClearValueuivANGLE (GLint plane, const GLuint value[4]); -GL_APICALL void GL_APIENTRY glBeginPixelLocalStorageANGLE (GLsizei planes, const GLenum loadops[]); -GL_APICALL void GL_APIENTRY glEndPixelLocalStorageANGLE (void); +GL_APICALL void GL_APIENTRY glBeginPixelLocalStorageANGLE (GLsizei n, const GLenum loadops[]); +GL_APICALL void GL_APIENTRY glEndPixelLocalStorageANGLE (GLsizei n, const GLenum storeops[]); GL_APICALL void GL_APIENTRY glPixelLocalStorageBarrierANGLE (void); GL_APICALL void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterfvANGLE (GLint plane, GLenum pname, GLfloat* params); GL_APICALL void GL_APIENTRY glGetFramebufferPixelLocalStorageParameterivANGLE (GLint plane, GLenum pname, GLint* params); diff --git a/scripts/code_generation_hashes/Extension_files.json b/scripts/code_generation_hashes/Extension_files.json index 56b5c5ff7..0e44f4bdf 100644 --- a/scripts/code_generation_hashes/Extension_files.json +++ b/scripts/code_generation_hashes/Extension_files.json @@ -20,7 +20,7 @@ "scripts/extension_data/swiftshader_win10_gles1.json": "fbf1c3dc83570c1e3fffdbee313bca30", "scripts/gl_angle_ext.xml": - "14d2478f5d85d15ead185182686805a9", + "87693dfe98fd0359b586d8665fc1c22b", "scripts/registry_xml.py": "4837b4beda7a0e2698e2be7e8e74fd88", "src/libANGLE/gen_extensions.py": diff --git a/scripts/code_generation_hashes/GL_EGL_WGL_loader.json b/scripts/code_generation_hashes/GL_EGL_WGL_loader.json index d5c6bdd24..6bca500d7 100644 --- a/scripts/code_generation_hashes/GL_EGL_WGL_loader.json +++ b/scripts/code_generation_hashes/GL_EGL_WGL_loader.json @@ -4,7 +4,7 @@ "scripts/generate_loader.py": "93c78a8d11323fa311fed5118fbcf083", "scripts/gl_angle_ext.xml": - "14d2478f5d85d15ead185182686805a9", + "87693dfe98fd0359b586d8665fc1c22b", "scripts/registry_xml.py": "4837b4beda7a0e2698e2be7e8e74fd88", "src/libEGL/egl_loader_autogen.cpp": diff --git a/scripts/code_generation_hashes/GL_EGL_entry_points.json b/scripts/code_generation_hashes/GL_EGL_entry_points.json index e9f5543f1..af2091753 100644 --- a/scripts/code_generation_hashes/GL_EGL_entry_points.json +++ b/scripts/code_generation_hashes/GL_EGL_entry_points.json @@ -8,7 +8,7 @@ "scripts/generate_entry_points.py": "0ea0e8dc52c8d2dd3be1430c36a5ceba", "scripts/gl_angle_ext.xml": - "14d2478f5d85d15ead185182686805a9", + "87693dfe98fd0359b586d8665fc1c22b", "scripts/registry_xml.py": "4837b4beda7a0e2698e2be7e8e74fd88", "src/common/entry_points_enum_autogen.cpp": @@ -38,7 +38,7 @@ "src/libANGLE/Context_gles_3_2_autogen.h": "48567dca16fd881dfe6d61fee0e3106f", "src/libANGLE/Context_gles_ext_autogen.h": - "4023219c94052b39d5706cbc5f9263d9", + "49426ac7b35f10b15269e0477288a21d", "src/libANGLE/capture/capture_egl_autogen.cpp": "592bc4286183e250f28218ee8c4d2d51", "src/libANGLE/capture/capture_egl_autogen.h": @@ -80,9 +80,9 @@ "src/libANGLE/capture/capture_gles_3_2_autogen.h": "74ed7366af3a46c0661397cfa29ec6fc", "src/libANGLE/capture/capture_gles_ext_autogen.cpp": - "e86b5bb2400c09ffcb195d1e24f9852e", + "d7a20279e3ca56d60c8770e55c0b3084", "src/libANGLE/capture/capture_gles_ext_autogen.h": - "d8cad3fc32723e76f222387beea5809b", + "913f92c87ee79be0f355a3e1b00adaef", "src/libANGLE/validationCL_autogen.h": "0022d0cdb6a9e2ef4a59b71164f62333", "src/libANGLE/validationEGL_autogen.h": @@ -98,7 +98,7 @@ "src/libANGLE/validationES3_autogen.h": "d34affed6670d9748af70c9b2d9b6f05", "src/libANGLE/validationESEXT_autogen.h": - "a6bee3ac05d4f66f6cd5807959b6137a", + "18f4ce8791ef46fb2bb32e04f21a837f", "src/libANGLE/validationGL1_autogen.h": "a247dddc40418180d4b2dbefeb75f233", "src/libANGLE/validationGL2_autogen.h": @@ -168,11 +168,11 @@ "src/libGLESv2/entry_points_gles_3_2_autogen.h": "647f932a299cdb4726b60bbba059f0d2", "src/libGLESv2/entry_points_gles_ext_autogen.cpp": - "52ff856150b1ccf798e3d65e5f1ddf3d", + "350ea50a505ed9b66d1f7583d03bbab2", "src/libGLESv2/entry_points_gles_ext_autogen.h": - "e8c89e9b23579b0bb1a0bac9c20db5b8", + "e75a63a77c6b6029b6a201489186daa8", "src/libGLESv2/libGLESv2_autogen.cpp": - "8251921aec777c0b8e268d86b2669ecc", + "4a8a294255a7b8fb34f7e8033ac75b6f", "src/libGLESv2/libGLESv2_autogen.def": "97dc41a4eaf03db22435900b9499f554", "src/libGLESv2/libGLESv2_no_capture_autogen.def": @@ -192,5 +192,5 @@ "third_party/OpenGL-Registry/src/xml/wgl.xml": "eae784bf4d1b983a42af5671b140b7c4", "util/capture/frame_capture_replay_autogen.cpp": - "2ca1891e5ce93f49ee5c47afb283267d" + "3aa01eddde135a7e088435560f702f03" } \ No newline at end of file diff --git a/scripts/code_generation_hashes/GLenum_value_to_string_map.json b/scripts/code_generation_hashes/GLenum_value_to_string_map.json index 4358328f9..36f65121f 100644 --- a/scripts/code_generation_hashes/GLenum_value_to_string_map.json +++ b/scripts/code_generation_hashes/GLenum_value_to_string_map.json @@ -2,7 +2,7 @@ "scripts/gen_gl_enum_utils.py": "9663ad2fbaec42c7d3e83f440b0fee67", "scripts/gl_angle_ext.xml": - "14d2478f5d85d15ead185182686805a9", + "87693dfe98fd0359b586d8665fc1c22b", "scripts/registry_xml.py": "4837b4beda7a0e2698e2be7e8e74fd88", "src/common/gl_enum_utils_autogen.cpp": diff --git a/scripts/code_generation_hashes/proc_table.json b/scripts/code_generation_hashes/proc_table.json index 9df8fb336..cdb7d1184 100644 --- a/scripts/code_generation_hashes/proc_table.json +++ b/scripts/code_generation_hashes/proc_table.json @@ -4,7 +4,7 @@ "scripts/gen_proc_table.py": "073351265b085943f816498cecaa281c", "scripts/gl_angle_ext.xml": - "14d2478f5d85d15ead185182686805a9", + "87693dfe98fd0359b586d8665fc1c22b", "scripts/registry_xml.py": "4837b4beda7a0e2698e2be7e8e74fd88", "src/libGLESv2/proc_table_cl_autogen.cpp": diff --git a/scripts/gl_angle_ext.xml b/scripts/gl_angle_ext.xml index f6245702e..3fd347b59 100644 --- a/scripts/gl_angle_ext.xml +++ b/scripts/gl_angle_ext.xml @@ -982,11 +982,13 @@ void glBeginPixelLocalStorageANGLE - GLsizei planes - const GLenum *loadops + GLsizei n + const GLenum *loadops void glEndPixelLocalStorageANGLE + GLsizei n + const GLenum *storeops void glPixelLocalStorageBarrierANGLE diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp index 78b471af3..ff8be16ff 100644 --- a/src/libANGLE/Context.cpp +++ b/src/libANGLE/Context.cpp @@ -9235,23 +9235,23 @@ void Context::framebufferPixelLocalClearValueuiv(GLint plane, const GLuint value pls.setClearValueui(plane, value); } -void Context::beginPixelLocalStorage(GLsizei planes, const GLenum loadops[]) +void Context::beginPixelLocalStorage(GLsizei n, const GLenum loadops[]) { Framebuffer *framebuffer = mState.getDrawFramebuffer(); ASSERT(framebuffer); PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this); - pls.begin(this, planes, loadops); - mState.setPixelLocalStorageActivePlanes(planes); + pls.begin(this, n, loadops); + mState.setPixelLocalStorageActivePlanes(n); } -void Context::endPixelLocalStorage() +void Context::endPixelLocalStorage(GLsizei n, const GLenum storeops[]) { Framebuffer *framebuffer = mState.getDrawFramebuffer(); ASSERT(framebuffer); PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this); - pls.end(this); + pls.end(this, storeops); mState.setPixelLocalStorageActivePlanes(0); } @@ -10033,13 +10033,13 @@ void Context::drawPixelLocalStorageEXTEnable(GLsizei n, } void Context::drawPixelLocalStorageEXTDisable(const PixelLocalStoragePlane planes[], - const GLenum loadops[]) + const GLenum storeops[]) { ASSERT(mImplementation->getNativePixelLocalStorageType() == ShPixelLocalStorageType::PixelLocalStorageEXT); ANGLE_CONTEXT_TRY(syncState(mPixelLocalStorageEXTEnableDisableDirtyBits, mPixelLocalStorageEXTEnableDisableDirtyObjects, Command::Draw)); - ANGLE_CONTEXT_TRY(mImplementation->drawPixelLocalStorageEXTDisable(this, planes, loadops)); + ANGLE_CONTEXT_TRY(mImplementation->drawPixelLocalStorageEXTDisable(this, planes, storeops)); } // ErrorSet implementation. diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h index 9fbc4b9fd..2178a25df 100644 --- a/src/libANGLE/Context.h +++ b/src/libANGLE/Context.h @@ -687,7 +687,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl // GL_SHADER_PIXEL_LOCAL_STORAGE_EXT. // // The implementation's ShPixelLocalStorageType must be "PixelLocalStorageEXT". - void drawPixelLocalStorageEXTDisable(const PixelLocalStoragePlane[], const GLenum loadops[]); + void drawPixelLocalStorageEXTDisable(const PixelLocalStoragePlane[], const GLenum storeops[]); private: void initializeDefaultResources(); diff --git a/src/libANGLE/Context_gles_ext_autogen.h b/src/libANGLE/Context_gles_ext_autogen.h index 0f7a19988..c2b400731 100644 --- a/src/libANGLE/Context_gles_ext_autogen.h +++ b/src/libANGLE/Context_gles_ext_autogen.h @@ -573,8 +573,8 @@ void framebufferPixelLocalClearValuefv(GLint plane, const GLfloat *value); \ void framebufferPixelLocalClearValueiv(GLint plane, const GLint *value); \ void framebufferPixelLocalClearValueuiv(GLint plane, const GLuint *value); \ - void beginPixelLocalStorage(GLsizei planes, const GLenum *loadops); \ - void endPixelLocalStorage(); \ + void beginPixelLocalStorage(GLsizei n, const GLenum *loadops); \ + void endPixelLocalStorage(GLsizei n, const GLenum *storeops); \ void pixelLocalStorageBarrier(); \ void getFramebufferPixelLocalStorageParameterfv(GLint plane, GLenum pname, GLfloat *params); \ void getFramebufferPixelLocalStorageParameteriv(GLint plane, GLenum pname, GLint *params); \ diff --git a/src/libANGLE/ErrorStrings.h b/src/libANGLE/ErrorStrings.h index a1e28831f..2726836be 100644 --- a/src/libANGLE/ErrorStrings.h +++ b/src/libANGLE/ErrorStrings.h @@ -494,13 +494,15 @@ MSG kPLSEnablingDeinitializedPlane = "Attempted to enable a pixel local storage MSG kPLSExtensionNotEnabled = "GL_ANGLE_shader_pixel_local_storage not enabled."; MSG kPLSInactive = "Pixel local storage is not active."; MSG kPLSInvalidInternalformat = "Invalid pixel local storage internal format."; -MSG kPLSInvalidLoadOperation = "Invalid pixel local storage Load Operation."; +MSG kPLSInvalidLoadOperation = "Invalid pixel local storage Load Operation: 0x%04X."; +MSG kPLSInvalidStoreOperation = "Invalid pixel local storage Store Operation: 0x%04X."; MSG kPLSInvalidTextureType = "Invalid pixel local storage texture type."; MSG kPLSKeepingMemorylessPlane = "Load Operation GL_KEEP is invalid for memoryless planes."; MSG kPLSMaxColorAttachmentsExceded = "Framebuffer cannot have images attached to color attachment points on or after COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE."; -MSG kPLSMaxCombinedDrawBuffersAndPlanesExceded = "Framebuffer cannot have images attached to color attachment points on or after COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - ."; +MSG kPLSMaxCombinedDrawBuffersAndPlanesExceded = "Framebuffer cannot have images attached to color attachment points on or after COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - ."; MSG kPLSMismatchedBackingTextureSizes = "Mismatched pixel local storage backing texture sizes."; MSG kPLSMultisamplingEnabled = "Attempted to begin pixel local storage with a multisampled framebuffer."; +MSG kPLSNNotEqualActivePlanes = " != ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE"; MSG kPLSNoAttachmentsNoTextureBacked = "Draw framebuffer has no attachments and no enabled, texture-backed pixel local storage planes."; MSG kPLSNullLoadOps = "loadops cannot null."; MSG kPLSPlaneLessThanZero = "Plane cannot be less than 0."; @@ -508,7 +510,7 @@ MSG kPLSPlaneOutOfRange = "Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PL MSG kPLSPlanesLessThanOne = "Planes must be greater than 0."; MSG kPLSPlanesOutOfRange = "Planes must be less than or equal to GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE."; MSG kPLSRasterizerDiscardEnabled = "Attempted to begin pixel local storage with GL_RASTERIZER_DISCARD enabled."; -MSG kPLSReservedDrawBufferInUse = "When beginning pixel local storage, glDrawBuffers must all be GL_NONE at indices greater than or equal to: min(GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PLS_ANGLE, GL_MAX_COMBINED_DRAW_BUFFERS_AND_PLS_PLANES_ANGLE - )."; +MSG kPLSReservedDrawBufferInUse = "When beginning pixel local storage, glDrawBuffers must all be GL_NONE at indices greater than or equal to: min(GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PLS_ANGLE, GL_MAX_COMBINED_DRAW_BUFFERS_AND_PLS_PLANES_ANGLE - )."; MSG kPLSSampleAlphaToCoverageEnabled = "Attempted to begin pixel local storage with GL_SAMPLE_ALPHA_TO_COVERAGE enabled."; MSG kPLSSampleCoverageEnabled = "Attempted to begin pixel local storage with GL_SAMPLE_COVERAGE enabled."; MSG kPointSizeArrayExtensionNotEnabled = "GL_OES_point_size_array not enabled."; diff --git a/src/libANGLE/PixelLocalStorage.cpp b/src/libANGLE/PixelLocalStorage.cpp index 5ff516d0e..f596d2982 100644 --- a/src/libANGLE/PixelLocalStorage.cpp +++ b/src/libANGLE/PixelLocalStorage.cpp @@ -238,7 +238,7 @@ bool PixelLocalStoragePlane::getTextureImageExtents(const Context *context, Exte return true; } -void PixelLocalStoragePlane::ensureBackingIfMemoryless(Context *context, Extents plsExtents) +void PixelLocalStoragePlane::ensureBackingTextureIfMemoryless(Context *context, Extents plsExtents) { ASSERT(!isDeinitialized()); ASSERT(!isTextureIDDeleted(context)); // Convert to memoryless first in this case. @@ -284,11 +284,10 @@ void PixelLocalStoragePlane::ensureBackingIfMemoryless(Context *context, Extents void PixelLocalStoragePlane::attachToDrawFramebuffer(Context *context, Extents plsExtents, - GLenum colorAttachment) + GLenum colorAttachment) const { ASSERT(!isDeinitialized()); - ensureBackingIfMemoryless(context, plsExtents); - ASSERT(mTextureRef != nullptr); + ASSERT(mTextureRef != nullptr); // Call ensureBackingTextureIfMemoryless() first! if (mTextureImageIndex.usesTex3D()) // GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY. { context->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, colorAttachment, mTextureRef->id(), @@ -393,11 +392,10 @@ void PixelLocalStoragePlane::issueClearCommand(ClearCommands *clearCommands, void PixelLocalStoragePlane::bindToImage(Context *context, Extents plsExtents, GLuint unit, - bool needsR32Packing) + bool needsR32Packing) const { ASSERT(!isDeinitialized()); - ensureBackingIfMemoryless(context, plsExtents); - ASSERT(mTextureRef != nullptr); + ASSERT(mTextureRef != nullptr); // Call ensureBackingTextureIfMemoryless() first! GLenum imageBindingFormat = mInternalformat; if (needsR32Packing) { @@ -433,7 +431,10 @@ const Texture *PixelLocalStoragePlane::getBackingTexture(const Context *context) return mTextureRef; } -PixelLocalStorage::PixelLocalStorage() {} +PixelLocalStorage::PixelLocalStorage(MemorylessBackingType memorylessBackingType) + : mMemorylessBackingType(memorylessBackingType) +{} + PixelLocalStorage::~PixelLocalStorage() {} void PixelLocalStorage::onFramebufferDestroyed(const Context *context) @@ -470,7 +471,7 @@ void PixelLocalStorage::begin(Context *context, GLsizei n, const GLenum loadops[ // storage rendering dimensions. Extents plsExtents; bool hasPLSExtents = false; - for (int i = 0; i < n; ++i) + for (GLsizei i = 0; i < n; ++i) { if (loadops[i] == GL_DISABLE_ANGLE) { @@ -497,13 +498,32 @@ void PixelLocalStorage::begin(Context *context, GLsizei n, const GLenum loadops[ context->getState().getDrawFramebuffer()->getState().getAttachmentExtentsIntersection(); ASSERT(plsExtents.depth == 0); } + for (GLsizei i = 0; i < n; ++i) + { + if (loadops[i] == GL_DISABLE_ANGLE) + { + continue; + } + PixelLocalStoragePlane &plane = mPlanes[i]; + if (mMemorylessBackingType == MemorylessBackingType::InternalTextures) + { + plane.ensureBackingTextureIfMemoryless(context, plsExtents); + } + plane.markActive(true); + } onBegin(context, n, loadops, plsExtents); } -void PixelLocalStorage::end(Context *context) +void PixelLocalStorage::end(Context *context, const GLenum storeops[]) { - onEnd(context); + onEnd(context, storeops); + + GLsizei n = context->getState().getPixelLocalStorageActivePlanes(); + for (GLsizei i = 0; i < n; ++i) + { + mPlanes[i].markActive(false); + } } void PixelLocalStorage::barrier(Context *context) @@ -518,7 +538,10 @@ namespace class PixelLocalStorageImageLoadStore : public PixelLocalStorage { public: - PixelLocalStorageImageLoadStore(bool needsR32Packing) : mNeedsR32Packing(needsR32Packing) {} + PixelLocalStorageImageLoadStore(bool needsR32Packing) + : PixelLocalStorage(MemorylessBackingType::InternalTextures), + mNeedsR32Packing(needsR32Packing) + {} // Call deleteContextObjects or onContextObjectsLost first! ~PixelLocalStorageImageLoadStore() override @@ -547,7 +570,7 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage ASSERT(static_cast(n) <= state.getImageUnits().size()); mSavedImageBindings.clear(); mSavedImageBindings.reserve(n); - for (int i = 0; i < n; ++i) + for (GLsizei i = 0; i < n; ++i) { mSavedImageBindings.emplace_back(state.getImageUnit(i)); } @@ -585,7 +608,7 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage // Bind and clear the PLS planes. size_t maxClearedAttachments = 0; - for (int i = 0; i < n;) + for (GLsizei i = 0; i < n;) { DrawBuffersVector pendingClears; for (; pendingClears.size() < maxDrawBuffers && i < n; ++i) @@ -595,7 +618,7 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage { continue; } - PixelLocalStoragePlane &plane = getPlane(i); + const PixelLocalStoragePlane &plane = getPlane(i); ASSERT(!plane.isDeinitialized()); plane.bindToImage(context, plsExtents, i, mNeedsR32Packing); if (loadop == GL_ZERO || loadop == GL_CLEAR_ANGLE) @@ -640,7 +663,7 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage context->memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); } - void onEnd(Context *context) override + void onEnd(Context *context, const GLenum storeops[]) override { GLsizei n = context->getState().getPixelLocalStorageActivePlanes(); @@ -689,6 +712,9 @@ class PixelLocalStorageImageLoadStore : public PixelLocalStorage class PixelLocalStorageFramebufferFetch : public PixelLocalStorage { public: + PixelLocalStorageFramebufferFetch() : PixelLocalStorage(MemorylessBackingType::InternalTextures) + {} + void onContextObjectsLost() override {} void onDeleteContextObjects(Context *) override {} @@ -716,7 +742,6 @@ class PixelLocalStorageFramebufferFetch : public PixelLocalStorage mBlendsToReEnable.reset(); mColorMasksToRestore.reset(); - mInvalidateList.clear(); bool needsClear = false; bool hasIndexedBlendAndColorMask = context->getExtensions().drawBuffersIndexedAny(); @@ -749,7 +774,7 @@ class PixelLocalStorageFramebufferFetch : public PixelLocalStorage continue; } - PixelLocalStoragePlane &plane = getPlane(i); + const PixelLocalStoragePlane &plane = getPlane(i); ASSERT(!plane.isDeinitialized()); // Attach our PLS texture to the framebuffer. Validation should have already ensured @@ -777,12 +802,6 @@ class PixelLocalStorageFramebufferFetch : public PixelLocalStorage } } - if (plane.isMemoryless()) - { - // Memoryless planes don't need to be preserved after glEndPixelLocalStorageANGLE(). - mInvalidateList.push_back(colorAttachment); - } - needsClear = needsClear || (loadop != GL_KEEP); } @@ -814,18 +833,30 @@ class PixelLocalStorageFramebufferFetch : public PixelLocalStorage } } - void onEnd(Context *context) override + void onEnd(Context *context, const GLenum storeops[]) override { GLsizei n = context->getState().getPixelLocalStorageActivePlanes(); const Caps &caps = context->getCaps(); - // Invalidate the memoryless PLS attachments. - if (!mInvalidateList.empty()) + // Invalidate the non-preserved PLS attachments. + DrawBuffersVector invalidateList; + for (GLsizei i = n - 1; i >= 0; --i) + { + if (!getPlane(i).isActive()) + { + continue; + } + if (storeops[i] != GL_KEEP || getPlane(i).isMemoryless()) + { + int drawBufferIdx = GetDrawBufferIdx(caps, i); + invalidateList.push_back(GL_COLOR_ATTACHMENT0 + drawBufferIdx); + } + } + if (!invalidateList.empty()) { context->invalidateFramebuffer(GL_DRAW_FRAMEBUFFER, - static_cast(mInvalidateList.size()), - mInvalidateList.data()); - mInvalidateList.clear(); + static_cast(invalidateList.size()), + invalidateList.data()); } bool hasIndexedBlendAndColorMask = context->getExtensions().drawBuffersIndexedAny(); @@ -891,12 +922,14 @@ class PixelLocalStorageFramebufferFetch : public PixelLocalStorage DrawBufferMask mBlendsToReEnable; DrawBufferMask mColorMasksToRestore; DrawBuffersArray> mSavedColorMasks; - DrawBuffersVector mInvalidateList; }; // Implements ANGLE_shader_pixel_local_storage directly via EXT_shader_pixel_local_storage. class PixelLocalStorageEXT : public PixelLocalStorage { + public: + PixelLocalStorageEXT() : PixelLocalStorage(MemorylessBackingType::TrueMemoryless) {} + private: void onContextObjectsLost() override {} @@ -931,9 +964,9 @@ class PixelLocalStorageEXT : public PixelLocalStorage memcpy(mActiveLoadOps.data(), loadops, sizeof(GLenum) * n); } - void onEnd(Context *context) override + void onEnd(Context *context, const GLenum storeops[]) override { - context->drawPixelLocalStorageEXTDisable(getPlanes(), mActiveLoadOps.data()); + context->drawPixelLocalStorageEXTDisable(getPlanes(), storeops); // Restore the default framebuffer width/height. context->framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, diff --git a/src/libANGLE/PixelLocalStorage.h b/src/libANGLE/PixelLocalStorage.h index 4f8387f78..3c6871bd8 100644 --- a/src/libANGLE/PixelLocalStorage.h +++ b/src/libANGLE/PixelLocalStorage.h @@ -61,6 +61,10 @@ class PixelLocalStoragePlane : angle::NonCopyable return mMemoryless; } + // Ensures we have an internal backing texture for memoryless planes. In some implementations we + // need a backing texture even if the plane is memoryless. + void ensureBackingTextureIfMemoryless(Context *, Extents plsSize); + GLenum getInternalformat() const { return mInternalformat; } // Implements glGetIntegeri_v() for GL_PIXEL_LOCAL_FORMAT_ANGLE, @@ -74,7 +78,7 @@ class PixelLocalStoragePlane : angle::NonCopyable bool getTextureImageExtents(const Context *, Extents *extents) const; // Attaches this plane to the specified color attachment point on the current draw framebuffer. - void attachToDrawFramebuffer(Context *, Extents plsExtents, GLenum colorAttachment); + void attachToDrawFramebuffer(Context *, Extents plsExtents, GLenum colorAttachment) const; // Interface for clearing typed pixel local storage planes. class ClearCommands @@ -92,7 +96,7 @@ class PixelLocalStoragePlane : angle::NonCopyable void issueClearCommand(ClearCommands *, int target, GLenum loadop) const; // Binds this PLS plane to a texture image unit for image load/store shader operations. - void bindToImage(Context *, Extents plsExtents, GLuint unit, bool needsR32Packing); + void bindToImage(Context *, Extents plsExtents, GLuint unit, bool needsR32Packing) const; // Low-level access to the backing texture. The plane must not be memoryless or deinitialized. const ImageIndex &getTextureImageIndex() const { return mTextureImageIndex; } @@ -106,12 +110,11 @@ class PixelLocalStoragePlane : angle::NonCopyable void getClearValuei(GLint value[4]) const { memcpy(value, mClearValuei.data(), 4 * 4); } void getClearValueui(GLuint value[4]) const { memcpy(value, mClearValueui.data(), 4 * 4); } - private: - // Ensures we have an internal backing texture for memoryless planes. In GL, we need a backing - // texture even if the plane is memoryless; glInvalidateFramebuffer() will ideally prevent the - // driver from writing out data where possible. - void ensureBackingIfMemoryless(Context *, Extents plsSize); + // True if PLS is currently active and this plane is enabled. + bool isActive() const { return mActive; } + void markActive(bool active) { mActive = active; } + private: GLenum mInternalformat = GL_NONE; // GL_NONE if this plane is in a deinitialized state. bool mMemoryless = false; TextureID mMemorylessTextureID{}; // We own memoryless backing textures and must delete them. @@ -122,6 +125,9 @@ class PixelLocalStoragePlane : angle::NonCopyable std::array mClearValuef{}; std::array mClearValuei{}; std::array mClearValueui{}; + + // True if PLS is currently active and this plane is enabled. + bool mActive = false; }; // Manages a collection of PixelLocalStoragePlanes and applies them to ANGLE's GL state. @@ -133,7 +139,6 @@ class PixelLocalStorage public: static std::unique_ptr Make(const Context *); - PixelLocalStorage(); virtual ~PixelLocalStorage(); // Called when the owning framebuffer is being destroyed. @@ -149,12 +154,6 @@ class PixelLocalStorage return mPlanes[plane]; } - PixelLocalStoragePlane &getPlane(GLint plane) - { - ASSERT(0 <= plane && plane < IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES); - return mPlanes[plane]; - } - const PixelLocalStoragePlane *getPlanes() { return mPlanes.data(); } // ANGLE_shader_pixel_local_storage API. @@ -171,10 +170,21 @@ class PixelLocalStorage void setClearValuei(GLint plane, const GLint val[4]) { mPlanes[plane].setClearValuei(val); } void setClearValueui(GLint plane, const GLuint val[4]) { mPlanes[plane].setClearValueui(val); } void begin(Context *, GLsizei n, const GLenum loadops[]); - void end(Context *); + void end(Context *, const GLenum storeops[]); void barrier(Context *); protected: + // In some implementations we need to allocate backing textures even for memoryless planes. + // glInvalidateFramebuffer() will ideally prevent memory transactions with these textures where + // possible. + enum class MemorylessBackingType : bool + { + TrueMemoryless, // No allocations necessary for memoryless planes. + InternalTextures // Allocate internal textures for memoryless planes. + }; + + PixelLocalStorage(MemorylessBackingType); + // Called when the context is lost or destroyed. Causes the subclass to clear its GL object // handles. virtual void onContextObjectsLost() = 0; @@ -185,10 +195,11 @@ class PixelLocalStorage // ANGLE_shader_pixel_local_storage API. virtual void onBegin(Context *, GLsizei n, const GLenum loadops[], Extents plsSize) = 0; - virtual void onEnd(Context *) = 0; + virtual void onEnd(Context *, const GLenum storeops[]) = 0; virtual void onBarrier(Context *) = 0; private: + const MemorylessBackingType mMemorylessBackingType; std::array mPlanes; }; diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp index 8cb3391a1..4b8e93b9d 100644 --- a/src/libANGLE/State.cpp +++ b/src/libANGLE/State.cpp @@ -2410,9 +2410,9 @@ void State::setPatchVertices(GLuint value) } } -void State::setPixelLocalStorageActivePlanes(GLuint planes) +void State::setPixelLocalStorageActivePlanes(GLsizei n) { - mPixelLocalStorageActivePlanes = planes; + mPixelLocalStorageActivePlanes = n; } void State::setShadingRate(GLenum rate) diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h index 56db2f526..f5a908db6 100644 --- a/src/libANGLE/State.h +++ b/src/libANGLE/State.h @@ -616,8 +616,8 @@ class State : angle::NonCopyable GLuint getPatchVertices() const { return mPatchVertices; } // GL_ANGLE_shader_pixel_local_storage - void setPixelLocalStorageActivePlanes(GLuint planes); - GLuint getPixelLocalStorageActivePlanes() const { return mPixelLocalStorageActivePlanes; } + void setPixelLocalStorageActivePlanes(GLsizei n); + GLsizei getPixelLocalStorageActivePlanes() const { return mPixelLocalStorageActivePlanes; } // State query functions void getBooleanv(GLenum pname, GLboolean *params) const; @@ -1195,7 +1195,7 @@ class State : angle::NonCopyable GLuint mPatchVertices; // GL_ANGLE_shader_pixel_local_storage - GLuint mPixelLocalStorageActivePlanes; + GLsizei mPixelLocalStorageActivePlanes; // GLES1 emulation: state specific to GLES1 GLES1State mGLES1State; diff --git a/src/libANGLE/capture/capture_gles_ext_autogen.cpp b/src/libANGLE/capture/capture_gles_ext_autogen.cpp index 9813e719c..ca3ad5d47 100644 --- a/src/libANGLE/capture/capture_gles_ext_autogen.cpp +++ b/src/libANGLE/capture/capture_gles_ext_autogen.cpp @@ -4766,19 +4766,18 @@ CallCapture CaptureFramebufferPixelLocalClearValueuivANGLE(const State &glState, CallCapture CaptureBeginPixelLocalStorageANGLE(const State &glState, bool isCallValid, - GLsizei planes, + GLsizei n, const GLenum *loadops) { ParamBuffer paramBuffer; - paramBuffer.addValueParam("planes", ParamType::TGLsizei, planes); + paramBuffer.addValueParam("n", ParamType::TGLsizei, n); if (isCallValid) { ParamCapture loadopsParam("loadops", ParamType::TGLenumConstPointer); InitParamValue(ParamType::TGLenumConstPointer, loadops, &loadopsParam.value); - CaptureBeginPixelLocalStorageANGLE_loadops(glState, isCallValid, planes, loadops, - &loadopsParam); + CaptureBeginPixelLocalStorageANGLE_loadops(glState, isCallValid, n, loadops, &loadopsParam); paramBuffer.addParam(std::move(loadopsParam)); } else @@ -4792,10 +4791,31 @@ CallCapture CaptureBeginPixelLocalStorageANGLE(const State &glState, return CallCapture(angle::EntryPoint::GLBeginPixelLocalStorageANGLE, std::move(paramBuffer)); } -CallCapture CaptureEndPixelLocalStorageANGLE(const State &glState, bool isCallValid) +CallCapture CaptureEndPixelLocalStorageANGLE(const State &glState, + bool isCallValid, + GLsizei n, + const GLenum *storeops) { ParamBuffer paramBuffer; + paramBuffer.addValueParam("n", ParamType::TGLsizei, n); + + if (isCallValid) + { + ParamCapture storeopsParam("storeops", ParamType::TGLenumConstPointer); + InitParamValue(ParamType::TGLenumConstPointer, storeops, &storeopsParam.value); + CaptureEndPixelLocalStorageANGLE_storeops(glState, isCallValid, n, storeops, + &storeopsParam); + paramBuffer.addParam(std::move(storeopsParam)); + } + else + { + ParamCapture storeopsParam("storeops", ParamType::TGLenumConstPointer); + InitParamValue(ParamType::TGLenumConstPointer, static_cast(nullptr), + &storeopsParam.value); + paramBuffer.addParam(std::move(storeopsParam)); + } + return CallCapture(angle::EntryPoint::GLEndPixelLocalStorageANGLE, std::move(paramBuffer)); } diff --git a/src/libANGLE/capture/capture_gles_ext_autogen.h b/src/libANGLE/capture/capture_gles_ext_autogen.h index ba2462bbe..2d06614eb 100644 --- a/src/libANGLE/capture/capture_gles_ext_autogen.h +++ b/src/libANGLE/capture/capture_gles_ext_autogen.h @@ -877,9 +877,12 @@ angle::CallCapture CaptureFramebufferPixelLocalClearValueuivANGLE(const State &g const GLuint *value); angle::CallCapture CaptureBeginPixelLocalStorageANGLE(const State &glState, bool isCallValid, - GLsizei planes, + GLsizei n, const GLenum *loadops); -angle::CallCapture CaptureEndPixelLocalStorageANGLE(const State &glState, bool isCallValid); +angle::CallCapture CaptureEndPixelLocalStorageANGLE(const State &glState, + bool isCallValid, + GLsizei n, + const GLenum *storeops); angle::CallCapture CapturePixelLocalStorageBarrierANGLE(const State &glState, bool isCallValid); angle::CallCapture CaptureGetFramebufferPixelLocalStorageParameterfvANGLE(const State &glState, bool isCallValid, @@ -4130,9 +4133,14 @@ void CaptureFramebufferPixelLocalClearValueuivANGLE_value(const State &glState, angle::ParamCapture *paramCapture); void CaptureBeginPixelLocalStorageANGLE_loadops(const State &glState, bool isCallValid, - GLsizei planes, + GLsizei n, const GLenum *loadops, angle::ParamCapture *paramCapture); +void CaptureEndPixelLocalStorageANGLE_storeops(const State &glState, + bool isCallValid, + GLsizei n, + const GLenum *storeops, + angle::ParamCapture *paramCapture); void CaptureGetFramebufferPixelLocalStorageParameterfvANGLE_params( const State &glState, bool isCallValid, diff --git a/src/libANGLE/capture/capture_gles_ext_params.cpp b/src/libANGLE/capture/capture_gles_ext_params.cpp index d350c2b4a..076257094 100644 --- a/src/libANGLE/capture/capture_gles_ext_params.cpp +++ b/src/libANGLE/capture/capture_gles_ext_params.cpp @@ -4273,11 +4273,20 @@ void CaptureFramebufferPixelLocalClearValueuivANGLE_value(const State &glState, void CaptureBeginPixelLocalStorageANGLE_loadops(const State &glState, bool isCallValid, - GLsizei planes, + GLsizei n, const GLenum loadops[], angle::ParamCapture *paramCapture) { - CaptureArray(loadops, planes, paramCapture); + CaptureArray(loadops, n, paramCapture); +} + +void CaptureEndPixelLocalStorageANGLE_storeops(const State &glState, + bool isCallValid, + GLsizei n, + const GLenum *storeops, + angle::ParamCapture *paramCapture) +{ + CaptureArray(storeops, n, paramCapture); } void CaptureGetFramebufferPixelLocalStorageParameterfvANGLE_params( diff --git a/src/libANGLE/renderer/ContextImpl.cpp b/src/libANGLE/renderer/ContextImpl.cpp index e9e25f3e5..7193a5759 100644 --- a/src/libANGLE/renderer/ContextImpl.cpp +++ b/src/libANGLE/renderer/ContextImpl.cpp @@ -98,7 +98,7 @@ angle::Result ContextImpl::drawPixelLocalStorageEXTEnable(gl::Context *, angle::Result ContextImpl::drawPixelLocalStorageEXTDisable(gl::Context *, const gl::PixelLocalStoragePlane[], - const GLenum loadops[]) + const GLenum storeops[]) { ASSERT(getNativePixelLocalStorageType() == ShPixelLocalStorageType::PixelLocalStorageEXT); UNREACHABLE(); diff --git a/src/libANGLE/renderer/ContextImpl.h b/src/libANGLE/renderer/ContextImpl.h index 84bae23b5..242cc3727 100644 --- a/src/libANGLE/renderer/ContextImpl.h +++ b/src/libANGLE/renderer/ContextImpl.h @@ -279,7 +279,7 @@ class ContextImpl : public GLImplFactory // The implementation's ShPixelLocalStorageType must be "PixelLocalStorageEXT". virtual angle::Result drawPixelLocalStorageEXTDisable(gl::Context *, const gl::PixelLocalStoragePlane[], - const GLenum loadops[]); + const GLenum storeops[]); protected: const gl::State &mState; diff --git a/src/libANGLE/renderer/gl/ContextGL.cpp b/src/libANGLE/renderer/gl/ContextGL.cpp index 3cf6403c3..72fc2840a 100644 --- a/src/libANGLE/renderer/gl/ContextGL.cpp +++ b/src/libANGLE/renderer/gl/ContextGL.cpp @@ -1082,7 +1082,7 @@ angle::Result ContextGL::drawPixelLocalStorageEXTEnable(gl::Context *context, angle::Result ContextGL::drawPixelLocalStorageEXTDisable(gl::Context *context, const gl::PixelLocalStoragePlane planes[], - const GLenum loadops[]) + const GLenum storeops[]) { ASSERT(getNativePixelLocalStorageType() == ShPixelLocalStorageType::PixelLocalStorageEXT); GLsizei n = context->getState().getPixelLocalStorageActivePlanes(); @@ -1091,9 +1091,8 @@ angle::Result ContextGL::drawPixelLocalStorageEXTDisable(gl::Context *context, for (GLsizei i = n - 1; i >= 0; --i) { const gl::PixelLocalStoragePlane &plane = planes[i]; - GLenum loadop = loadops[i]; - bool preserved = loadop != GL_DISABLE_ANGLE && !plane.isMemoryless(); - b.prependPlane(loadop != GL_DISABLE_ANGLE ? plane.getInternalformat() : GL_NONE, preserved); + bool preserved = plane.isActive() && !plane.isMemoryless() && storeops[i] == GL_KEEP; + b.prependPlane(plane.isActive() ? plane.getInternalformat() : GL_NONE, preserved); if (preserved) { const gl::ImageIndex &idx = plane.getTextureImageIndex(); diff --git a/src/libANGLE/renderer/gl/ContextGL.h b/src/libANGLE/renderer/gl/ContextGL.h index fc2da55c9..6aa4cebf5 100644 --- a/src/libANGLE/renderer/gl/ContextGL.h +++ b/src/libANGLE/renderer/gl/ContextGL.h @@ -294,7 +294,7 @@ class ContextGL : public ContextImpl const GLenum loadops[]) override; angle::Result drawPixelLocalStorageEXTDisable(gl::Context *, const gl::PixelLocalStoragePlane[], - const GLenum loadops[]) override; + const GLenum storeops[]) override; private: angle::Result setDrawArraysState(const gl::Context *context, diff --git a/src/libANGLE/validationESEXT.cpp b/src/libANGLE/validationESEXT.cpp index 682554d86..bba06d98b 100644 --- a/src/libANGLE/validationESEXT.cpp +++ b/src/libANGLE/validationESEXT.cpp @@ -1693,8 +1693,8 @@ bool ValidatePLSTextureType(const Context *context, bool ValidatePLSLoadOperation(const Context *context, angle::EntryPoint entryPoint, GLenum loadop) { - // INVALID_ENUM is generated if [0..-1] is not one of the Load Operations - // enumerated in Table X.1. + // INVALID_ENUM is generated if [0..-1] is not one of the Load Operations enumerated + // in Table X.1. switch (loadop) { case GL_ZERO: @@ -1704,7 +1704,24 @@ bool ValidatePLSLoadOperation(const Context *context, angle::EntryPoint entryPoi case GL_DISABLE_ANGLE: return true; default: - context->validationError(entryPoint, GL_INVALID_ENUM, kPLSInvalidLoadOperation); + context->validationErrorF(entryPoint, GL_INVALID_ENUM, kPLSInvalidLoadOperation, + loadop); + return false; + } +} + +bool ValidatePLSStoreOperation(const Context *context, angle::EntryPoint entryPoint, GLenum storeop) +{ + // INVALID_ENUM is generated if [0..PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE-1] is not + // one of the Store Operations enumerated in Table X.2. + switch (storeop) + { + case GL_KEEP: + case GL_DONT_CARE: + return true; + default: + context->validationErrorF(entryPoint, GL_INVALID_ENUM, kPLSInvalidStoreOperation, + storeop); return false; } } @@ -1839,7 +1856,7 @@ bool ValidateFramebufferPixelLocalClearValueuivANGLE(const Context *context, bool ValidateBeginPixelLocalStorageANGLE(const Context *context, angle::EntryPoint entryPoint, - GLsizei planes, + GLsizei n, const GLenum loadops[]) { if (!ValidatePLSCommon(context, entryPoint, PLSExpectedStatus::Inactive)) @@ -1887,14 +1904,13 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, return false; } - // INVALID_VALUE is generated if < 1 or > - // MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. - if (planes < 1) + // INVALID_VALUE is generated if < 1 or > MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. + if (n < 1) { context->validationError(entryPoint, GL_INVALID_VALUE, kPLSPlanesLessThanOne); return false; } - if (planes > static_cast(context->getCaps().maxPixelLocalStoragePlanes)) + if (n > static_cast(context->getCaps().maxPixelLocalStoragePlanes)) { context->validationError(entryPoint, GL_INVALID_VALUE, kPLSPlanesOutOfRange); return false; @@ -1921,11 +1937,9 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to // any color attachment point on or after: // - // COLOR_ATTACHMENT0 + - // MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - - // + // COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - // - for (GLuint i = caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - planes; + for (GLuint i = caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - n; i < caps.maxColorAttachmentsWithActivePixelLocalStorage; ++i) { if (framebuffer->getColorAttachment(i)) @@ -1947,10 +1961,10 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, bool hasTextureBackedPLSPlanes = false; Extents textureBackedPLSExtents{}; - for (int i = 0; i < planes; ++i) + for (GLsizei i = 0; i < n; ++i) { - // INVALID_ENUM is generated if [0..-1] is not one of the Load - // Operations enumerated in Table X.1. + // INVALID_ENUM is generated if [0..-1] is not one of the Load Operations + // enumerated in Table X.1. if (!ValidatePLSLoadOperation(context, entryPoint, loadops[i])) { return false; @@ -1961,8 +1975,8 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, continue; } - // INVALID_OPERATION is generated if [0..-1] is not DISABLE_ANGLE, and - // the pixel local storage plane at that same index is is in a deinitialized state. + // INVALID_OPERATION is generated if [0..-1] is not DISABLE_ANGLE, and the pixel + // local storage plane at that same index is is in a deinitialized state. if (pls == nullptr || pls->getPlane(i).isDeinitialized()) { context->validationError(entryPoint, GL_INVALID_OPERATION, @@ -1995,8 +2009,8 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, } else { - // INVALID_OPERATION is generated if [0..-1] is KEEP and the pixel - // local storage plane at that same index is memoryless. + // INVALID_OPERATION is generated if [0..-1] is KEEP and the pixel local + // storage plane at that same index is memoryless. if (loadops[i] == GL_KEEP) { context->validationError(entryPoint, GL_INVALID_OPERATION, @@ -2048,9 +2062,34 @@ bool ValidateBeginPixelLocalStorageANGLE(const Context *context, return true; } -bool ValidateEndPixelLocalStorageANGLE(const Context *context, angle::EntryPoint entryPoint) +bool ValidateEndPixelLocalStorageANGLE(const Context *context, + angle::EntryPoint entryPoint, + GLsizei n, + const GLenum storeops[]) { - return ValidatePLSCommon(context, entryPoint, PLSExpectedStatus::Active); + if (!ValidatePLSCommon(context, entryPoint, PLSExpectedStatus::Active)) + { + return false; + } + + // INVALID_VALUE is generated if != PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE. + if (n != context->getState().getPixelLocalStorageActivePlanes()) + { + context->validationError(entryPoint, GL_INVALID_VALUE, kPLSNNotEqualActivePlanes); + return false; + } + + // INVALID_ENUM is generated if [0..PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE-1] is not + // one of the Store Operations enumerated in Table X.2. + for (GLsizei i = 0; i < n; ++i) + { + if (!ValidatePLSStoreOperation(context, entryPoint, storeops[i])) + { + return false; + } + } + + return true; } bool ValidatePixelLocalStorageBarrierANGLE(const Context *context, angle::EntryPoint entryPoint) diff --git a/src/libANGLE/validationESEXT_autogen.h b/src/libANGLE/validationESEXT_autogen.h index 9c31379ff..a7c7b29a6 100644 --- a/src/libANGLE/validationESEXT_autogen.h +++ b/src/libANGLE/validationESEXT_autogen.h @@ -875,9 +875,12 @@ bool ValidateFramebufferPixelLocalClearValueuivANGLE(const Context *context, const GLuint *value); bool ValidateBeginPixelLocalStorageANGLE(const Context *context, angle::EntryPoint entryPoint, - GLsizei planes, + GLsizei n, const GLenum *loadops); -bool ValidateEndPixelLocalStorageANGLE(const Context *context, angle::EntryPoint entryPoint); +bool ValidateEndPixelLocalStorageANGLE(const Context *context, + angle::EntryPoint entryPoint, + GLsizei n, + const GLenum *storeops); bool ValidatePixelLocalStorageBarrierANGLE(const Context *context, angle::EntryPoint entryPoint); bool ValidateGetFramebufferPixelLocalStorageParameterfvANGLE(const Context *context, angle::EntryPoint entryPoint, diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.cpp b/src/libGLESv2/entry_points_gles_ext_autogen.cpp index 1d05841ae..5977eda82 100644 --- a/src/libGLESv2/entry_points_gles_ext_autogen.cpp +++ b/src/libGLESv2/entry_points_gles_ext_autogen.cpp @@ -3932,12 +3932,11 @@ void GL_APIENTRY GL_FramebufferPixelLocalClearValueuivANGLE(GLint plane, const G } } -void GL_APIENTRY GL_BeginPixelLocalStorageANGLE(GLsizei planes, const GLenum *loadops) +void GL_APIENTRY GL_BeginPixelLocalStorageANGLE(GLsizei n, const GLenum *loadops) { Context *context = GetValidGlobalContext(); EVENT(context, GLBeginPixelLocalStorageANGLE, - "context = %d, planes = %d, loadops = 0x%016" PRIxPTR "", CID(context), planes, - (uintptr_t)loadops); + "context = %d, n = %d, loadops = 0x%016" PRIxPTR "", CID(context), n, (uintptr_t)loadops); if (context) { @@ -3947,12 +3946,12 @@ void GL_APIENTRY GL_BeginPixelLocalStorageANGLE(GLsizei planes, const GLenum *lo (ValidatePixelLocalStorageInactive(context, angle::EntryPoint::GLBeginPixelLocalStorageANGLE) && ValidateBeginPixelLocalStorageANGLE( - context, angle::EntryPoint::GLBeginPixelLocalStorageANGLE, planes, loadops))); + context, angle::EntryPoint::GLBeginPixelLocalStorageANGLE, n, loadops))); if (isCallValid) { - context->beginPixelLocalStorage(planes, loadops); + context->beginPixelLocalStorage(n, loadops); } - ANGLE_CAPTURE_GL(BeginPixelLocalStorageANGLE, isCallValid, context, planes, loadops); + ANGLE_CAPTURE_GL(BeginPixelLocalStorageANGLE, isCallValid, context, n, loadops); } else { @@ -3960,22 +3959,25 @@ void GL_APIENTRY GL_BeginPixelLocalStorageANGLE(GLsizei planes, const GLenum *lo } } -void GL_APIENTRY GL_EndPixelLocalStorageANGLE() +void GL_APIENTRY GL_EndPixelLocalStorageANGLE(GLsizei n, const GLenum *storeops) { Context *context = GetValidGlobalContext(); - EVENT(context, GLEndPixelLocalStorageANGLE, "context = %d", CID(context)); + EVENT(context, GLEndPixelLocalStorageANGLE, + "context = %d, n = %d, storeops = 0x%016" PRIxPTR "", CID(context), n, + (uintptr_t)storeops); if (context) { SCOPED_SHARE_CONTEXT_LOCK(context); - bool isCallValid = (context->skipValidation() || - ValidateEndPixelLocalStorageANGLE( - context, angle::EntryPoint::GLEndPixelLocalStorageANGLE)); + bool isCallValid = + (context->skipValidation() || + ValidateEndPixelLocalStorageANGLE( + context, angle::EntryPoint::GLEndPixelLocalStorageANGLE, n, storeops)); if (isCallValid) { - context->endPixelLocalStorage(); + context->endPixelLocalStorage(n, storeops); } - ANGLE_CAPTURE_GL(EndPixelLocalStorageANGLE, isCallValid, context); + ANGLE_CAPTURE_GL(EndPixelLocalStorageANGLE, isCallValid, context, n, storeops); } else { diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.h b/src/libGLESv2/entry_points_gles_ext_autogen.h index 9341ab262..f9dd198a4 100644 --- a/src/libGLESv2/entry_points_gles_ext_autogen.h +++ b/src/libGLESv2/entry_points_gles_ext_autogen.h @@ -654,8 +654,8 @@ ANGLE_EXPORT void GL_APIENTRY GL_FramebufferPixelLocalClearValueivANGLE(GLint pl const GLint *value); ANGLE_EXPORT void GL_APIENTRY GL_FramebufferPixelLocalClearValueuivANGLE(GLint plane, const GLuint *value); -ANGLE_EXPORT void GL_APIENTRY GL_BeginPixelLocalStorageANGLE(GLsizei planes, const GLenum *loadops); -ANGLE_EXPORT void GL_APIENTRY GL_EndPixelLocalStorageANGLE(); +ANGLE_EXPORT void GL_APIENTRY GL_BeginPixelLocalStorageANGLE(GLsizei n, const GLenum *loadops); +ANGLE_EXPORT void GL_APIENTRY GL_EndPixelLocalStorageANGLE(GLsizei n, const GLenum *storeops); ANGLE_EXPORT void GL_APIENTRY GL_PixelLocalStorageBarrierANGLE(); ANGLE_EXPORT void GL_APIENTRY GL_GetFramebufferPixelLocalStorageParameterfvANGLE(GLint plane, GLenum pname, diff --git a/src/libGLESv2/libGLESv2_autogen.cpp b/src/libGLESv2/libGLESv2_autogen.cpp index b4f79cfaf..e58785e59 100644 --- a/src/libGLESv2/libGLESv2_autogen.cpp +++ b/src/libGLESv2/libGLESv2_autogen.cpp @@ -3797,14 +3797,14 @@ void GL_APIENTRY glFramebufferPixelLocalClearValueuivANGLE(GLint plane, const GL return GL_FramebufferPixelLocalClearValueuivANGLE(plane, value); } -void GL_APIENTRY glBeginPixelLocalStorageANGLE(GLsizei planes, const GLenum *loadops) +void GL_APIENTRY glBeginPixelLocalStorageANGLE(GLsizei n, const GLenum *loadops) { - return GL_BeginPixelLocalStorageANGLE(planes, loadops); + return GL_BeginPixelLocalStorageANGLE(n, loadops); } -void GL_APIENTRY glEndPixelLocalStorageANGLE() +void GL_APIENTRY glEndPixelLocalStorageANGLE(GLsizei n, const GLenum *storeops) { - return GL_EndPixelLocalStorageANGLE(); + return GL_EndPixelLocalStorageANGLE(n, storeops); } void GL_APIENTRY glPixelLocalStorageBarrierANGLE() diff --git a/src/tests/gl_tests/PixelLocalStorageTest.cpp b/src/tests/gl_tests/PixelLocalStorageTest.cpp index 043089656..a547cc799 100644 --- a/src/tests/gl_tests/PixelLocalStorageTest.cpp +++ b/src/tests/gl_tests/PixelLocalStorageTest.cpp @@ -508,7 +508,7 @@ TEST_P(PixelLocalStorageTest, RGBA8) {FULLSCREEN, {0, 0, 1, 0}, {0, 0, -70, 0}, {0, 0, 100, 0}}, {FULLSCREEN, {0, 0, 0, -1}, {128, 0, 0, 500}, {0, 0, 0, 300}}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_KEEP, GL_KEEP, GL_KEEP})); attachTextureToScratchFBO(tex1); EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor(255, 255, 255, 0)); @@ -554,7 +554,7 @@ TEST_P(PixelLocalStorageTest, R32) {FULLSCREEN, {-100, 0, 0, 0}, {0x00ff0000, 0, 0, 0}}, {FULLSCREEN, {.25, 0, 0, 0}, {0xff000000, 0, 0, 22}}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_KEEP, GL_KEEP})); // These values should be exact matches. // @@ -626,6 +626,7 @@ TEST_P(PixelLocalStorageTest, ClearState) glFramebufferTexturePixelLocalStorageANGLE(1, tex8i, 0, 0); glFramebufferTexturePixelLocalStorageANGLE(2, tex8ui, 0, 0); auto clearLoads = GLenumArray({GL_CLEAR_ANGLE, GL_CLEAR_ANGLE, GL_CLEAR_ANGLE}); + auto keepStores = GLenumArray({GL_KEEP, GL_KEEP, GL_KEEP}); // Clear values are initially zero. EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({0, 0, 0, 0})); @@ -633,7 +634,7 @@ TEST_P(PixelLocalStorageTest, ClearState) EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({0, 0, 0, 0})); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBeginPixelLocalStorageANGLE(3, clearLoads); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, keepStores); attachTextureToScratchFBO(tex8f); EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(0, 0, 0, 0)); attachTextureToScratchFBO(tex8i); @@ -650,7 +651,7 @@ TEST_P(PixelLocalStorageTest, ClearState) EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({100.5, 0, 0, 0})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(1, ({-1, 2, -3, 4})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({5, 6, 7, 8})); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, keepStores); attachTextureToScratchFBO(tex8f); EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(255, 0, 0, 0)); attachTextureToScratchFBO(tex8i); @@ -668,7 +669,7 @@ TEST_P(PixelLocalStorageTest, ClearState) EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(0, ({0, 0, 0, 0})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(1, ({0, 0, 0, 0})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(2, ({0, 0, 0, 0})); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, keepStores); attachTextureToScratchFBO(tex8ui); EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0, 0, 0, 0)); attachTextureToScratchFBO(tex8f); @@ -685,7 +686,7 @@ TEST_P(PixelLocalStorageTest, ClearState) EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(1, ({-1, 0, 1, 2})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(2, ({-129, -128, 127, 128})); glBeginPixelLocalStorageANGLE(3, clearLoads); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, keepStores); attachTextureToScratchFBO(tex8ui); EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(254, 255, 255, 255)); attachTextureToScratchFBO(tex8f); @@ -703,7 +704,7 @@ TEST_P(PixelLocalStorageTest, ClearState) EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(1, ({0, 0, 0, 0})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(2, ({0, 0, 0, 0})); glBeginPixelLocalStorageANGLE(3, clearLoads); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, keepStores); attachTextureToScratchFBO(tex8i); EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(0, 0, 0, 0)); attachTextureToScratchFBO(tex8ui); @@ -720,7 +721,7 @@ TEST_P(PixelLocalStorageTest, ClearState) EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(1, ({0, 0, 999, 999})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(2, ({999, 999, -999, -999})); glBeginPixelLocalStorageANGLE(3, clearLoads); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, keepStores); attachTextureToScratchFBO(tex8i); EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(127, 127, -128, -128)); attachTextureToScratchFBO(tex8ui); @@ -731,7 +732,7 @@ TEST_P(PixelLocalStorageTest, ClearState) // GL_ZERO shouldn't be affected by previous clear colors. glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBeginPixelLocalStorageANGLE(3, GLenumArray({GL_ZERO, GL_ZERO, GL_ZERO})); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, keepStores); attachTextureToScratchFBO(tex8f); EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(0, 0, 0, 0)); attachTextureToScratchFBO(tex8i); @@ -748,7 +749,7 @@ TEST_P(PixelLocalStorageTest, ClearState) EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(1, ({-1, 2, -3, 4})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({5, 6, 7, 8})); glBeginPixelLocalStorageANGLE(3, clearLoads); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, keepStores); attachTextureToScratchFBO(tex8f); EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(255, 0, 0, 0)); attachTextureToScratchFBO(tex8i); @@ -767,7 +768,7 @@ TEST_P(PixelLocalStorageTest, ClearState) EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({0, 0, 0, 0})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(1, ({0, 0, 0, 0})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({0, 0, 0, 0})); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, keepStores); attachTextureToScratchFBO(tex8f); EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(0, 0, 0, 0)); attachTextureToScratchFBO(tex8i); @@ -786,7 +787,7 @@ TEST_P(PixelLocalStorageTest, ClearState) GLenumArray({GL_CLEAR_ANGLE, GL_DISABLE_ANGLE, GL_CLEAR_ANGLE})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({100.5f, 0, 0, 0})); EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({0xbaadbeef, 1, 1, 0})); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_KEEP, GL_DONT_CARE, GL_KEEP})); attachTextureToScratchFBO(tex32f); EXPECT_PIXEL_RECT32F_EQ(0, 0, 1, 1, GLColor32F(100.5f, 0, 0, 1)); attachTextureToScratchFBO(tex32ui); @@ -838,13 +839,14 @@ TEST_P(PixelLocalStorageTest, LoadOps) glFramebufferPixelLocalClearValuefvANGLE(i, ClearF(0, 0, 0, 1)); loadOps[i] = (i & 1) ? GL_CLEAR_ANGLE : GL_KEEP; } + std::vector storeOps(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_KEEP); glViewport(0, 0, W, H); glDrawBuffers(0, nullptr); // Draw transparent green into all pls attachments. glBeginPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, loadOps.data()); mProgram.drawBoxes({{{FULLSCREEN}, {0, 1, 0, 0}}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, storeOps.data()); for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i) { @@ -873,7 +875,7 @@ TEST_P(PixelLocalStorageTest, LoadOps) // Execute a pls pass without a draw. glBeginPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, loadOps.data()); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, storeOps.data()); for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i) { @@ -964,7 +966,7 @@ TEST_P(PixelLocalStorageTest, FragmentReject_stencil) GLint zero = 0; glClearBufferiv(GL_STENCIL, 0, &zero); mProgram.drawBoxes({{{0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT}}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); glDisable(GL_STENCIL_TEST); attachTextureToScratchFBO(tex); EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::black); @@ -978,7 +980,7 @@ TEST_P(PixelLocalStorageTest, FragmentReject_stencil) glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); mProgram.drawBoxes({FRAG_REJECT_TEST_BOX}); glDisable(GL_STENCIL_TEST); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); renderTextureToDefaultFramebuffer(tex); EXPECT_PIXEL_RECT_EQ(0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT, GLColor::green); EXPECT_PIXEL_RECT_EQ(FRAG_REJECT_TEST_WIDTH, 0, W - FRAG_REJECT_TEST_WIDTH, @@ -1019,7 +1021,7 @@ TEST_P(PixelLocalStorageTest, FragmentReject_depth) glDisable(GL_SCISSOR_TEST); glDepthFunc(GL_LESS); mProgram.drawBoxes({FRAG_REJECT_TEST_BOX}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); glDisable(GL_DEPTH_TEST); renderTextureToDefaultFramebuffer(tex); @@ -1049,7 +1051,7 @@ TEST_P(PixelLocalStorageTest, FragmentReject_viewport) glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_CLEAR_ANGLE})); glViewport(0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT); mProgram.drawBoxes({FRAG_REJECT_TEST_BOX}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); glViewport(0, 0, W, H); renderTextureToDefaultFramebuffer(tex); @@ -1117,7 +1119,7 @@ TEST_P(PixelLocalStorageTest, ForgetBarrier) mProgram.drawBoxes(boxesA_100, UseBarriers::No); glPixelLocalStorageBarrierANGLE(); mProgram.drawBoxes(boxesB_7, UseBarriers::No); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); attachTextureToScratchFBO(tex); EXPECT_PIXEL_RECT32F_EQ(0, 0, W, H, GLColor32F(211, 0, 0, 1)); @@ -1136,7 +1138,7 @@ TEST_P(PixelLocalStorageTest, ForgetBarrier) mProgram.drawBoxes(boxesA_100, UseBarriers::No); // OOPS! We forgot to insert a barrier! mProgram.drawBoxes(boxesB_7, UseBarriers::No); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); float pixels[H * W * 4]; attachTextureToScratchFBO(tex); @@ -1223,7 +1225,7 @@ TEST_P(PixelLocalStorageTest, MemorylessStorage) transferToTextureProgram.bind(); transferToTextureProgram.drawBoxes({{FULLSCREEN}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_KEEP, GL_DONT_CARE})); attachTextureToScratchFBO(tex); EXPECT_PIXEL_RECT_EQ(0, 60, W, H - 60, GLColor(0, 0, 0, 255)); @@ -1316,7 +1318,8 @@ TEST_P(PixelLocalStorageTest, MaxCombinedDrawBuffersAndPLSPlanes) glBeginPixelLocalStorageANGLE(numPLSPlanes, std::vector(numPLSPlanes, GL_ZERO).data()); mProgram.drawBoxes({{FULLSCREEN, {255, 254, 253, 252}, {0, 1, 2, 3}}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(numPLSPlanes, + std::vector(numPLSPlanes, GL_KEEP).data()); for (int i = 0; i < numPLSPlanes; ++i) { @@ -1407,7 +1410,7 @@ TEST_P(PixelLocalStorageTest, LoadOnly) pass3.bind(); pass3.drawBoxes({{FULLSCREEN}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_KEEP})); attachTextureToScratchFBO(tex); EXPECT_PIXEL_RECT_EQ(0, 0, 64, 64, GLColor(255, 255, 255, 255)); @@ -1454,7 +1457,9 @@ TEST_P(PixelLocalStorageTest, LoadOnly) mProgram.drawBoxes({{FULLSCREEN}}); - glEndPixelLocalStorageANGLE(); + int n; + glGetIntegerv(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, &n); + glEndPixelLocalStorageANGLE(n, GLenumArray({GL_DONT_CARE, GL_KEEP, GL_KEEP})); // Ensure "tex" was properly read in the shader. if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE == 0) @@ -1510,7 +1515,7 @@ TEST_P(PixelLocalStorageTest, LoadAfterStore) glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_ZERO})); mProgram.drawBoxes({{FULLSCREEN}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); attachTextureToScratchFBO(tex); EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(233, 144, 89, 55)); // fib(13, 12, 11, 10) @@ -1568,8 +1573,12 @@ TEST_P(PixelLocalStorageTest, LoadAfterStore) glBeginPixelLocalStorageANGLE(3, GLenumArray({GL_ZERO, GL_ZERO, GL_DONT_CARE})); } + mProgram.drawBoxes({{FULLSCREEN}}); - glEndPixelLocalStorageANGLE(); + + int n; + glGetIntegerv(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, &n); + glEndPixelLocalStorageANGLE(n, GLenumArray({GL_DONT_CARE, GL_DONT_CARE, GL_KEEP})); if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE == 0) { @@ -1633,7 +1642,7 @@ TEST_P(PixelLocalStorageTest, FunctionArguments) glFramebufferPixelLocalClearValuefvANGLE(2, ClearF(1, 0, 0, 1)); glBeginPixelLocalStorageANGLE(3, GLenumArray({GL_ZERO, GL_CLEAR_ANGLE, GL_CLEAR_ANGLE})); mProgram.drawBoxes({{FULLSCREEN}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_KEEP, GL_DONT_CARE, GL_DONT_CARE})); attachTextureToScratchFBO(dst); EXPECT_PIXEL_RECT_EQ(0, 0, 25, H, GLColor(0, 255, 255, 0)); @@ -1740,7 +1749,7 @@ TEST_P(PixelLocalStorageTest, Coherency) { mProgram.drawBoxes(boxes); } - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_KEEP, GL_DONT_CARE})); attachTextureToScratchFBO(tex); std::vector actual(H * W * 4); @@ -1794,7 +1803,7 @@ TEST_P(PixelLocalStorageTest, MipMapLevels) mProgram.drawBoxes({{{0, 0, (float)levelWidth - 3, (float)levelHeight}, {0, 0, 1, 0}}, {{0, 0, (float)levelWidth - 2, (float)levelHeight}, {0, 1, 0, 0}}, {{0, 0, (float)levelWidth - 1, (float)levelHeight}, {1, 0, 0, 0}}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); attachTextureToScratchFBO(tex, level); EXPECT_PIXEL_RECT_EQ(0, 0, levelWidth - 3, levelHeight, GLColor::white); EXPECT_PIXEL_RECT_EQ(levelWidth - 3, 0, 1, levelHeight, GLColor::yellow); @@ -1880,7 +1889,8 @@ void PixelLocalStorageTest::doStateRestorationTest() glFramebufferPixelLocalClearValuefvANGLE(2, ClearF(.1, .2, .3, .4)); glBeginPixelLocalStorageANGLE(4, GLenumArray({GL_ZERO, GL_KEEP, GL_CLEAR_ANGLE, GL_DONT_CARE})); glPixelLocalStorageBarrierANGLE(); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(4, + GLenumArray({GL_DONT_CARE, GL_KEEP, GL_DONT_CARE, GL_DONT_CARE})); // Check state. GLint textureBinding2D; @@ -2052,7 +2062,7 @@ void PixelLocalStorageTest::doDrawStateTest() // Store PLS to the texture. This should work again even though the blocking draw state was // synced for the previous draw. - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); attachTextureToScratchFBO(tex); EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor(0, 255, 0, 255)); @@ -2163,7 +2173,10 @@ TEST_P(PixelLocalStorageTest, BlendAndColorMask) } mProgram.drawBoxes({{FULLSCREEN}}); - glEndPixelLocalStorageANGLE(); + + int n; + glGetIntegerv(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, &n); + glEndPixelLocalStorageANGLE(n, GLenumArray({GL_KEEP, GL_KEEP, GL_KEEP, GL_KEEP})); attachTextureToScratchFBO(tex1); EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red); @@ -2214,7 +2227,7 @@ TEST_P(PixelLocalStorageTest, ParallelFramebufferFetch) // Swap pls and fbfetch. mProgram.drawBoxes({{FULLSCREEN}}); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green); @@ -2603,7 +2616,8 @@ TEST_P(PixelLocalStorageValidationTest, FramebufferMemorylessPixelLocalStorageAN glFramebufferMemorylessPixelLocalStorageANGLE(3, GL_R32UI); EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active."); - glEndPixelLocalStorageANGLE(); + // The store operation is ignored if its plane is memoryless or disabled. + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_KEEP, GL_KEEP})); glFramebufferTexturePixelLocalStorageANGLE(1, 0, 0, 0); } @@ -2723,7 +2737,8 @@ TEST_P(PixelLocalStorageValidationTest, FramebufferTexturePixelLocalStorageANGLE glFramebufferTexturePixelLocalStorageANGLE(0, tmp, 0, 0); EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active."); - glEndPixelLocalStorageANGLE(); + // The store operation is ignored if its plane is memoryless or disabled. + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_KEEP, GL_DONT_CARE})); glFramebufferTexturePixelLocalStorageANGLE(1, 0, 0, 0); } @@ -2947,7 +2962,7 @@ TEST_P(PixelLocalStorageValidationTest, glFramebufferPixelLocalClearValuesANGLE) EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); ASSERT_GL_NO_ERROR(); @@ -2979,7 +2994,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_context_stat EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); EXPECT_GL_NO_ERROR(); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); @@ -3046,8 +3061,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_framebuffer_ PLSTestTexture pls0(GL_RGBA8, 100, 100); glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0); - // INVALID_VALUE is generated if < 1 or > - // MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. + // INVALID_VALUE is generated if < 1 or > MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. glBeginPixelLocalStorageANGLE(0, nullptr); EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE); EXPECT_GL_SINGLE_ERROR_MSG("Planes must be greater than 0."); @@ -3087,9 +3101,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_framebuffer_ // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to // any color attachment point on or after: // - // COLOR_ATTACHMENT0 + - // MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - - // + // COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - // int maxColorAttachmentsWithMaxPLSPlanes = MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - MAX_PIXEL_LOCAL_STORAGE_PLANES; @@ -3108,7 +3120,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_framebuffer_ EXPECT_GL_SINGLE_ERROR_MSG( "Framebuffer cannot have images attached to color attachment points on or after " "COLOR_ATTACHMENT0 + " - "MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - ."); + "MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - ."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); } } @@ -3127,29 +3139,29 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_loadops) EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE); EXPECT_GL_SINGLE_ERROR_MSG("loadops cannot null."); - // INVALID_ENUM is generated if [0..-1] is not one of the Load Operations - // enumerated in Table X.1. + // INVALID_ENUM is generated if [0..-1] is not one of the Load Operations enumerated + // in Table X.1. { glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_REPLACE})); EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Load Operation."); + EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Load Operation: 0x1E01."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); std::vector loadops(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_DISABLE_ANGLE); loadops.back() = GL_SCISSOR_BOX; glBeginPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, loadops.data()); EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); - EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Load Operation."); + EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Load Operation: 0x0C10."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); } - // INVALID_OPERATION is generated if [0..-1] is not DISABLE_ANGLE, and the - // pixel local storage plane at that same index is is in a deinitialized state. + // INVALID_OPERATION is generated if [0..-1] is not DISABLE_ANGLE, and the pixel + // local storage plane at that same index is is in a deinitialized state. { glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_CLEAR_ANGLE})); EXPECT_GL_NO_ERROR(); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); EXPECT_GL_NO_ERROR(); glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_CLEAR_ANGLE, GL_DONT_CARE})); @@ -3170,7 +3182,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_loadops) glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0); glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_ZERO})); EXPECT_GL_NO_ERROR(); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); EXPECT_GL_NO_ERROR(); // If is NONE, the pixel local storage plane at index is @@ -3183,8 +3195,8 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_loadops) ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); } - // INVALID_OPERATION is generated if [0..-1] is KEEP and the pixel local - // storage plane at that same index is memoryless. + // INVALID_OPERATION is generated if [0..-1] is KEEP and the pixel local storage + // plane at that same index is memoryless. glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA8); glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_KEEP})); EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); @@ -3215,7 +3227,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_planes) // Disabling the mismatched size plane is fine. glBeginPixelLocalStorageANGLE(3, GLenumArray({GL_KEEP, GL_DISABLE_ANGLE, GL_KEEP})); EXPECT_GL_NO_ERROR(); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_DONT_CARE, GL_KEEP, GL_DONT_CARE})); EXPECT_GL_NO_ERROR(); // Enabling the mismatched size plane errors. @@ -3228,7 +3240,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_planes) pls1.reset(); glBeginPixelLocalStorageANGLE(3, GLenumArray({GL_KEEP, GL_ZERO, GL_KEEP})); EXPECT_GL_NO_ERROR(); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_KEEP, GL_KEEP, GL_KEEP})); EXPECT_GL_NO_ERROR(); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); @@ -3262,7 +3274,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_planes) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt0, 0); glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_KEEP, GL_CLEAR_ANGLE})); EXPECT_GL_NO_ERROR(); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_KEEP, GL_DONT_CARE})); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); } @@ -3276,8 +3288,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_planes) EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG( "Draw framebuffer has no attachments and no enabled, texture-backed pixel local " - "storage " - "planes."); + "storage planes."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA8); @@ -3285,8 +3296,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_planes) EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG( "Draw framebuffer has no attachments and no enabled, texture-backed pixel local " - "storage " - "planes."); + "storage planes."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); } } @@ -3308,7 +3318,7 @@ TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_planes) TEST_P(PixelLocalStorageValidationTest, EndAndBarrierANGLE) { // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is zero. - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(0, nullptr); EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active."); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); @@ -3322,7 +3332,7 @@ TEST_P(PixelLocalStorageValidationTest, EndAndBarrierANGLE) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(1, nullptr); EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active."); @@ -3339,7 +3349,7 @@ TEST_P(PixelLocalStorageValidationTest, EndAndBarrierANGLE) EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active."); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(2, nullptr); EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active."); @@ -3358,13 +3368,15 @@ TEST_P(PixelLocalStorageValidationTest, EndAndBarrierANGLE) glPixelLocalStorageBarrierANGLE(); EXPECT_GL_NO_ERROR(); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE( + MAX_PIXEL_LOCAL_STORAGE_PLANES, + std::vector(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_DONT_CARE).data()); EXPECT_GL_NO_ERROR(); ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0); EXPECT_GL_NO_ERROR(); - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(0, nullptr); EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active."); @@ -3373,6 +3385,44 @@ TEST_P(PixelLocalStorageValidationTest, EndAndBarrierANGLE) EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active."); ASSERT_GL_NO_ERROR(); + + // INVALID_VALUE is generated if != PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE. + glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_KEEP, GL_DISABLE_ANGLE})); + ASSERT_GL_NO_ERROR(); + + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE); + EXPECT_GL_SINGLE_ERROR_MSG(" != ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE"); + + glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE); + EXPECT_GL_SINGLE_ERROR_MSG(" != ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE"); + + glEndPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_DONT_CARE})); + ASSERT_GL_NO_ERROR(); + + // INVALID_ENUM is generated if [0..PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE-1] is not + // one of the Store Operations enumerated in Table X.2. + glBeginPixelLocalStorageANGLE(3, GLenumArray({GL_KEEP, GL_DISABLE_ANGLE, GL_CLEAR_ANGLE})); + ASSERT_GL_NO_ERROR(); + + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_CLEAR_ANGLE, GL_DONT_CARE, GL_KEEP})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); + EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E4."); + + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_DONT_CARE, GL_DISABLE_ANGLE, GL_KEEP})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); + EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E5."); + + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_DONT_CARE, GL_KEEP, GL_ZERO})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); + EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x0000."); + + glEndPixelLocalStorageANGLE(3, GLenumArray({GL_DONT_CARE, GL_SCISSOR_BOX, GL_KEEP})); + EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM); + EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x0C10."); + + ASSERT_GL_NO_ERROR(); } // Check that glEndPixelLocalStorageANGLE and glPixelLocalStorageBarrierANGLE validate as specified. diff --git a/util/capture/frame_capture_replay_autogen.cpp b/util/capture/frame_capture_replay_autogen.cpp index fc5b7e168..31497b684 100644 --- a/util/capture/frame_capture_replay_autogen.cpp +++ b/util/capture/frame_capture_replay_autogen.cpp @@ -937,7 +937,8 @@ void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &cu glEndPerfMonitorAMD(captures[0].value.GLuintVal); break; case angle::EntryPoint::GLEndPixelLocalStorageANGLE: - glEndPixelLocalStorageANGLE(); + glEndPixelLocalStorageANGLE(captures[0].value.GLsizeiVal, + captures[1].value.GLenumConstPointerVal); break; case angle::EntryPoint::GLEndQuery: glEndQuery(captures[0].value.GLenumVal);