xref: /aosp_15_r20/external/angle/src/libANGLE/PixelLocalStorage.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 "GLSLANG/ShaderLang.h"
15 #include "libANGLE/Caps.h"
16 #include "libANGLE/ImageIndex.h"
17 #include "libANGLE/angletypes.h"
18 
19 namespace gl
20 {
21 
22 class Context;
23 class Texture;
24 
25 // Holds the configuration of an ANGLE_shader_pixel_local_storage plane.
26 //
27 // Unlike normal framebuffer attachments, pixel local storage planes don't take effect until the
28 // application calls glBeginPixelLocalStorageANGLE, and the manner in which they take effect is
29 // highly dependent on the backend implementation. A PixelLocalStoragePlane is just a plain data
30 // description what to set up later once PLS is enabled.
31 class PixelLocalStoragePlane : angle::NonCopyable, public angle::ObserverInterface
32 {
33   public:
34     PixelLocalStoragePlane();
35     ~PixelLocalStoragePlane() override;
36 
37     // Called when the context is lost or destroyed. Causes this class to clear its GL object
38     // handles.
39     void onContextObjectsLost();
40 
41     void deinitialize(Context *);
42     void setMemoryless(Context *, GLenum internalformat);
43     void setTextureBacked(Context *, Texture *, int level, int layer);
44     void onSubjectStateChange(angle::SubjectIndex, angle::SubjectMessage) override;
45 
46     // Returns true if the plane is deinitialized, either explicitly or implicitly via deleting the
47     // texture that was attached to it.
48     bool isDeinitialized() const;
49 
getInternalformat()50     GLenum getInternalformat() const { return mInternalformat; }
isMemoryless()51     bool isMemoryless() const { return mMemoryless; }
getTextureID()52     TextureID getTextureID() const { return mTextureID; }
53 
54     // Implements glGetIntegeri_v() for GL_PIXEL_LOCAL_FORMAT_ANGLE,
55     // GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, and
56     // GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE
57     GLint getIntegeri(GLenum target) const;
58 
59     // If this plane is texture backed, stores the bound texture image's {width, height, 0} to
60     // Extents and returns true. Otherwise returns false, meaning the plane is either deinitialized
61     // or memoryless.
62     bool getTextureImageExtents(const Context *, Extents *extents) const;
63 
64     // Ensures we have an internal backing texture for memoryless planes. In some implementations we
65     // need a backing texture even if the plane is memoryless.
66     void ensureBackingTextureIfMemoryless(Context *, Extents plsSize);
67 
68     // Attaches this plane to the specified color attachment point on the current draw framebuffer.
69     void attachToDrawFramebuffer(Context *, GLenum colorAttachment) const;
70 
71     // Interface for clearing typed pixel local storage planes.
72     class ClearCommands
73     {
74       public:
~ClearCommands()75         virtual ~ClearCommands() {}
76         virtual void clearfv(int target, const GLfloat[]) const = 0;
77         virtual void cleariv(int target, const GLint[]) const   = 0;
78         virtual void clearuiv(int target, const GLuint[]) const = 0;
79     };
80 
81     // Issues the approprite command from ClearCommands for this plane's internalformat. Uses the
82     // clear state value that corresponds to mInternalFormat, and potentially clamps it to ensure it
83     // is representable.
84     void issueClearCommand(ClearCommands *, int target, GLenum loadop) const;
85 
86     // Binds this PLS plane to a texture image unit for image load/store shader operations.
87     void bindToImage(Context *, GLuint unit, bool needsR32Packing) const;
88 
89     // Low-level access to the backing texture. The plane must not be memoryless or deinitialized.
getTextureImageIndex()90     const ImageIndex &getTextureImageIndex() const { return mTextureImageIndex; }
91     const Texture *getBackingTexture(const Context *context) const;
92 
setClearValuef(const GLfloat value[4])93     void setClearValuef(const GLfloat value[4]) { memcpy(mClearValuef.data(), value, 4 * 4); }
setClearValuei(const GLint value[4])94     void setClearValuei(const GLint value[4]) { memcpy(mClearValuei.data(), value, 4 * 4); }
setClearValueui(const GLuint value[4])95     void setClearValueui(const GLuint value[4]) { memcpy(mClearValueui.data(), value, 4 * 4); }
96 
getClearValuef(GLfloat value[4])97     void getClearValuef(GLfloat value[4]) const { memcpy(value, mClearValuef.data(), 4 * 4); }
getClearValuei(GLint value[4])98     void getClearValuei(GLint value[4]) const { memcpy(value, mClearValuei.data(), 4 * 4); }
getClearValueui(GLuint value[4])99     void getClearValueui(GLuint value[4]) const { memcpy(value, mClearValueui.data(), 4 * 4); }
100 
101     // True if PLS is currently active and this plane is enabled.
isActive()102     bool isActive() const { return mActive; }
markActive(bool active)103     void markActive(bool active) { mActive = active; }
104 
105   private:
106     GLenum mInternalformat = GL_NONE;  // GL_NONE if this plane is in a deinitialized state.
107     bool mMemoryless       = false;
108     TextureID mTextureID   = TextureID();
109     ImageIndex mTextureImageIndex;
110 
111     // Clear value state.
112     std::array<GLfloat, 4> mClearValuef{};
113     std::array<GLint, 4> mClearValuei{};
114     std::array<GLuint, 4> mClearValueui{};
115 
116     // True if PLS is currently active and this plane is enabled.
117     bool mActive = false;
118 
119     angle::ObserverBinding mTextureObserver;
120 };
121 
122 // Manages a collection of PixelLocalStoragePlanes and applies them to ANGLE's GL state.
123 //
124 // The main magic of ANGLE_shader_pixel_local_storage happens inside shaders, so we just emulate the
125 // client API on top of ANGLE's OpenGL ES API for simplicity.
126 class PixelLocalStorage
127 {
128   public:
129     static std::unique_ptr<PixelLocalStorage> Make(const Context *);
130 
131     virtual ~PixelLocalStorage();
132 
133     // Called when the owning framebuffer is being destroyed.
134     void onFramebufferDestroyed(const Context *);
135 
136     // Deletes any GL objects that have been allocated for pixel local storage. These can't be
137     // cleaned up in the destructor because they require a non-const Context object.
138     void deleteContextObjects(Context *);
139 
getPlane(GLint plane)140     const PixelLocalStoragePlane &getPlane(GLint plane) const
141     {
142         ASSERT(0 <= plane && plane < IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);
143         return mPlanes[plane];
144     }
145 
getPlanes()146     const PixelLocalStoragePlane *getPlanes() { return mPlanes.data(); }
147 
interruptCount()148     size_t interruptCount() const { return mInterruptCount; }
149 
150     // ANGLE_shader_pixel_local_storage API.
deinitialize(Context * context,GLint plane)151     void deinitialize(Context *context, GLint plane) { mPlanes[plane].deinitialize(context); }
setMemoryless(Context * context,GLint plane,GLenum internalformat)152     void setMemoryless(Context *context, GLint plane, GLenum internalformat)
153     {
154         mPlanes[plane].setMemoryless(context, internalformat);
155     }
setTextureBacked(Context * context,GLint plane,Texture * tex,int level,int layer)156     void setTextureBacked(Context *context, GLint plane, Texture *tex, int level, int layer)
157     {
158         mPlanes[plane].setTextureBacked(context, tex, level, layer);
159     }
setClearValuef(GLint plane,const GLfloat val[4])160     void setClearValuef(GLint plane, const GLfloat val[4]) { mPlanes[plane].setClearValuef(val); }
setClearValuei(GLint plane,const GLint val[4])161     void setClearValuei(GLint plane, const GLint val[4]) { mPlanes[plane].setClearValuei(val); }
setClearValueui(GLint plane,const GLuint val[4])162     void setClearValueui(GLint plane, const GLuint val[4]) { mPlanes[plane].setClearValueui(val); }
163     void begin(Context *, GLsizei n, const GLenum loadops[]);
164     void end(Context *, GLsizei n, const GLenum storeops[]);
165     void barrier(Context *);
166     void interrupt(Context *);
167     void restore(Context *);
168 
169     // While pixel local storage is active, the draw buffers on and after
170     // 'FirstOverriddenDrawBuffer' are blocked from the client and reserved for internal use by PLS.
FirstOverriddenDrawBuffer(const Caps & caps,GLuint numActivePlanes)171     static GLint FirstOverriddenDrawBuffer(const Caps &caps, GLuint numActivePlanes)
172     {
173         ASSERT(numActivePlanes > 0);
174         return std::min(caps.maxColorAttachmentsWithActivePixelLocalStorage,
175                         caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - numActivePlanes);
176     }
177 
178   protected:
179     PixelLocalStorage(const ShPixelLocalStorageOptions &, const Caps &);
180 
181     // Called when the context is lost or destroyed. Causes the subclass to clear its GL object
182     // handles.
183     virtual void onContextObjectsLost() = 0;
184 
185     // Called when the framebuffer is being destroyed. Causes the subclass to delete its frontend GL
186     // object handles.
187     virtual void onDeleteContextObjects(Context *) = 0;
188 
189     // ANGLE_shader_pixel_local_storage API.
190     virtual void onBegin(Context *, GLsizei n, const GLenum loadops[], Extents plsSize) = 0;
191     virtual void onEnd(Context *, GLsizei n, const GLenum storeops[])                   = 0;
192     virtual void onBarrier(Context *)                                                   = 0;
193 
194     const ShPixelLocalStorageOptions mPLSOptions;
195 
196   private:
197     angle::FixedVector<PixelLocalStoragePlane, IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES>
198         mPlanes;
199     size_t mInterruptCount           = 0;
200     GLsizei mActivePlanesAtInterrupt = 0;
201 };
202 
203 }  // namespace gl
204 
205 #endif  // LIBANGLE_PIXEL_LOCAL_STORAGE_H_
206