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