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