blob: 4bdd21f0a00a0d40c04a9150103a1878dacb0c92 [file] [log] [blame] [edit]
//
// 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_