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