Skip to content
Permalink
Browse files
Merge pull request #6141 from JonnyH/WIP/shader-framebuffer-fetch2
Implement dual-source blending in shader
  • Loading branch information
degasus committed Jan 5, 2018
2 parents 1cf1e7c + c709f3c commit dc08b73
Show file tree
Hide file tree
Showing 16 changed files with 453 additions and 100 deletions.
@@ -82,6 +82,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsBitfield = false;
g_Config.backend_info.bSupportsDynamicSamplerIndexing = false;
g_Config.backend_info.bSupportsBPTCTextures = false;
g_Config.backend_info.bSupportsFramebufferFetch = false;

IDXGIFactory2* factory;
IDXGIAdapter* ad;
@@ -46,6 +46,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsGPUTextureDecoding = false;
g_Config.backend_info.bSupportsST3CTextures = false;
g_Config.backend_info.bSupportsBPTCTextures = false;
g_Config.backend_info.bSupportsFramebufferFetch = false;

// aamodes: We only support 1 sample, so no MSAA
g_Config.backend_info.Adapters.clear();
@@ -64,26 +64,26 @@ static std::string s_glsl_header = "";

static std::string GetGLSLVersionString()
{
GLSL_VERSION v = g_ogl_config.eSupportedGLSLVersion;
GlslVersion v = g_ogl_config.eSupportedGLSLVersion;
switch (v)
{
case GLSLES_300:
case GlslEs300:
return "#version 300 es";
case GLSLES_310:
case GlslEs310:
return "#version 310 es";
case GLSLES_320:
case GlslEs320:
return "#version 320 es";
case GLSL_130:
case Glsl130:
return "#version 130";
case GLSL_140:
case Glsl140:
return "#version 140";
case GLSL_150:
case Glsl150:
return "#version 150";
case GLSL_330:
case Glsl330:
return "#version 330";
case GLSL_400:
case Glsl400:
return "#version 400";
case GLSL_430:
case Glsl430:
return "#version 430";
default:
// Shouldn't ever hit this
@@ -431,7 +431,7 @@ bool ProgramShaderCache::CompileComputeShader(SHADER& shader, const std::string&
// but not GLSL 4.3. Mesa is one example.
std::string header;
if (g_ActiveConfig.backend_info.bSupportsComputeShaders &&
g_ogl_config.eSupportedGLSLVersion < GLSL_430)
g_ogl_config.eSupportedGLSLVersion < Glsl430)
{
header = "#extension GL_ARB_compute_shader : enable\n";
}
@@ -839,8 +839,8 @@ void ProgramShaderCache::DestroyShaders()

void ProgramShaderCache::CreateHeader()
{
GLSL_VERSION v = g_ogl_config.eSupportedGLSLVersion;
bool is_glsles = v >= GLSLES_300;
GlslVersion v = g_ogl_config.eSupportedGLSLVersion;
bool is_glsles = v >= GlslEs300;
std::string SupportedESPointSize;
std::string SupportedESTextureBuffer;
switch (g_ogl_config.SupportedESPointSize)
@@ -858,14 +858,14 @@ void ProgramShaderCache::CreateHeader()

switch (g_ogl_config.SupportedESTextureBuffer)
{
case ES_TEXBUF_TYPE::TEXBUF_EXT:
case EsTexbufType::TexbufExt:
SupportedESTextureBuffer = "#extension GL_EXT_texture_buffer : enable";
break;
case ES_TEXBUF_TYPE::TEXBUF_OES:
case EsTexbufType::TexbufOes:
SupportedESTextureBuffer = "#extension GL_OES_texture_buffer : enable";
break;
case ES_TEXBUF_TYPE::TEXBUF_CORE:
case ES_TEXBUF_TYPE::TEXBUF_NONE:
case EsTexbufType::TexbufCore:
case EsTexbufType::TexbufNone:
SupportedESTextureBuffer = "";
break;
}
@@ -885,6 +885,24 @@ void ProgramShaderCache::CreateHeader()
}
}

std::string framebuffer_fetch_string;
switch (g_ogl_config.SupportedFramebufferFetch)
{
case EsFbFetchType::FbFetchExt:
framebuffer_fetch_string = "#extension GL_EXT_shader_framebuffer_fetch: enable\n"
"#define FB_FETCH_VALUE real_ocol0\n"
"#define FRAGMENT_INOUT inout";
break;
case EsFbFetchType::FbFetchArm:
framebuffer_fetch_string = "#extension GL_ARM_shader_framebuffer_fetch: enable\n"
"#define FB_FETCH_VALUE gl_LastFragColorARM\n"
"#define FRAGMENT_INOUT out";
break;
case EsFbFetchType::FbFetchNone:
framebuffer_fetch_string = "";
break;
}

s_glsl_header = StringFromFormat(
"%s\n"
"%s\n" // ubo
@@ -902,6 +920,7 @@ void ProgramShaderCache::CreateHeader()
"%s\n" // ES texture buffer
"%s\n" // ES dual source blend
"%s\n" // shader image load store
"%s\n" // shader framebuffer fetch

// Precision defines for GLSL ES
"%s\n"
@@ -928,11 +947,11 @@ void ProgramShaderCache::CreateHeader()

,
GetGLSLVersionString().c_str(),
v < GLSL_140 ? "#extension GL_ARB_uniform_buffer_object : enable" : "", earlyz_string.c_str(),
(g_ActiveConfig.backend_info.bSupportsBindingLayout && v < GLSLES_310) ?
v < Glsl140 ? "#extension GL_ARB_uniform_buffer_object : enable" : "", earlyz_string.c_str(),
(g_ActiveConfig.backend_info.bSupportsBindingLayout && v < GlslEs310) ?
"#extension GL_ARB_shading_language_420pack : enable" :
"",
(g_ogl_config.bSupportsMSAA && v < GLSL_150) ?
(g_ogl_config.bSupportsMSAA && v < Glsl150) ?
"#extension GL_ARB_texture_multisample : enable" :
"",
// Attribute and fragment output bindings are still done via glBindAttribLocation and
@@ -955,15 +974,15 @@ void ProgramShaderCache::CreateHeader()
!is_glsles && g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics ?
"#extension GL_ARB_shader_storage_buffer_object : enable" :
"",
v < GLSL_400 && g_ActiveConfig.backend_info.bSupportsGSInstancing ?
v < Glsl400 && g_ActiveConfig.backend_info.bSupportsGSInstancing ?
"#extension GL_ARB_gpu_shader5 : enable" :
"",
v < GLSL_400 && g_ActiveConfig.backend_info.bSupportsSSAA ?
v < Glsl400 && g_ActiveConfig.backend_info.bSupportsSSAA ?
"#extension GL_ARB_sample_shading : enable" :
"",
SupportedESPointSize.c_str(),
g_ogl_config.bSupportsAEP ? "#extension GL_ANDROID_extension_pack_es31a : enable" : "",
v < GLSL_140 && g_ActiveConfig.backend_info.bSupportsPaletteConversion ?
v < Glsl140 && g_ActiveConfig.backend_info.bSupportsPaletteConversion ?
"#extension GL_ARB_texture_buffer_object : enable" :
"",
SupportedESTextureBuffer.c_str(),
@@ -973,16 +992,16 @@ void ProgramShaderCache::CreateHeader()

,
g_ogl_config.bSupportsImageLoadStore &&
((!is_glsles && v < GLSL_430) || (is_glsles && v < GLSLES_310)) ?
((!is_glsles && v < Glsl430) || (is_glsles && v < GlslEs310)) ?
"#extension GL_ARB_shader_image_load_store : enable" :
"",
is_glsles ? "precision highp float;" : "", is_glsles ? "precision highp int;" : "",
is_glsles ? "precision highp sampler2DArray;" : "",
framebuffer_fetch_string.c_str(), 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_310 ? "precision highp image2DArray;" : "");
v > GlslEs300 ? "precision highp sampler2DMS;" : "",
v >= GlslEs310 ? "precision highp image2DArray;" : "");
}

void ProgramShaderCache::PrecompileUberShaders()
@@ -508,12 +508,12 @@ Renderer::Renderer()
1 :
GLExtensions::Supports("GL_EXT_geometry_point_size") ? 2 : 0;
g_ogl_config.SupportedESTextureBuffer = GLExtensions::Supports("VERSION_GLES_3_2") ?
ES_TEXBUF_TYPE::TEXBUF_CORE :
EsTexbufType::TexbufCore :
GLExtensions::Supports("GL_OES_texture_buffer") ?
ES_TEXBUF_TYPE::TEXBUF_OES :
EsTexbufType::TexbufOes :
GLExtensions::Supports("GL_EXT_texture_buffer") ?
ES_TEXBUF_TYPE::TEXBUF_EXT :
ES_TEXBUF_TYPE::TEXBUF_NONE;
EsTexbufType::TexbufExt :
EsTexbufType::TexbufNone;

g_ogl_config.bSupportsGLSLCache = true;
g_ogl_config.bSupportsGLSync = true;
@@ -522,16 +522,31 @@ Renderer::Renderer()
// depth clamping.
g_Config.backend_info.bSupportsDepthClamp = false;

if (GLExtensions::Supports("GL_EXT_shader_framebuffer_fetch"))
{
g_ogl_config.SupportedFramebufferFetch = EsFbFetchType::FbFetchExt;
}
else if (GLExtensions::Supports("GL_ARM_shader_framebuffer_fetch"))
{
g_ogl_config.SupportedFramebufferFetch = EsFbFetchType::FbFetchArm;
}
else
{
g_ogl_config.SupportedFramebufferFetch = EsFbFetchType::FbFetchNone;
}
g_Config.backend_info.bSupportsFramebufferFetch =
g_ogl_config.SupportedFramebufferFetch != EsFbFetchType::FbFetchNone;

if (GLExtensions::Version() == 300)
{
g_ogl_config.eSupportedGLSLVersion = GLSLES_300;
g_ogl_config.eSupportedGLSLVersion = GlslEs300;
g_ogl_config.bSupportsAEP = false;
g_ogl_config.bSupportsTextureStorage = true;
g_Config.backend_info.bSupportsGeometryShaders = false;
}
else if (GLExtensions::Version() == 310)
{
g_ogl_config.eSupportedGLSLVersion = GLSLES_310;
g_ogl_config.eSupportedGLSLVersion = GlslEs310;
g_ogl_config.bSupportsAEP = GLExtensions::Supports("GL_ANDROID_extension_pack_es31a");
g_Config.backend_info.bSupportsBindingLayout = true;
g_ogl_config.bSupportsImageLoadStore = true;
@@ -556,7 +571,7 @@ Renderer::Renderer()
}
else
{
g_ogl_config.eSupportedGLSLVersion = GLSLES_320;
g_ogl_config.eSupportedGLSLVersion = GlslEs320;
g_ogl_config.bSupportsAEP = GLExtensions::Supports("GL_ANDROID_extension_pack_es31a");
g_Config.backend_info.bSupportsBindingLayout = true;
g_ogl_config.bSupportsImageLoadStore = true;
@@ -589,7 +604,7 @@ Renderer::Renderer()
}
else if (GLExtensions::Version() == 300)
{
g_ogl_config.eSupportedGLSLVersion = GLSL_130;
g_ogl_config.eSupportedGLSLVersion = Glsl130;
g_ogl_config.bSupportsImageLoadStore = false; // layout keyword is only supported on glsl150+
g_ogl_config.bSupportsConservativeDepth =
false; // layout keyword is only supported on glsl150+
@@ -598,7 +613,7 @@ Renderer::Renderer()
}
else if (GLExtensions::Version() == 310)
{
g_ogl_config.eSupportedGLSLVersion = GLSL_140;
g_ogl_config.eSupportedGLSLVersion = Glsl140;
g_ogl_config.bSupportsImageLoadStore = false; // layout keyword is only supported on glsl150+
g_ogl_config.bSupportsConservativeDepth =
false; // layout keyword is only supported on glsl150+
@@ -607,16 +622,16 @@ Renderer::Renderer()
}
else if (GLExtensions::Version() == 320)
{
g_ogl_config.eSupportedGLSLVersion = GLSL_150;
g_ogl_config.eSupportedGLSLVersion = Glsl150;
}
else if (GLExtensions::Version() == 330)
{
g_ogl_config.eSupportedGLSLVersion = GLSL_330;
g_ogl_config.eSupportedGLSLVersion = Glsl330;
}
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.eSupportedGLSLVersion = Glsl430;
g_ogl_config.bSupportsTextureStorage = true;
g_ogl_config.bSupportsImageLoadStore = true;
g_Config.backend_info.bSupportsSSAA = true;
@@ -628,7 +643,7 @@ Renderer::Renderer()
}
else
{
g_ogl_config.eSupportedGLSLVersion = GLSL_400;
g_ogl_config.eSupportedGLSLVersion = Glsl400;
g_Config.backend_info.bSupportsSSAA = true;

if (GLExtensions::Version() == 420)
@@ -1275,44 +1290,54 @@ void Renderer::SetBlendingState(const BlendingState& state)
bool useDualSource =
state.usedualsrc && g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
(!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) || state.dstalpha);
// Only use shader blend if we need to and we don't support dual-source blending directly
bool useShaderBlend = !useDualSource && state.usedualsrc && state.dstalpha &&
g_ActiveConfig.backend_info.bSupportsFramebufferFetch;

const GLenum src_factors[8] = {
GL_ZERO,
GL_ONE,
GL_DST_COLOR,
GL_ONE_MINUS_DST_COLOR,
useDualSource ? GL_SRC1_ALPHA : (GLenum)GL_SRC_ALPHA,
useDualSource ? GL_ONE_MINUS_SRC1_ALPHA : (GLenum)GL_ONE_MINUS_SRC_ALPHA,
GL_DST_ALPHA,
GL_ONE_MINUS_DST_ALPHA};
const GLenum dst_factors[8] = {
GL_ZERO,
GL_ONE,
GL_SRC_COLOR,
GL_ONE_MINUS_SRC_COLOR,
useDualSource ? GL_SRC1_ALPHA : (GLenum)GL_SRC_ALPHA,
useDualSource ? GL_ONE_MINUS_SRC1_ALPHA : (GLenum)GL_ONE_MINUS_SRC_ALPHA,
GL_DST_ALPHA,
GL_ONE_MINUS_DST_ALPHA};

if (state.blendenable)
if (useShaderBlend)
{
glEnable(GL_BLEND);
glDisable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
}
const GLenum src_factors[8] = {
GL_ZERO,
GL_ONE,
GL_DST_COLOR,
GL_ONE_MINUS_DST_COLOR,
useDualSource ? GL_SRC1_ALPHA : (GLenum)GL_SRC_ALPHA,
useDualSource ? GL_ONE_MINUS_SRC1_ALPHA : (GLenum)GL_ONE_MINUS_SRC_ALPHA,
GL_DST_ALPHA,
GL_ONE_MINUS_DST_ALPHA};
const GLenum dst_factors[8] = {
GL_ZERO,
GL_ONE,
GL_SRC_COLOR,
GL_ONE_MINUS_SRC_COLOR,
useDualSource ? GL_SRC1_ALPHA : (GLenum)GL_SRC_ALPHA,
useDualSource ? GL_ONE_MINUS_SRC1_ALPHA : (GLenum)GL_ONE_MINUS_SRC_ALPHA,
GL_DST_ALPHA,
GL_ONE_MINUS_DST_ALPHA};

if (state.blendenable)
{
glEnable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
}

// Always call glBlendEquationSeparate and glBlendFuncSeparate, even when
// GL_BLEND is disabled, as a workaround for some bugs (possibly graphics
// driver issues?). See https://bugs.dolphin-emu.org/issues/10120 : "Sonic
// Adventure 2 Battle: graphics crash when loading first Dark level"
GLenum equation = state.subtract ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
GLenum equationAlpha = state.subtractAlpha ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
glBlendEquationSeparate(equation, equationAlpha);
glBlendFuncSeparate(src_factors[state.srcfactor], dst_factors[state.dstfactor],
src_factors[state.srcfactoralpha], dst_factors[state.dstfactoralpha]);
// Always call glBlendEquationSeparate and glBlendFuncSeparate, even when
// GL_BLEND is disabled, as a workaround for some bugs (possibly graphics
// driver issues?). See https://bugs.dolphin-emu.org/issues/10120 : "Sonic
// Adventure 2 Battle: graphics crash when loading first Dark level"
GLenum equation = state.subtract ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
GLenum equationAlpha = state.subtractAlpha ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
glBlendEquationSeparate(equation, equationAlpha);
glBlendFuncSeparate(src_factors[state.srcfactor], dst_factors[state.dstfactor],
src_factors[state.srcfactoralpha], dst_factors[state.dstfactoralpha]);
}

const GLenum logic_op_codes[16] = {
GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP,

0 comments on commit dc08b73

Please sign in to comment.