phoenix-firestorm/indra/llrender/llglslshader.h

346 lines
13 KiB
C++

/**
* @file llglslshader.h
* @brief GLSL shader wrappers
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLGLSLSHADER_H
#define LL_LLGLSLSHADER_H
#include "llgl.h"
#include "llrender.h"
#include "llstaticstringtable.h"
#include <unordered_map>
class LLShaderFeatures
{
public:
S32 mIndexedTextureChannels = 0;
bool calculatesLighting = false;
bool calculatesAtmospherics = false;
bool hasLighting = false; // implies no transport (it's possible to have neither though)
bool isAlphaLighting = false; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions)
bool isSpecular = false;
bool hasTransport = false; // implies no lighting (it's possible to have neither though)
bool hasSkinning = false;
bool hasObjectSkinning = false;
bool hasAtmospherics = false;
bool hasGamma = false;
bool hasShadows = false;
bool hasAmbientOcclusion = false;
bool hasSrgb = false;
bool isDeferred = false;
bool hasScreenSpaceReflections = false;
bool disableTextureIndex = false;
bool hasAlphaMask = false;
bool hasReflectionProbes = false;
bool attachNothing = false;
bool hasHeroProbes = false;
bool isPBRTerrain = false;
};
// ============= Structure for caching shader uniforms ===============
class LLGLSLShader;
class LLShaderUniforms
{
public:
template<typename T>
struct UniformSetting
{
S32 mUniform{ 0 };
T mValue{};
};
typedef UniformSetting<S32> IntSetting;
typedef UniformSetting<F32> FloatSetting;
typedef UniformSetting<LLVector4> VectorSetting;
typedef UniformSetting<LLVector3> Vector3Setting;
void clear()
{
mIntegers.resize(0);
mFloats.resize(0);
mVectors.resize(0);
mVector3s.resize(0);
}
void uniform1i(S32 index, S32 value)
{
mIntegers.push_back({ index, value });
}
void uniform1f(S32 index, F32 value)
{
mFloats.push_back({ index, value });
}
void uniform4fv(S32 index, const LLVector4& value)
{
mVectors.push_back({ index, value });
}
void uniform4fv(S32 index, const F32* value)
{
mVectors.push_back({ index, LLVector4(value) });
}
void uniform3fv(S32 index, const LLVector3& value)
{
mVector3s.push_back({ index, value });
}
void uniform3fv(S32 index, const F32* value)
{
mVector3s.push_back({ index, LLVector3(value) });
}
void apply(LLGLSLShader* shader);
std::vector<IntSetting> mIntegers;
std::vector<FloatSetting> mFloats;
std::vector<VectorSetting> mVectors;
std::vector<Vector3Setting> mVector3s;
};
class LLGLSLShader
{
public:
// NOTE: Keep gShaderConsts and LLGLSLShader::ShaderConsts_e in sync!
enum eShaderConsts
{
SHADER_CONST_CLOUD_MOON_DEPTH
, SHADER_CONST_STAR_DEPTH
, NUM_SHADER_CONSTS
};
// enum primarily used to control application sky settings uniforms
typedef enum
{
SG_DEFAULT = 0, // not sky or water specific
SG_SKY, //
SG_WATER,
SG_ANY,
SG_COUNT
} eGroup;
static std::set<LLGLSLShader*> sInstances;
static bool sProfileEnabled;
LLGLSLShader();
~LLGLSLShader();
static GLuint sCurBoundShader;
static LLGLSLShader* sCurBoundShaderPtr;
static S32 sIndexedTextureChannels;
static void initProfile();
static void finishProfile(bool emit_report = true);
static void startProfile();
static void stopProfile();
void unload();
void clearStats();
void dumpStats();
// place query objects for profiling if profiling is enabled
// if for_runtime is true, will place timer query only whether or not profiling is enabled
void placeProfileQuery(bool for_runtime = false);
// Readback query objects if profiling is enabled
// If for_runtime is true, will readback timer query iff query is available
// Will return false if a query is pending (try again later)
// If force_read is true, will force an immediate readback (severe performance penalty)
bool readProfileQuery(bool for_runtime = false, bool force_read = false);
bool createShader(std::vector<LLStaticHashedString>* attributes,
std::vector<LLStaticHashedString>* uniforms,
U32 varying_count = 0,
const char** varyings = NULL);
bool attachFragmentObject(std::string object);
bool attachVertexObject(std::string object);
void attachObject(GLuint object);
void attachObjects(GLuint* objects = NULL, S32 count = 0);
bool mapAttributes(const std::vector<LLStaticHashedString>* attributes);
bool mapUniforms(const std::vector<LLStaticHashedString>*);
void mapUniform(GLint index, const std::vector<LLStaticHashedString>*);
void uniform1i(U32 index, GLint i);
void uniform1f(U32 index, GLfloat v);
void fastUniform1f(U32 index, GLfloat v);
void uniform2f(U32 index, GLfloat x, GLfloat y);
void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z);
void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void uniform1iv(U32 index, U32 count, const GLint* i);
void uniform4iv(U32 index, U32 count, const GLint* i);
void uniform1fv(U32 index, U32 count, const GLfloat* v);
void uniform2fv(U32 index, U32 count, const GLfloat* v);
void uniform3fv(U32 index, U32 count, const GLfloat* v);
void uniform4fv(U32 index, U32 count, const GLfloat* v);
void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
void uniform1i(const LLStaticHashedString& uniform, GLint i);
void uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
void uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v);
void setMinimumAlpha(F32 minimum);
void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void vertexAttrib4fv(U32 index, GLfloat* v);
//GLint getUniformLocation(const std::string& uniform);
GLint getUniformLocation(const LLStaticHashedString& uniform);
GLint getUniformLocation(U32 index);
GLint getAttribLocation(U32 attrib);
GLint mapUniformTextureChannel(GLint location, GLenum type, GLint size);
void clearPermutations();
void addPermutation(std::string name, std::string value);
void removePermutation(std::string name);
void addConstant(const LLGLSLShader::eShaderConsts shader_const);
//enable/disable texture channel for specified uniform
//if given texture uniform is active in the shader,
//the corresponding channel will be active upon return
//returns channel texture is enabled in from [0-MAX)
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
// get the texture channel of the given uniform, or -1 if uniform is not used as a texture
S32 getTextureChannel(S32 uniform) const;
// bindTexture returns the texture unit we've bound the texture to.
// You can reuse the return value to unbind a texture when required.
S32 bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
S32 bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
S32 bindTexture(const std::string& uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR);
S32 bindTexture(S32 uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR, U32 index = 0);
S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
bool link(bool suppress_errors = false);
void bind();
//helper to conditionally bind mRiggedVariant instead of this
void bind(bool rigged);
bool isComplete() const { return mProgramObject != 0; }
LLUUID hash();
// Unbinds any previously bound shader by explicitly binding no shader.
static void unbind();
U32 mMatHash[LLRender::NUM_MATRIX_MODES];
U32 mLightHash;
GLuint mProgramObject;
#if LL_RELEASE_WITH_DEBUG_INFO
struct attr_name
{
GLint loc;
const char* name;
void operator = (GLint _loc) { loc = _loc; }
operator GLint () { return loc; }
};
std::vector<attr_name> mAttribute; //lookup table of attribute enum to attribute channel
#else
std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
#endif
U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
typedef std::unordered_map<GLint, LLVector4> uniform_value_map_t;
uniform_value_map_t mValue; //lookup map of uniform location to last known value
std::vector<GLint> mTexture;
S32 mTotalUniformSize;
S32 mActiveTextureChannels;
S32 mShaderLevel;
S32 mShaderGroup; // see LLGLSLShader::eGroup
bool mUniformsDirty;
LLShaderFeatures mFeatures;
std::vector< std::pair< std::string, GLenum > > mShaderFiles;
std::string mName;
typedef std::map<std::string, std::string> defines_map_t; //NOTE: this must be an ordered map to maintain hash consistency
defines_map_t mDefines;
static defines_map_t sGlobalDefines;
LLUUID mShaderHash;
bool mUsingBinaryProgram = false;
//statistics for profiling shader performance
bool mProfilePending = false;
U32 mTimerQuery;
U32 mSamplesQuery;
U32 mPrimitivesQuery;
U64 mTimeElapsed;
static U64 sTotalTimeElapsed;
U32 mTrianglesDrawn;
static U32 sTotalTrianglesDrawn;
U64 mSamplesDrawn;
static U64 sTotalSamplesDrawn;
U32 mBinds;
static U32 sTotalBinds;
// this pointer should be set to whichever shader represents this shader's rigged variant
LLGLSLShader* mRiggedVariant = nullptr;
// hacky flag used for optimization in LLDrawPoolAlpha
bool mCanBindFast = false;
#ifdef LL_PROFILER_ENABLE_RENDER_DOC
void setLabel(const char* label);
#endif
private:
void unloadInternal();
};
//UI shader (declared here so llui_libtest will link properly)
extern LLGLSLShader gUIProgram;
//output vec4(color.rgb,color.a*tex0[tc0].a)
extern LLGLSLShader gSolidColorProgram;
//Alpha mask shader (declared here so llappearance can access properly)
extern LLGLSLShader gAlphaMaskProgram;
#ifdef LL_PROFILER_ENABLE_RENDER_DOC
#define LL_SET_SHADER_LABEL(shader) shader.setLabel(#shader)
#else
#define LL_SET_SHADER_LABEL(shader, label)
#endif
#endif