• 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 // PLSProgramCache.h: Implements a cache of native programs used to render load/store operations for
8 // EXT_shader_pixel_local_storage.
9 
10 #ifndef LIBANGLE_RENDERER_GL_PLS_PROGRAM_CACHE_H_
11 #define LIBANGLE_RENDERER_GL_PLS_PROGRAM_CACHE_H_
12 
13 #include "libANGLE/SizedMRUCache.h"
14 #include "libANGLE/renderer/gl/StateManagerGL.h"
15 
16 namespace gl
17 {
18 class PixelLocalStoragePlane;
19 struct Caps;
20 }  // namespace gl
21 
22 namespace rx
23 {
24 class FunctionsGL;
25 class PLSProgram;
26 class PLSProgramKey;
27 
28 // Implements a cache of native PLSPrograms used to render load/store operations for
29 // EXT_shader_pixel_local_storage.
30 //
31 // These programs require no vertex arrays, and draw fullscreen quads from 4-point
32 // GL_TRIANGLE_STRIPs:
33 //
34 //   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
35 //
36 class PLSProgramCache : angle::NonCopyable
37 {
38   public:
39     size_t MaximumTotalPrograms = 64 * 2;  // Enough programs for 64 unique PLS configurations.
40 
41     PLSProgramCache(const FunctionsGL *, const gl::Caps &nativeCaps);
42     ~PLSProgramCache();
43 
44     const PLSProgram *getProgram(PLSProgramKey);
45 
46     // An empty vertex array object to bind when rendering with a program from this cache.
getEmptyVAO()47     GLuint getEmptyVAO() { return mEmptyVAO; }
getEmptyVAOState()48     VertexArrayStateGL *getEmptyVAOState() { return &mEmptyVAOState; }
49 
50   private:
51     const FunctionsGL *const mGL;
52     const GLuint mVertexShaderID;
53     const GLuint mEmptyVAO;
54     VertexArrayStateGL mEmptyVAOState;
55     angle::SizedMRUCache<uint64_t, std::unique_ptr<PLSProgram>> mCache;
56 };
57 
58 enum class PLSProgramType : uint64_t
59 {
60     Load  = 0,  // Initializes PLS data with either a uniform color or an image load.
61     Store = 1   // Stores texture-backed PLS data out to images.
62 };
63 
64 // Re-enumerates PLS formats with a 0-based index, for tighter packing in a PLSProgramKey.
65 enum class PLSFormatKey : uint64_t
66 {
67     INACTIVE = 0,
68     RGBA8    = 1,
69     RGBA8I   = 2,
70     RGBA8UI  = 3,
71     R32F     = 4,
72     R32UI    = 5
73 };
74 
75 // Compact descriptor of an entire PLS load/store program. The LSB says whether the program is load
76 // or store, and each following run of 5 bits state the format of a specific plane and whether it is
77 // preserved.
78 class PLSProgramKey
79 {
80   public:
81     constexpr static int BitsPerPlane    = 5;
82     constexpr static int SinglePlaneMask = (1 << BitsPerPlane) - 1;
83 
84     PLSProgramKey() = default;
PLSProgramKey(const PLSProgramKey & key)85     PLSProgramKey(const PLSProgramKey &key) : PLSProgramKey(key.rawKey()) {}
PLSProgramKey(uint64_t rawKey)86     explicit PLSProgramKey(uint64_t rawKey) : mRawKey(rawKey) {}
87 
88     PLSProgramKey &operator=(const PLSProgramKey &key)
89     {
90         mRawKey = key.mRawKey;
91         return *this;
92     }
93 
rawKey()94     uint64_t rawKey() const { return mRawKey; }
95     PLSProgramType type() const;
96     bool areAnyPreserved() const;
97 
98     // Iterates each active plane in the descriptor, in order.
99     class Iter
100     {
101       public:
102         Iter() = default;
103         Iter(const PLSProgramKey &);
104 
binding()105         int binding() const { return mBinding; }
106         PLSFormatKey formatKey() const;
107         bool preserved() const;
108         std::tuple<int, PLSFormatKey, bool> operator*() const
109         {
110             return {binding(), formatKey(), preserved()};
111         }
112 
113         bool operator!=(const Iter &iter) const;
114         void operator++();
115 
116       private:
117         // Skips over any planes that are not active. The only effect inactive planes have on
118         // shaders is to offset the next binding index.
119         void skipInactivePlanes();
120 
121         int mBinding        = 0;
122         uint64_t mPlaneKeys = 0;
123     };
begin()124     Iter begin() const { return Iter(*this); }
end()125     Iter end() const { return Iter(); }
126 
127   private:
128     uint64_t mRawKey = 0;
129 };
130 
131 class PLSProgramKeyBuilder
132 {
133   public:
134     // Prepends a plane's format and whether it is preserved to the descriptor.
135     void prependPlane(GLenum internalformat, bool preserved);
136     PLSProgramKey finish(PLSProgramType);
137 
138   private:
139     uint64_t mRawKey = 0;
140 };
141 
142 class PLSProgram : angle::NonCopyable
143 {
144   public:
145     PLSProgram(const FunctionsGL *, GLuint vertexShaderID, PLSProgramKey);
146     ~PLSProgram();
147 
getProgramID()148     GLuint getProgramID() const { return mProgramID; }
149 
150     void setClearValues(const gl::PixelLocalStoragePlane[], const GLenum loadops[]) const;
151 
152   private:
153     const FunctionsGL *const mGL;
154     const PLSProgramKey mKey;
155     const GLuint mProgramID;
156     gl::DrawBuffersArray<GLint> mClearValueUniformLocations;
157 };
158 }  // namespace rx
159 
160 #endif  // LIBANGLE_RENDERER_GL_PLS_PROGRAM_CACHE_H_
161