OGL: Support compute shaders and emitting GLSL 4.3
This also changes bSupportsEarlyFragmentTests to bSupportsImageLoadStore, as it is used for both.
This commit is contained in:
parent
b987f220e1
commit
abc662d69c
|
@ -65,6 +65,8 @@ static std::string GetGLSLVersionString()
|
|||
return "#version 330";
|
||||
case GLSL_400:
|
||||
return "#version 400";
|
||||
case GLSL_430:
|
||||
return "#version 430";
|
||||
default:
|
||||
// Shouldn't ever hit this
|
||||
return "#version ERROR";
|
||||
|
@ -103,27 +105,30 @@ void SHADER::SetProgramVariables()
|
|||
}
|
||||
}
|
||||
|
||||
void SHADER::SetProgramBindings()
|
||||
void SHADER::SetProgramBindings(bool is_compute)
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
|
||||
if (!is_compute)
|
||||
{
|
||||
// So we do support extended blending
|
||||
// So we need to set a few more things here.
|
||||
// Bind our out locations
|
||||
glBindFragDataLocationIndexed(glprogid, 0, 0, "ocol0");
|
||||
glBindFragDataLocationIndexed(glprogid, 0, 1, "ocol1");
|
||||
if (g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
|
||||
{
|
||||
// So we do support extended blending
|
||||
// So we need to set a few more things here.
|
||||
// Bind our out locations
|
||||
glBindFragDataLocationIndexed(glprogid, 0, 0, "ocol0");
|
||||
glBindFragDataLocationIndexed(glprogid, 0, 1, "ocol1");
|
||||
}
|
||||
// Need to set some attribute locations
|
||||
glBindAttribLocation(glprogid, SHADER_POSITION_ATTRIB, "rawpos");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_POSMTX_ATTRIB, "posmtx");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_COLOR0_ATTRIB, "color0");
|
||||
glBindAttribLocation(glprogid, SHADER_COLOR1_ATTRIB, "color1");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_NORM0_ATTRIB, "rawnorm0");
|
||||
glBindAttribLocation(glprogid, SHADER_NORM1_ATTRIB, "rawnorm1");
|
||||
glBindAttribLocation(glprogid, SHADER_NORM2_ATTRIB, "rawnorm2");
|
||||
}
|
||||
// Need to set some attribute locations
|
||||
glBindAttribLocation(glprogid, SHADER_POSITION_ATTRIB, "rawpos");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_POSMTX_ATTRIB, "posmtx");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_COLOR0_ATTRIB, "color0");
|
||||
glBindAttribLocation(glprogid, SHADER_COLOR1_ATTRIB, "color1");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_NORM0_ATTRIB, "rawnorm0");
|
||||
glBindAttribLocation(glprogid, SHADER_NORM1_ATTRIB, "rawnorm1");
|
||||
glBindAttribLocation(glprogid, SHADER_NORM2_ATTRIB, "rawnorm2");
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
|
@ -281,7 +286,7 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const std::string& vcode,
|
|||
if (g_ogl_config.bSupportsGLSLCache)
|
||||
glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
||||
|
||||
shader.SetProgramBindings();
|
||||
shader.SetProgramBindings(false);
|
||||
|
||||
glLinkProgram(pid);
|
||||
|
||||
|
@ -296,10 +301,10 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const std::string& vcode,
|
|||
glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length);
|
||||
if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
|
||||
{
|
||||
GLsizei charsWritten;
|
||||
GLchar* infoLog = new GLchar[length];
|
||||
glGetProgramInfoLog(pid, length, &charsWritten, infoLog);
|
||||
ERROR_LOG(VIDEO, "Program info log:\n%s", infoLog);
|
||||
std::string info_log;
|
||||
info_log.resize(length);
|
||||
glGetProgramInfoLog(pid, length, &length, &info_log[0]);
|
||||
ERROR_LOG(VIDEO, "Program info log:\n%s", info_log.c_str());
|
||||
|
||||
std::string filename =
|
||||
StringFromFormat("%sbad_p_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
|
@ -308,7 +313,7 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const std::string& vcode,
|
|||
file << s_glsl_header << vcode << s_glsl_header << pcode;
|
||||
if (!gcode.empty())
|
||||
file << s_glsl_header << gcode;
|
||||
file << infoLog;
|
||||
file << info_log;
|
||||
file.close();
|
||||
|
||||
if (linkStatus != GL_TRUE)
|
||||
|
@ -316,10 +321,8 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const std::string& vcode,
|
|||
PanicAlert("Failed to link shaders: %s\n"
|
||||
"Debug info (%s, %s, %s):\n%s",
|
||||
filename.c_str(), g_ogl_config.gl_vendor, g_ogl_config.gl_renderer,
|
||||
g_ogl_config.gl_version, infoLog);
|
||||
g_ogl_config.gl_version, info_log.c_str());
|
||||
}
|
||||
|
||||
delete[] infoLog;
|
||||
}
|
||||
if (linkStatus != GL_TRUE)
|
||||
{
|
||||
|
@ -336,6 +339,73 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const std::string& vcode,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ProgramShaderCache::CompileComputeShader(SHADER& shader, const std::string& code)
|
||||
{
|
||||
// We need to enable GL_ARB_compute_shader for drivers that support the extension,
|
||||
// but not GLSL 4.3. Mesa is one example.
|
||||
std::string header;
|
||||
if (g_ActiveConfig.backend_info.bSupportsComputeShaders &&
|
||||
g_ogl_config.eSupportedGLSLVersion < GLSL_430)
|
||||
{
|
||||
header = "#extension GL_ARB_compute_shader : enable\n";
|
||||
}
|
||||
|
||||
GLuint shader_id = CompileSingleShader(GL_COMPUTE_SHADER, header + code);
|
||||
if (!shader_id)
|
||||
return false;
|
||||
|
||||
GLuint pid = shader.glprogid = glCreateProgram();
|
||||
glAttachShader(pid, shader_id);
|
||||
if (g_ogl_config.bSupportsGLSLCache)
|
||||
glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
||||
|
||||
shader.SetProgramBindings(true);
|
||||
|
||||
glLinkProgram(pid);
|
||||
|
||||
// original shaders aren't needed any more
|
||||
glDeleteShader(shader_id);
|
||||
|
||||
GLint linkStatus;
|
||||
glGetProgramiv(pid, GL_LINK_STATUS, &linkStatus);
|
||||
GLsizei length = 0;
|
||||
glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length);
|
||||
if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
|
||||
{
|
||||
std::string info_log;
|
||||
info_log.resize(length);
|
||||
glGetProgramInfoLog(pid, length, &length, &info_log[0]);
|
||||
ERROR_LOG(VIDEO, "Program info log:\n%s", info_log.c_str());
|
||||
|
||||
std::string filename =
|
||||
StringFromFormat("%sbad_p_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
std::ofstream file;
|
||||
OpenFStream(file, filename, std::ios_base::out);
|
||||
file << s_glsl_header << code;
|
||||
file << info_log;
|
||||
file.close();
|
||||
|
||||
if (linkStatus != GL_TRUE)
|
||||
{
|
||||
PanicAlert("Failed to link shaders: %s\n"
|
||||
"Debug info (%s, %s, %s):\n%s",
|
||||
filename.c_str(), g_ogl_config.gl_vendor, g_ogl_config.gl_renderer,
|
||||
g_ogl_config.gl_version, info_log.c_str());
|
||||
}
|
||||
}
|
||||
if (linkStatus != GL_TRUE)
|
||||
{
|
||||
// Compile failed
|
||||
ERROR_LOG(VIDEO, "Program linking failed; see info log");
|
||||
|
||||
// Don't try to use this shader
|
||||
glDeleteProgram(pid);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLuint ProgramShaderCache::CompileSingleShader(GLuint type, const std::string& code)
|
||||
{
|
||||
GLuint result = glCreateShader(type);
|
||||
|
@ -351,31 +421,43 @@ GLuint ProgramShaderCache::CompileSingleShader(GLuint type, const std::string& c
|
|||
|
||||
if (compileStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
|
||||
{
|
||||
GLsizei charsWritten;
|
||||
GLchar* infoLog = new GLchar[length];
|
||||
glGetShaderInfoLog(result, length, &charsWritten, infoLog);
|
||||
ERROR_LOG(VIDEO, "%s Shader info log:\n%s",
|
||||
type == GL_VERTEX_SHADER ? "VS" : type == GL_FRAGMENT_SHADER ? "PS" : "GS", infoLog);
|
||||
std::string info_log;
|
||||
info_log.resize(length);
|
||||
glGetShaderInfoLog(result, length, &length, &info_log[0]);
|
||||
|
||||
const char* prefix = "";
|
||||
switch (type)
|
||||
{
|
||||
case GL_VERTEX_SHADER:
|
||||
prefix = "vs";
|
||||
break;
|
||||
case GL_GEOMETRY_SHADER:
|
||||
prefix = "gs";
|
||||
break;
|
||||
case GL_FRAGMENT_SHADER:
|
||||
prefix = "ps";
|
||||
break;
|
||||
case GL_COMPUTE_SHADER:
|
||||
prefix = "cs";
|
||||
break;
|
||||
}
|
||||
|
||||
ERROR_LOG(VIDEO, "%s Shader info log:\n%s", prefix, info_log.c_str());
|
||||
|
||||
std::string filename = StringFromFormat(
|
||||
"%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(),
|
||||
type == GL_VERTEX_SHADER ? "vs" : type == GL_FRAGMENT_SHADER ? "ps" : "gs", num_failures++);
|
||||
"%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), prefix, num_failures++);
|
||||
std::ofstream file;
|
||||
OpenFStream(file, filename, std::ios_base::out);
|
||||
file << s_glsl_header << code << infoLog;
|
||||
file << s_glsl_header << code << info_log;
|
||||
file.close();
|
||||
|
||||
if (compileStatus != GL_TRUE)
|
||||
{
|
||||
PanicAlert("Failed to compile %s shader: %s\n"
|
||||
"Debug info (%s, %s, %s):\n%s",
|
||||
type == GL_VERTEX_SHADER ? "vertex" : type == GL_FRAGMENT_SHADER ? "pixel" :
|
||||
"geometry",
|
||||
filename.c_str(), g_ogl_config.gl_vendor, g_ogl_config.gl_renderer,
|
||||
g_ogl_config.gl_version, infoLog);
|
||||
prefix, filename.c_str(), g_ogl_config.gl_vendor, g_ogl_config.gl_renderer,
|
||||
g_ogl_config.gl_version, info_log.c_str());
|
||||
}
|
||||
|
||||
delete[] infoLog;
|
||||
}
|
||||
if (compileStatus != GL_TRUE)
|
||||
{
|
||||
|
@ -539,11 +621,9 @@ void ProgramShaderCache::CreateHeader()
|
|||
std::string earlyz_string = "";
|
||||
if (g_ActiveConfig.backend_info.bSupportsEarlyZ)
|
||||
{
|
||||
if (g_ogl_config.bSupportsEarlyFragmentTests)
|
||||
if (g_ogl_config.bSupportsImageLoadStore)
|
||||
{
|
||||
earlyz_string = "#define FORCE_EARLY_Z layout(early_fragment_tests) in\n";
|
||||
if (!is_glsles) // GLES supports this by default
|
||||
earlyz_string += "#extension GL_ARB_shader_image_load_store : enable\n";
|
||||
}
|
||||
else if (g_ogl_config.bSupportsConservativeDepth)
|
||||
{
|
||||
|
@ -569,6 +649,7 @@ void ProgramShaderCache::CreateHeader()
|
|||
"%s\n" // texture buffer
|
||||
"%s\n" // ES texture buffer
|
||||
"%s\n" // ES dual source blend
|
||||
"%s\n" // shader image load store
|
||||
|
||||
// Precision defines for GLSL ES
|
||||
"%s\n"
|
||||
|
@ -576,6 +657,7 @@ void ProgramShaderCache::CreateHeader()
|
|||
"%s\n"
|
||||
"%s\n"
|
||||
"%s\n"
|
||||
"%s\n"
|
||||
|
||||
// Silly differences
|
||||
"#define float2 vec2\n"
|
||||
|
@ -638,12 +720,17 @@ void ProgramShaderCache::CreateHeader()
|
|||
""
|
||||
|
||||
,
|
||||
g_ogl_config.bSupportsImageLoadStore &&
|
||||
((!is_glsles && v < GLSL_430) || (is_glsles && v < GLSLES_310)) ?
|
||||
"#extension GL_ARB_shader_image_load_store : enable" :
|
||||
"",
|
||||
is_glsles ? "precision highp float;" : "", is_glsles ? "precision highp int;" : "",
|
||||
is_glsles ? "precision highp sampler2DArray;" : "",
|
||||
(is_glsles && g_ActiveConfig.backend_info.bSupportsPaletteConversion) ?
|
||||
"precision highp usamplerBuffer;" :
|
||||
"",
|
||||
v > GLSLES_300 ? "precision highp sampler2DMS;" : "");
|
||||
v > GLSLES_300 ? "precision highp sampler2DMS;" : "",
|
||||
v >= GLSLES_310 ? "precision highp image2DArray;" : "");
|
||||
}
|
||||
|
||||
void ProgramShaderCache::ProgramShaderCacheInserter::Read(const SHADERUID& key, const u8* value,
|
||||
|
|
|
@ -46,7 +46,7 @@ struct SHADER
|
|||
std::string strvprog, strpprog, strgprog;
|
||||
|
||||
void SetProgramVariables();
|
||||
void SetProgramBindings();
|
||||
void SetProgramBindings(bool is_compute);
|
||||
void Bind();
|
||||
};
|
||||
|
||||
|
@ -67,6 +67,7 @@ public:
|
|||
|
||||
static bool CompileShader(SHADER& shader, const std::string& vcode, const std::string& pcode,
|
||||
const std::string& gcode = "");
|
||||
static bool CompileComputeShader(SHADER& shader, const std::string& code);
|
||||
static GLuint CompileSingleShader(GLuint type, const std::string& code);
|
||||
static void UploadConstants();
|
||||
|
||||
|
|
|
@ -457,10 +457,10 @@ Renderer::Renderer()
|
|||
GLExtensions::Supports("GL_OES_texture_storage_multisample_2d_array");
|
||||
g_ogl_config.bSupports2DTextureStorageMultisample =
|
||||
GLExtensions::Supports("GL_ARB_texture_storage_multisample");
|
||||
g_ogl_config.bSupportsEarlyFragmentTests =
|
||||
GLExtensions::Supports("GL_ARB_shader_image_load_store");
|
||||
g_ogl_config.bSupportsImageLoadStore = GLExtensions::Supports("GL_ARB_shader_image_load_store");
|
||||
g_ogl_config.bSupportsConservativeDepth = GLExtensions::Supports("GL_ARB_conservative_depth");
|
||||
g_ogl_config.bSupportsAniso = GLExtensions::Supports("GL_EXT_texture_filter_anisotropic");
|
||||
g_Config.backend_info.bSupportsComputeShaders = GLExtensions::Supports("GL_ARB_compute_shader");
|
||||
|
||||
if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3)
|
||||
{
|
||||
|
@ -495,8 +495,9 @@ Renderer::Renderer()
|
|||
g_ogl_config.eSupportedGLSLVersion = GLSLES_310;
|
||||
g_ogl_config.bSupportsAEP = GLExtensions::Supports("GL_ANDROID_extension_pack_es31a");
|
||||
g_Config.backend_info.bSupportsBindingLayout = true;
|
||||
g_ogl_config.bSupportsEarlyFragmentTests = true;
|
||||
g_ogl_config.bSupportsImageLoadStore = true;
|
||||
g_Config.backend_info.bSupportsGeometryShaders = g_ogl_config.bSupportsAEP;
|
||||
g_Config.backend_info.bSupportsComputeShaders = true;
|
||||
g_Config.backend_info.bSupportsGSInstancing =
|
||||
g_Config.backend_info.bSupportsGeometryShaders && g_ogl_config.SupportedESPointSize > 0;
|
||||
g_Config.backend_info.bSupportsSSAA = g_ogl_config.bSupportsAEP;
|
||||
|
@ -517,8 +518,9 @@ Renderer::Renderer()
|
|||
g_ogl_config.eSupportedGLSLVersion = GLSLES_320;
|
||||
g_ogl_config.bSupportsAEP = GLExtensions::Supports("GL_ANDROID_extension_pack_es31a");
|
||||
g_Config.backend_info.bSupportsBindingLayout = true;
|
||||
g_ogl_config.bSupportsEarlyFragmentTests = true;
|
||||
g_ogl_config.bSupportsImageLoadStore = true;
|
||||
g_Config.backend_info.bSupportsGeometryShaders = true;
|
||||
g_Config.backend_info.bSupportsComputeShaders = true;
|
||||
g_Config.backend_info.bSupportsGSInstancing = g_ogl_config.SupportedESPointSize > 0;
|
||||
g_Config.backend_info.bSupportsPaletteConversion = true;
|
||||
g_Config.backend_info.bSupportsSSAA = true;
|
||||
|
@ -545,8 +547,7 @@ Renderer::Renderer()
|
|||
else if (GLExtensions::Version() == 300)
|
||||
{
|
||||
g_ogl_config.eSupportedGLSLVersion = GLSL_130;
|
||||
g_ogl_config.bSupportsEarlyFragmentTests =
|
||||
false; // layout keyword is only supported on glsl150+
|
||||
g_ogl_config.bSupportsImageLoadStore = false; // layout keyword is only supported on glsl150+
|
||||
g_ogl_config.bSupportsConservativeDepth =
|
||||
false; // layout keyword is only supported on glsl150+
|
||||
g_Config.backend_info.bSupportsGeometryShaders =
|
||||
|
@ -555,8 +556,7 @@ Renderer::Renderer()
|
|||
else if (GLExtensions::Version() == 310)
|
||||
{
|
||||
g_ogl_config.eSupportedGLSLVersion = GLSL_140;
|
||||
g_ogl_config.bSupportsEarlyFragmentTests =
|
||||
false; // layout keyword is only supported on glsl150+
|
||||
g_ogl_config.bSupportsImageLoadStore = false; // layout keyword is only supported on glsl150+
|
||||
g_ogl_config.bSupportsConservativeDepth =
|
||||
false; // layout keyword is only supported on glsl150+
|
||||
g_Config.backend_info.bSupportsGeometryShaders =
|
||||
|
@ -570,10 +570,28 @@ Renderer::Renderer()
|
|||
{
|
||||
g_ogl_config.eSupportedGLSLVersion = GLSL_330;
|
||||
}
|
||||
else if (GLExtensions::Version() >= 430)
|
||||
{
|
||||
// TODO: We should really parse the GL_SHADING_LANGUAGE_VERSION token.
|
||||
g_ogl_config.eSupportedGLSLVersion = GLSL_430;
|
||||
g_ogl_config.bSupportsTextureStorage = true;
|
||||
g_ogl_config.bSupportsImageLoadStore = true;
|
||||
g_Config.backend_info.bSupportsSSAA = true;
|
||||
|
||||
// Compute shaders are core in GL4.3.
|
||||
g_Config.backend_info.bSupportsComputeShaders = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ogl_config.eSupportedGLSLVersion = GLSL_400;
|
||||
g_Config.backend_info.bSupportsSSAA = true;
|
||||
|
||||
if (GLExtensions::Version() == 420)
|
||||
{
|
||||
// Texture storage and shader image load/store are core in GL4.2.
|
||||
g_ogl_config.bSupportsTextureStorage = true;
|
||||
g_ogl_config.bSupportsImageLoadStore = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Desktop OpenGL can't have the Android Extension Pack
|
||||
|
@ -582,7 +600,7 @@ Renderer::Renderer()
|
|||
|
||||
// Either method can do early-z tests. See PixelShaderGen for details.
|
||||
g_Config.backend_info.bSupportsEarlyZ =
|
||||
g_ogl_config.bSupportsEarlyFragmentTests || g_ogl_config.bSupportsConservativeDepth;
|
||||
g_ogl_config.bSupportsImageLoadStore || g_ogl_config.bSupportsConservativeDepth;
|
||||
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &g_ogl_config.max_samples);
|
||||
if (g_ogl_config.max_samples < 1 || !g_ogl_config.bSupportsMSAA)
|
||||
|
|
|
@ -22,7 +22,8 @@ enum GLSL_VERSION
|
|||
GLSL_140,
|
||||
GLSL_150,
|
||||
GLSL_330,
|
||||
GLSL_400, // and above
|
||||
GLSL_400, // and above
|
||||
GLSL_430,
|
||||
GLSLES_300, // GLES 3.0
|
||||
GLSLES_310, // GLES 3.1
|
||||
GLSLES_320, // GLES 3.2
|
||||
|
@ -54,8 +55,8 @@ struct VideoConfig
|
|||
bool bSupportsTextureStorage;
|
||||
bool bSupports2DTextureStorageMultisample;
|
||||
bool bSupports3DTextureStorageMultisample;
|
||||
bool bSupportsEarlyFragmentTests;
|
||||
bool bSupportsConservativeDepth;
|
||||
bool bSupportsImageLoadStore;
|
||||
bool bSupportsAniso;
|
||||
|
||||
const char* gl_vendor;
|
||||
|
|
Loading…
Reference in New Issue