PixelLocalStorage.h (7251B)
1 // 2 // Copyright 2022 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // PixelLocalStorage.h: Defines the renderer-agnostic container classes 8 // gl::PixelLocalStorage and gl::PixelLocalStoragePlane for 9 // ANGLE_shader_pixel_local_storage. 10 11 #ifndef LIBANGLE_PIXEL_LOCAL_STORAGE_H_ 12 #define LIBANGLE_PIXEL_LOCAL_STORAGE_H_ 13 14 #include "angle_gl.h" 15 #include "libANGLE/ImageIndex.h" 16 #include "libANGLE/angletypes.h" 17 18 namespace gl 19 { 20 21 class Context; 22 class Texture; 23 24 // Holds the configuration of an ANGLE_shader_pixel_local_storage plane. 25 // 26 // Unlike normal framebuffer attachments, pixel local storage planes don't take effect until the 27 // application calls glBeginPixelLocalStorageANGLE, and the manner in which they take effect is 28 // highly dependent on the backend implementation. A PixelLocalStoragePlane is just a plain data 29 // description what to set up later once PLS is enabled. 30 class PixelLocalStoragePlane : angle::NonCopyable 31 { 32 public: 33 ~PixelLocalStoragePlane(); 34 35 // Called when the context is lost or destroyed. Causes this class to clear its GL object 36 // handles. 37 void onContextObjectsLost(); 38 39 // Called when the owning framebuffer is being destroyed. Causes this class to release its 40 // texture object reference. 41 void onFramebufferDestroyed(const Context *); 42 43 void deinitialize(Context *); 44 void setMemoryless(Context *, GLenum internalformat); 45 void setTextureBacked(Context *, Texture *, int level, int layer); 46 47 bool isDeinitialized() const { return mInternalformat == GL_NONE; } 48 49 // Returns true if the texture ID bound to this plane has been deleted. 50 // 51 // [ANGLE_shader_pixel_local_storage] Section 4.4.2.X "Configuring Pixel Local Storage 52 // on a Framebuffer": When a texture object is deleted, any pixel local storage plane to 53 // which it was bound is automatically converted to a memoryless plane of matching 54 // internalformat. 55 bool isTextureIDDeleted(const Context *) const; 56 57 bool isMemoryless() const 58 { 59 // isMemoryless() should be false if the plane is deinitialized. 60 ASSERT(!(isDeinitialized() && mMemoryless)); 61 return mMemoryless; 62 } 63 64 GLenum getInternalformat() const { return mInternalformat; } 65 66 // Implements glGetIntegeri_v() for GL_PIXEL_LOCAL_FORMAT_ANGLE, 67 // GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, and 68 // GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE 69 GLint getIntegeri(const Context *, GLenum target, GLuint index) const; 70 71 // If this plane is texture backed, stores the bound texture image's {width, height, 0} to 72 // Extents and returns true. Otherwise returns false, meaning the plane is either deinitialized 73 // or memoryless. 74 bool getTextureImageExtents(const Context *, Extents *extents) const; 75 76 // Attaches this plane to the specified color attachment point on the current draw framebuffer. 77 void attachToDrawFramebuffer(Context *, Extents plsExtents, GLenum colorAttachment); 78 79 // Clears the draw buffer at 0-based index 'drawbuffer' on the current framebuffer. Reads the 80 // clear value from 'data' if 'loadop' is GL_CLEAR_ANGLE, otherwise clears to zero. 81 // 82 // 'data' is interpereted as either 4 GLfloats, 4 GLints, or 4 GLuints, depending on 83 // mInternalFormat. 84 // 85 // The context must internally disable the scissor test before calling this method, since the 86 // intention is to clear the entire surface. 87 void performLoadOperationClear(Context *, GLint drawbuffer, GLenum loadop, const void *data); 88 89 // Binds this PLS plane to a texture image unit for image load/store shader operations. 90 void bindToImage(Context *, Extents plsExtents, GLuint unit, bool needsR32Packing); 91 92 private: 93 // Ensures we have an internal backing texture for memoryless planes. In GL, we need a backing 94 // texture even if the plane is memoryless; glInvalidateFramebuffer() will ideally prevent the 95 // driver from writing out data where possible. 96 void ensureBackingIfMemoryless(Context *, Extents plsSize); 97 98 GLenum mInternalformat = GL_NONE; // GL_NONE if this plane is in a deinitialized state. 99 bool mMemoryless = false; 100 TextureID mMemorylessTextureID{}; // We own memoryless backing textures and must delete them. 101 ImageIndex mTextureImageIndex; 102 Texture *mTextureRef = nullptr; 103 }; 104 105 // Manages a collection of PixelLocalStoragePlanes and applies them to ANGLE's GL state. 106 // 107 // The main magic of ANGLE_shader_pixel_local_storage happens inside shaders, so we just emulate the 108 // client API on top of ANGLE's OpenGL ES API for simplicity. 109 class PixelLocalStorage 110 { 111 public: 112 static std::unique_ptr<PixelLocalStorage> Make(const Context *); 113 114 PixelLocalStorage(); 115 virtual ~PixelLocalStorage(); 116 117 // Called when the owning framebuffer is being destroyed. 118 void onFramebufferDestroyed(const Context *); 119 120 // Deletes any GL objects that have been allocated for pixel local storage. These can't be 121 // cleaned up in the destructor because they require a non-const Context object. 122 void deleteContextObjects(Context *); 123 124 const PixelLocalStoragePlane &getPlane(GLint plane) const 125 { 126 ASSERT(0 <= plane && plane < IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES); 127 return mPlanes[plane]; 128 } 129 130 PixelLocalStoragePlane &getPlane(GLint plane) 131 { 132 ASSERT(0 <= plane && plane < IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES); 133 return mPlanes[plane]; 134 } 135 136 // ANGLE_shader_pixel_local_storage API. 137 void deinitialize(Context *context, GLint plane) { mPlanes[plane].deinitialize(context); } 138 void setMemoryless(Context *context, GLint plane, GLenum internalformat) 139 { 140 mPlanes[plane].setMemoryless(context, internalformat); 141 } 142 void setTextureBacked(Context *context, GLint plane, Texture *tex, int level, int layer) 143 { 144 mPlanes[plane].setTextureBacked(context, tex, level, layer); 145 } 146 void begin(Context *, GLsizei n, const GLenum loadops[], const void *cleardata); 147 void end(Context *); 148 void barrier(Context *); 149 150 protected: 151 // Called when the context is lost or destroyed. Causes the subclass to clear its GL object 152 // handles. 153 virtual void onContextObjectsLost() = 0; 154 155 // Called when the framebuffer is being destroyed. Causes the subclass to delete its frontend GL 156 // object handles. 157 virtual void onDeleteContextObjects(Context *) = 0; 158 159 // ANGLE_shader_pixel_local_storage API. 160 virtual void onBegin(Context *, 161 GLsizei n, 162 const GLenum loadops[], 163 const char *cleardata, 164 Extents plsSize) = 0; 165 virtual void onEnd(Context *, GLsizei numActivePLSPlanes) = 0; 166 virtual void onBarrier(Context *) = 0; 167 168 private: 169 std::array<PixelLocalStoragePlane, IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES> mPlanes; 170 171 // "n" from the last call to begin(), or 0 if pixel local storage is not active. 172 GLsizei mNumActivePLSPlanes = 0; 173 }; 174 175 } // namespace gl 176 177 #endif // LIBANGLE_PIXEL_LOCAL_STORAGE_H_