mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-28 16:00:58 +00:00
GL: Compute "availableUniform" when generating shaders instead of by querying.
This commit is contained in:
parent
32df9e25da
commit
33d3d2f178
@ -36,9 +36,10 @@
|
||||
// #define DEBUG_SHADER
|
||||
|
||||
// Missing: Z depth range
|
||||
bool GenerateFragmentShader(const ShaderID &id, char *buffer) {
|
||||
bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformMask) {
|
||||
char *p = buffer;
|
||||
|
||||
*uniformMask = 0;
|
||||
// In GLSL ES 3.0, you use "in" variables instead of varying.
|
||||
|
||||
bool glslES30 = false;
|
||||
@ -180,6 +181,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer) {
|
||||
WRITE(p, "uniform sampler2D tex;\n");
|
||||
|
||||
if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
|
||||
*uniformMask |= DIRTY_SHADERBLEND;
|
||||
if (!gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH) && replaceBlend == REPLACE_BLEND_COPY_FBO) {
|
||||
if (!texelFetch) {
|
||||
WRITE(p, "uniform vec2 u_fbotexSize;\n");
|
||||
@ -195,6 +197,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer) {
|
||||
}
|
||||
|
||||
if (needShaderTexClamp && doTexture) {
|
||||
*uniformMask |= DIRTY_TEXCLAMP;
|
||||
WRITE(p, "uniform vec4 u_texclamp;\n");
|
||||
if (id.Bit(FS_BIT_TEXTURE_AT_OFFSET)) {
|
||||
WRITE(p, "uniform vec2 u_texclampoff;\n");
|
||||
@ -205,8 +208,10 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer) {
|
||||
if (g_Config.bFragmentTestCache) {
|
||||
WRITE(p, "uniform sampler2D testtex;\n");
|
||||
} else {
|
||||
*uniformMask |= DIRTY_ALPHACOLORREF;
|
||||
WRITE(p, "uniform vec4 u_alphacolorref;\n");
|
||||
if (bitwiseOps && ((enableColorTest && !colorTestAgainstZero) || (enableAlphaTest && !alphaTestAgainstZero))) {
|
||||
*uniformMask |= DIRTY_ALPHACOLORMASK;
|
||||
WRITE(p, "uniform ivec4 u_alphacolormask;\n");
|
||||
}
|
||||
}
|
||||
@ -214,15 +219,19 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer) {
|
||||
|
||||
StencilValueType replaceAlphaWithStencilType = (StencilValueType)id.Bits(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, 4);
|
||||
if (stencilToAlpha && replaceAlphaWithStencilType == STENCIL_VALUE_UNIFORM) {
|
||||
*uniformMask |= DIRTY_STENCILREPLACEVALUE;
|
||||
WRITE(p, "uniform float u_stencilReplaceValue;\n");
|
||||
}
|
||||
if (doTexture && texFunc == GE_TEXFUNC_BLEND)
|
||||
if (doTexture && texFunc == GE_TEXFUNC_BLEND) {
|
||||
*uniformMask |= DIRTY_TEXENV;
|
||||
WRITE(p, "uniform vec3 u_texenv;\n");
|
||||
}
|
||||
|
||||
WRITE(p, "%s %s vec4 v_color0;\n", shading, varying);
|
||||
if (lmode)
|
||||
WRITE(p, "%s %s vec3 v_color1;\n", shading, varying);
|
||||
if (enableFog) {
|
||||
*uniformMask |= DIRTY_FOGCOLOR;
|
||||
WRITE(p, "uniform vec3 u_fogcolor;\n");
|
||||
WRITE(p, "%s %s float v_fogdepth;\n", varying, highpFog ? "highp" : "mediump");
|
||||
}
|
||||
|
@ -19,4 +19,4 @@
|
||||
|
||||
struct ShaderID;
|
||||
|
||||
bool GenerateFragmentShader(const ShaderID &id, char *buffer);
|
||||
bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformMask);
|
||||
|
@ -43,8 +43,8 @@
|
||||
#include "GPU/GLES/DrawEngineGLES.h"
|
||||
#include "FramebufferManagerGLES.h"
|
||||
|
||||
Shader::Shader(const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask)
|
||||
: failed_(false), useHWTransform_(useHWTransform), attrMask_(attrMask) {
|
||||
Shader::Shader(const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask)
|
||||
: failed_(false), useHWTransform_(useHWTransform), attrMask_(attrMask), uniformMask_(uniformMask) {
|
||||
PROFILE_THIS_SCOPE("shadercomp");
|
||||
isFragment_ = glShaderType == GL_FRAGMENT_SHADER;
|
||||
source_ = code;
|
||||
@ -242,54 +242,7 @@ LinkedShader::LinkedShader(ShaderID VSID, Shader *vs, ShaderID FSID, Shader *fs,
|
||||
u_spline_type_v = glGetUniformLocation(program, "u_spline_type_v");
|
||||
|
||||
attrMask = vs->GetAttrMask();
|
||||
|
||||
availableUniforms = 0;
|
||||
if (u_proj != -1) availableUniforms |= DIRTY_PROJMATRIX;
|
||||
if (u_proj_through != -1) availableUniforms |= DIRTY_PROJTHROUGHMATRIX;
|
||||
if (u_texenv != -1) availableUniforms |= DIRTY_TEXENV;
|
||||
if (u_alphacolorref != -1) availableUniforms |= DIRTY_ALPHACOLORREF;
|
||||
if (u_alphacolormask != -1) availableUniforms |= DIRTY_ALPHACOLORMASK;
|
||||
if (u_fogcolor != -1) availableUniforms |= DIRTY_FOGCOLOR;
|
||||
if (u_fogcoef != -1) availableUniforms |= DIRTY_FOGCOEF;
|
||||
if (u_texenv != -1) availableUniforms |= DIRTY_TEXENV;
|
||||
if (u_uvscaleoffset != -1) availableUniforms |= DIRTY_UVSCALEOFFSET;
|
||||
if (u_texclamp != -1) availableUniforms |= DIRTY_TEXCLAMP;
|
||||
if (u_world != -1) availableUniforms |= DIRTY_WORLDMATRIX;
|
||||
if (u_view != -1) availableUniforms |= DIRTY_VIEWMATRIX;
|
||||
if (u_texmtx != -1) availableUniforms |= DIRTY_TEXMATRIX;
|
||||
if (u_stencilReplaceValue != -1) availableUniforms |= DIRTY_STENCILREPLACEVALUE;
|
||||
if (u_blendFixA != -1 || u_blendFixB != -1 || u_fbotexSize != -1) availableUniforms |= DIRTY_SHADERBLEND;
|
||||
if (u_depthRange != -1)
|
||||
availableUniforms |= DIRTY_DEPTHRANGE;
|
||||
|
||||
// Looping up to numBones lets us avoid checking u_bone[i]
|
||||
#ifdef USE_BONE_ARRAY
|
||||
if (u_bone != -1) {
|
||||
for (int i = 0; i < numBones; i++) {
|
||||
availableUniforms |= DIRTY_BONEMATRIX0 << i;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < numBones; i++) {
|
||||
if (u_bone[i] != -1)
|
||||
availableUniforms |= DIRTY_BONEMATRIX0 << i;
|
||||
}
|
||||
#endif
|
||||
if (u_ambient != -1) availableUniforms |= DIRTY_AMBIENT;
|
||||
if (u_matambientalpha != -1) availableUniforms |= DIRTY_MATAMBIENTALPHA;
|
||||
if (u_matdiffuse != -1) availableUniforms |= DIRTY_MATDIFFUSE;
|
||||
if (u_matemissive != -1) availableUniforms |= DIRTY_MATEMISSIVE;
|
||||
if (u_matspecular != -1) availableUniforms |= DIRTY_MATSPECULAR;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (u_lightdir[i] != -1 ||
|
||||
u_lightspecular[i] != -1 ||
|
||||
u_lightpos[i] != -1)
|
||||
availableUniforms |= DIRTY_LIGHT0 << i;
|
||||
}
|
||||
if (u_spline_count_u != -1) availableUniforms |= DIRTY_BEZIERSPLINE;
|
||||
if (u_spline_count_v != -1) availableUniforms |= DIRTY_BEZIERSPLINE;
|
||||
if (u_spline_type_u != -1) availableUniforms |= DIRTY_BEZIERSPLINE;
|
||||
if (u_spline_type_v != -1) availableUniforms |= DIRTY_BEZIERSPLINE;
|
||||
availableUniforms = vs->GetUniformMask() | fs->GetUniformMask();
|
||||
|
||||
glUseProgram(program);
|
||||
|
||||
@ -297,7 +250,6 @@ LinkedShader::LinkedShader(ShaderID VSID, Shader *vs, ShaderID FSID, Shader *fs,
|
||||
glUniform1i(u_tex, 0);
|
||||
glUniform1i(u_fbotex, 1);
|
||||
glUniform1i(u_testtex, 2);
|
||||
|
||||
|
||||
if (u_tess_pos_tex != -1)
|
||||
glUniform1i(u_tess_pos_tex, 4); // Texture unit 4
|
||||
@ -782,17 +734,19 @@ void ShaderManagerGLES::DirtyLastShader() { // disables vertex arrays
|
||||
}
|
||||
|
||||
Shader *ShaderManagerGLES::CompileFragmentShader(ShaderID FSID) {
|
||||
if (!GenerateFragmentShader(FSID, codeBuffer_)) {
|
||||
uint64_t uniformMask;
|
||||
if (!GenerateFragmentShader(FSID, codeBuffer_, &uniformMask)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new Shader(codeBuffer_, GL_FRAGMENT_SHADER, false);
|
||||
return new Shader(codeBuffer_, GL_FRAGMENT_SHADER, false, 0, uniformMask);
|
||||
}
|
||||
|
||||
Shader *ShaderManagerGLES::CompileVertexShader(ShaderID VSID) {
|
||||
bool useHWTransform = VSID.Bit(VS_BIT_USE_HW_TRANSFORM);
|
||||
uint32_t attrMask;
|
||||
GenerateVertexShader(VSID, codeBuffer_, &attrMask);
|
||||
return new Shader(codeBuffer_, GL_VERTEX_SHADER, useHWTransform, attrMask);
|
||||
uint64_t uniformMask;
|
||||
GenerateVertexShader(VSID, codeBuffer_, &attrMask, &uniformMask);
|
||||
return new Shader(codeBuffer_, GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask);
|
||||
}
|
||||
|
||||
Shader *ShaderManagerGLES::ApplyVertexShader(int prim, u32 vertType, ShaderID *VSID) {
|
||||
@ -841,8 +795,9 @@ Shader *ShaderManagerGLES::ApplyVertexShader(int prim, u32 vertType, ShaderID *V
|
||||
ShaderID vsidTemp;
|
||||
ComputeVertexShaderID(&vsidTemp, vertType, false);
|
||||
uint32_t attrMask;
|
||||
GenerateVertexShader(vsidTemp, codeBuffer_, &attrMask);
|
||||
vs = new Shader(codeBuffer_, GL_VERTEX_SHADER, false, attrMask);
|
||||
uint64_t uniformMask;
|
||||
GenerateVertexShader(vsidTemp, codeBuffer_, &attrMask, &uniformMask);
|
||||
vs = new Shader(codeBuffer_, GL_VERTEX_SHADER, false, attrMask, uniformMask);
|
||||
}
|
||||
|
||||
vsCache_.Insert(*VSID, vs);
|
||||
|
@ -124,7 +124,7 @@ public:
|
||||
|
||||
class Shader {
|
||||
public:
|
||||
Shader(const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask = 0);
|
||||
Shader(const char *code, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask);
|
||||
~Shader();
|
||||
uint32_t shader;
|
||||
|
||||
@ -134,6 +134,7 @@ public:
|
||||
std::string GetShaderString(DebugShaderStringType type, ShaderID id) const;
|
||||
|
||||
uint32_t GetAttrMask() const { return attrMask_; }
|
||||
uint64_t GetUniformMask() const { return uniformMask_; }
|
||||
|
||||
private:
|
||||
std::string source_;
|
||||
@ -141,6 +142,7 @@ private:
|
||||
bool useHWTransform_;
|
||||
bool isFragment_;
|
||||
uint32_t attrMask_; // only used in vertex shaders
|
||||
uint64_t uniformMask_;
|
||||
};
|
||||
|
||||
class ShaderManagerGLES : public ShaderManagerCommon {
|
||||
|
@ -95,9 +95,10 @@ enum DoLightComputation {
|
||||
// is a bit of a rare configuration, although quite common on mobile.
|
||||
|
||||
|
||||
void GenerateVertexShader(const ShaderID &id, char *buffer, uint32_t *attrMask) {
|
||||
void GenerateVertexShader(const ShaderID &id, char *buffer, uint32_t *attrMask, uint64_t *uniformMask) {
|
||||
char *p = buffer;
|
||||
*attrMask = 0;
|
||||
*uniformMask = 0;
|
||||
// #define USE_FOR_LOOP
|
||||
|
||||
// In GLSL ES 3.0, you use "out" variables instead.
|
||||
@ -250,10 +251,12 @@ void GenerateVertexShader(const ShaderID &id, char *buffer, uint32_t *attrMask)
|
||||
}
|
||||
}
|
||||
|
||||
if (isModeThrough) {
|
||||
if (isModeThrough) {
|
||||
WRITE(p, "uniform mat4 u_proj_through;\n");
|
||||
*uniformMask |= DIRTY_PROJTHROUGHMATRIX;
|
||||
} else {
|
||||
WRITE(p, "uniform mat4 u_proj;\n");
|
||||
*uniformMask |= DIRTY_PROJMATRIX;
|
||||
// Add all the uniforms we'll need to transform properly.
|
||||
}
|
||||
|
||||
@ -263,28 +266,36 @@ void GenerateVertexShader(const ShaderID &id, char *buffer, uint32_t *attrMask)
|
||||
// When transforming by hardware, we need a great deal more uniforms...
|
||||
WRITE(p, "uniform mat4 u_world;\n");
|
||||
WRITE(p, "uniform mat4 u_view;\n");
|
||||
if (doTextureProjection)
|
||||
*uniformMask |= DIRTY_WORLDMATRIX | DIRTY_VIEWMATRIX;
|
||||
if (doTextureProjection) {
|
||||
WRITE(p, "uniform mediump mat4 u_texmtx;\n");
|
||||
*uniformMask |= DIRTY_TEXMATRIX;
|
||||
}
|
||||
if (enableBones) {
|
||||
#ifdef USE_BONE_ARRAY
|
||||
WRITE(p, "uniform mediump mat4 u_bone[%i];\n", numBoneWeights);
|
||||
*uniformMask |= DIRTY_BONE_UNIFORMS;
|
||||
#else
|
||||
for (int i = 0; i < numBoneWeights; i++) {
|
||||
WRITE(p, "uniform mat4 u_bone%i;\n", i);
|
||||
*uniformMask |= DIRTY_BONEMATRIX0 << i;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (doTexture) {
|
||||
WRITE(p, "uniform vec4 u_uvscaleoffset;\n");
|
||||
*uniformMask |= DIRTY_UVSCALEOFFSET;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (doLight[i] != LIGHT_OFF) {
|
||||
// This is needed for shade mapping
|
||||
WRITE(p, "uniform vec3 u_lightpos%i;\n", i);
|
||||
*uniformMask |= DIRTY_LIGHT0 << i;
|
||||
}
|
||||
if (doLight[i] == LIGHT_FULL) {
|
||||
GELightType type = static_cast<GELightType>(id.Bits(VS_BIT_LIGHT0_TYPE + 4*i, 2));
|
||||
GELightComputation comp = static_cast<GELightComputation>(id.Bits(VS_BIT_LIGHT0_COMP + 4*i, 2));
|
||||
*uniformMask |= DIRTY_LIGHT0 << i;
|
||||
GELightType type = static_cast<GELightType>(id.Bits(VS_BIT_LIGHT0_TYPE + 4 * i, 2));
|
||||
GELightComputation comp = static_cast<GELightComputation>(id.Bits(VS_BIT_LIGHT0_COMP + 4 * i, 2));
|
||||
|
||||
if (type != GE_LIGHTTYPE_DIRECTIONAL)
|
||||
WRITE(p, "uniform mediump vec3 u_lightatt%i;\n", i);
|
||||
@ -304,22 +315,29 @@ void GenerateVertexShader(const ShaderID &id, char *buffer, uint32_t *attrMask)
|
||||
}
|
||||
if (enableLighting) {
|
||||
WRITE(p, "uniform lowp vec4 u_ambient;\n");
|
||||
if ((matUpdate & 2) == 0 || !hasColor)
|
||||
*uniformMask |= DIRTY_AMBIENT;
|
||||
if ((matUpdate & 2) == 0 || !hasColor) {
|
||||
WRITE(p, "uniform lowp vec3 u_matdiffuse;\n");
|
||||
*uniformMask |= DIRTY_MATDIFFUSE;
|
||||
}
|
||||
WRITE(p, "uniform lowp vec4 u_matspecular;\n"); // Specular coef is contained in alpha
|
||||
WRITE(p, "uniform lowp vec3 u_matemissive;\n");
|
||||
*uniformMask |= DIRTY_MATSPECULAR | DIRTY_MATEMISSIVE;
|
||||
}
|
||||
}
|
||||
|
||||
if (useHWTransform || !hasColor)
|
||||
if (useHWTransform || !hasColor) {
|
||||
WRITE(p, "uniform lowp vec4 u_matambientalpha;\n"); // matambient + matalpha
|
||||
|
||||
*uniformMask |= DIRTY_MATAMBIENTALPHA;
|
||||
}
|
||||
if (enableFog) {
|
||||
WRITE(p, "uniform highp vec2 u_fogcoef;\n");
|
||||
*uniformMask |= DIRTY_FOGCOEF;
|
||||
}
|
||||
|
||||
if (!isModeThrough && gstate_c.Supports(GPU_ROUND_DEPTH_TO_16BIT)) {
|
||||
WRITE(p, "uniform highp vec4 u_depthRange;\n");
|
||||
*uniformMask |= DIRTY_DEPTHRANGE;
|
||||
}
|
||||
|
||||
WRITE(p, "%s%s lowp vec4 v_color0;\n", shading, varying);
|
||||
@ -354,6 +372,8 @@ void GenerateVertexShader(const ShaderID &id, char *buffer, uint32_t *attrMask)
|
||||
|
||||
// Hardware tessellation
|
||||
if (doBezier || doSpline) {
|
||||
*uniformMask |= DIRTY_BEZIERSPLINE;
|
||||
|
||||
const char *sampler = !isAllowTexture1D ? "sampler2D" : "sampler1D";
|
||||
WRITE(p, "uniform %s u_tess_pos_tex;\n", sampler);
|
||||
WRITE(p, "uniform %s u_tess_tex_tex;\n", sampler);
|
||||
|
@ -23,4 +23,4 @@
|
||||
|
||||
struct ShaderID;
|
||||
|
||||
void GenerateVertexShader(const ShaderID &id, char *buffer, uint32_t *attrMask);
|
||||
void GenerateVertexShader(const ShaderID &id, char *buffer, uint32_t *attrMask, uint64_t *uniformMask);
|
||||
|
Loading…
Reference in New Issue
Block a user