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