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