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:
Stenzek 2016-11-27 18:14:56 +10:00
parent b987f220e1
commit abc662d69c
4 changed files with 164 additions and 57 deletions

View File

@ -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,

View File

@ -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();

View File

@ -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)

View File

@ -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;