OpenGL: Share the shader version detection.

Use a version integer instead of a string
This commit is contained in:
Henrik Rydgård 2020-10-22 09:04:42 +02:00
parent c45515866b
commit 9e245d6835
7 changed files with 95 additions and 138 deletions

View File

@ -140,7 +140,8 @@ enum DoLightComputation {
};
struct GLSLShaderCompat {
const char *versionString;
int glslVersionNumber;
bool gles;
const char *varying_fs;
const char *varying_vs;
const char *attribute;
@ -150,7 +151,6 @@ struct GLSLShaderCompat {
const char *texelFetch;
const char *lastFragData;
const char *framebufferFetchExtension;
bool gles;
bool glslES30;
bool bitwiseOps;
};

View File

@ -33,89 +33,9 @@
#define WRITE p+=sprintf
// #define DEBUG_SHADER
// Missing: Z depth range
bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uniformMask, std::string *errorString) {
bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, const GLSLShaderCompat &compat, uint64_t *uniformMask, std::string *errorString) {
*uniformMask = 0;
GLSLShaderCompat compat{};
compat.varying_vs = "varying";
compat.varying_fs = "varying";
compat.fragColor0 = "gl_FragColor";
compat.fragColor1 = "fragColor1";
compat.texture = "texture2D";
compat.texelFetch = nullptr;
compat.bitwiseOps = false;
compat.lastFragData = nullptr;
compat.gles = gl_extensions.IsGLES;
if (compat.gles) {
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) {
compat.versionString = "#version 300 es"; // GLSL ES 3.0
compat.fragColor0 = "fragColor0";
compat.texture = "texture";
compat.glslES30 = true;
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch";
} else {
compat.versionString = "#version 100"; // GLSL ES 1.0
if (gl_extensions.EXT_gpu_shader4) {
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch2D";
}
if (gl_extensions.EXT_blend_func_extended) {
// Oldy moldy GLES, so use the fixed output name.
compat.fragColor1 = "gl_SecondaryFragColorEXT";
}
}
} else {
if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) {
if (gl_extensions.VersionGEThan(3, 3, 0)) {
compat.versionString = "#version 330";
compat.fragColor0 = "fragColor0";
compat.texture = "texture";
compat.glslES30 = true;
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch";
} else if (gl_extensions.VersionGEThan(3, 0, 0)) {
compat.versionString = "#version 130";
compat.fragColor0 = "fragColor0";
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch";
} else {
compat.versionString = "#version 110";
if (gl_extensions.EXT_gpu_shader4) {
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch2D";
}
}
}
}
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300) && gl_extensions.EXT_shader_framebuffer_fetch) {
compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
compat.lastFragData = "fragColor0";
} else if (gl_extensions.EXT_shader_framebuffer_fetch) {
compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
compat.lastFragData = "gl_LastFragData[0]";
} else if (gl_extensions.NV_shader_framebuffer_fetch) {
// GL_NV_shader_framebuffer_fetch is available on mobile platform and ES 2.0 only but not on desktop.
compat.framebufferFetchExtension = "#extension GL_NV_shader_framebuffer_fetch : require";
compat.lastFragData = "gl_LastFragData[0]";
} else if (gl_extensions.ARM_shader_framebuffer_fetch) {
compat.framebufferFetchExtension = "#extension GL_ARM_shader_framebuffer_fetch : require";
compat.lastFragData = "gl_LastFragColorARM";
}
}
if (compat.glslES30 || gl_extensions.IsCoreContext) {
compat.varying_vs = "out";
compat.varying_fs = "in";
compat.attribute = "in";
}
bool highpFog = false;
bool highpTexcoord = false;
if (compat.gles) {
@ -129,8 +49,7 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
char *p = buffer;
// Here the writing starts!
WRITE(p, "%s\n", compat.versionString);
WRITE(p, "#version %d%s\n", compat.glslVersionNumber, compat.gles ? " es" : "");
if (stencilToAlpha == REPLACE_ALPHA_DUALSOURCE && gl_extensions.EXT_blend_func_extended) {
WRITE(p, "#extension GL_EXT_blend_func_extended : require\n");

View File

@ -17,6 +17,8 @@
#pragma once
#include "GPU/Common/ShaderCommon.h"
struct FShaderID;
bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uniformMask, std::string *errorString);
bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, const GLSLShaderCompat &compat, uint64_t *uniformMask, std::string *errorString);

View File

@ -576,12 +576,93 @@ ShaderManagerGLES::ShaderManagerGLES(Draw::DrawContext *draw)
codeBuffer_ = new char[16384];
lastFSID_.set_invalid();
lastVSID_.set_invalid();
DetectShaderLanguage();
}
ShaderManagerGLES::~ShaderManagerGLES() {
delete [] codeBuffer_;
}
void ShaderManagerGLES::DetectShaderLanguage() {
GLSLShaderCompat &compat = compat_;
compat.attribute = "attribute";
compat.varying_vs = "varying";
compat.varying_fs = "varying";
compat.fragColor0 = "gl_FragColor";
compat.fragColor1 = "fragColor1";
compat.texture = "texture2D";
compat.texelFetch = nullptr;
compat.bitwiseOps = false;
compat.lastFragData = nullptr;
compat.gles = gl_extensions.IsGLES;
if (compat.gles) {
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) {
compat.glslVersionNumber = 300; // GLSL ES 3.0
compat.fragColor0 = "fragColor0";
compat.texture = "texture";
compat.glslES30 = true;
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch";
} else {
compat.glslVersionNumber = 100; // GLSL ES 1.0
if (gl_extensions.EXT_gpu_shader4) {
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch2D";
}
if (gl_extensions.EXT_blend_func_extended) {
// Oldy moldy GLES, so use the fixed output name.
compat.fragColor1 = "gl_SecondaryFragColorEXT";
}
}
} else {
if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) {
if (gl_extensions.VersionGEThan(3, 3, 0)) {
compat.glslVersionNumber = 330;
compat.fragColor0 = "fragColor0";
compat.texture = "texture";
compat.glslES30 = true;
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch";
} else if (gl_extensions.VersionGEThan(3, 0, 0)) {
compat.glslVersionNumber = 130;
compat.fragColor0 = "fragColor0";
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch";
} else {
compat.glslVersionNumber = 110;
if (gl_extensions.EXT_gpu_shader4) {
compat.bitwiseOps = true;
compat.texelFetch = "texelFetch2D";
}
}
}
}
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300) && gl_extensions.EXT_shader_framebuffer_fetch) {
compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
compat.lastFragData = "fragColor0";
} else if (gl_extensions.EXT_shader_framebuffer_fetch) {
compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
compat.lastFragData = "gl_LastFragData[0]";
} else if (gl_extensions.NV_shader_framebuffer_fetch) {
// GL_NV_shader_framebuffer_fetch is available on mobile platform and ES 2.0 only but not on desktop.
compat.framebufferFetchExtension = "#extension GL_NV_shader_framebuffer_fetch : require";
compat.lastFragData = "gl_LastFragData[0]";
} else if (gl_extensions.ARM_shader_framebuffer_fetch) {
compat.framebufferFetchExtension = "#extension GL_ARM_shader_framebuffer_fetch : require";
compat.lastFragData = "gl_LastFragColorARM";
}
}
if (compat.glslES30 || gl_extensions.IsCoreContext) {
compat.varying_vs = "out";
compat.varying_fs = "in";
compat.attribute = "in";
}
}
void ShaderManagerGLES::Clear() {
DirtyLastShader();
for (auto iter = linkedShaderCache_.begin(); iter != linkedShaderCache_.end(); ++iter) {
@ -630,7 +711,7 @@ void ShaderManagerGLES::DirtyLastShader() {
Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) {
uint64_t uniformMask;
std::string errorString;
if (!GenerateFragmentShaderGLSL(FSID, codeBuffer_, &uniformMask, &errorString)) {
if (!GenerateFragmentShaderGLSL(FSID, codeBuffer_, compat_, &uniformMask, &errorString)) {
ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str());
return nullptr;
}
@ -643,7 +724,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) {
uint32_t attrMask;
uint64_t uniformMask;
std::string errorString;
if (!GenerateVertexShaderGLSL(VSID, codeBuffer_, &attrMask, &uniformMask, &errorString)) {
if (!GenerateVertexShaderGLSL(VSID, codeBuffer_, compat_, &attrMask, &uniformMask, &errorString)) {
ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str());
return nullptr;
}

View File

@ -183,6 +183,7 @@ private:
void Clear();
Shader *CompileFragmentShader(FShaderID id);
Shader *CompileVertexShader(VShaderID id);
void DetectShaderLanguage();
struct LinkedShaderCacheEntry {
LinkedShaderCacheEntry(Shader *vs_, Shader *fs_, LinkedShader *ls_)
@ -195,6 +196,7 @@ private:
typedef std::vector<LinkedShaderCacheEntry> LinkedShaderCache;
GLRenderManager *render_;
GLSLShaderCompat compat_{};
LinkedShaderCache linkedShaderCache_;
bool lastVShaderSame_;

View File

@ -87,59 +87,12 @@ static const char * const boneWeightInDecl[9] = {
// TODO: Skip all this if we can actually get a 16-bit depth buffer along with stencil, which
// is a bit of a rare configuration, although quite common on mobile.
bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString) {
bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, const GLSLShaderCompat &compat, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString) {
*attrMask = 0;
*uniformMask = 0;
// In GLSL ES 3.0, you use "out" variables instead.
GLSLShaderCompat compat{};
compat.glslES30 = false;
compat.varying_vs = "varying";
compat.varying_fs = "varying";
compat.attribute = "attribute";
compat.texelFetch = nullptr;
compat.gles = gl_extensions.IsGLES;
if (compat.gles) {
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) {
compat.versionString = "#version 300 es"; // GLSL ES 3.0
compat.glslES30 = true;
compat.texelFetch = "texelFetch";
} else {
compat.versionString = "#version 100"; // GLSL ES 1.0
if (gl_extensions.EXT_gpu_shader4) {
compat.texelFetch = "texelFetch2D";
}
}
} else {
if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) {
if (gl_extensions.VersionGEThan(3, 3, 0)) {
compat.glslES30 = true;
compat.versionString = "#version 330";
compat.texelFetch = "texelFetch";
} else if (gl_extensions.VersionGEThan(3, 0, 0)) {
compat.versionString = "#version 130";
if (gl_extensions.EXT_gpu_shader4) {
compat.texelFetch = "texelFetch";
}
} else {
compat.versionString = "#version 110";
if (gl_extensions.EXT_gpu_shader4) {
compat.texelFetch = "texelFetch2D";
}
}
}
}
if (compat.glslES30 || gl_extensions.IsCoreContext) {
compat.attribute = "in";
compat.varying_vs = "out";
compat.varying_fs = "in";
}
char *p = buffer;
// Here the writing starts!
WRITE(p, "%s\n", compat.versionString);
WRITE(p, "#version %d%s\n", compat.glslVersionNumber, compat.gles ? " es" : "");
bool highpFog = false;
bool highpTexcoord = false;

View File

@ -21,4 +21,4 @@
struct VShaderID;
bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString);
bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, const GLSLShaderCompat &compat, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString);