GPU/HW: Add framebuffer fetch blending path
This commit is contained in:
@ -170,6 +170,7 @@ void D3D11Device::SetFeatures()
|
||||
}
|
||||
|
||||
m_features.dual_source_blend = true;
|
||||
m_features.framebuffer_fetch = false;
|
||||
m_features.per_sample_shading = (feature_level >= D3D_FEATURE_LEVEL_10_1);
|
||||
m_features.noperspective_interpolation = true;
|
||||
m_features.supports_texture_buffers = true;
|
||||
|
||||
@ -1173,6 +1173,7 @@ void D3D12Device::SetFeatures()
|
||||
}
|
||||
|
||||
m_features.dual_source_blend = true;
|
||||
m_features.framebuffer_fetch = false;
|
||||
m_features.noperspective_interpolation = true;
|
||||
m_features.per_sample_shading = true;
|
||||
m_features.supports_texture_buffers = true;
|
||||
|
||||
@ -410,7 +410,7 @@ bool GPUDevice::CreateResources()
|
||||
if (!(m_linear_sampler = CreateSampler(GPUSampler::GetLinearConfig())))
|
||||
return false;
|
||||
|
||||
ShaderGen shadergen(GetRenderAPI(), m_features.dual_source_blend);
|
||||
ShaderGen shadergen(GetRenderAPI(), m_features.dual_source_blend, m_features.framebuffer_fetch);
|
||||
|
||||
std::unique_ptr<GPUShader> imgui_vs = CreateShader(GPUShaderStage::Vertex, shadergen.GenerateImGuiVertexShader());
|
||||
std::unique_ptr<GPUShader> imgui_fs = CreateShader(GPUShaderStage::Fragment, shadergen.GenerateImGuiFragmentShader());
|
||||
|
||||
@ -446,6 +446,7 @@ public:
|
||||
struct Features
|
||||
{
|
||||
bool dual_source_blend : 1;
|
||||
bool framebuffer_fetch : 1;
|
||||
bool per_sample_shading : 1;
|
||||
bool noperspective_interpolation : 1;
|
||||
bool supports_texture_buffers : 1;
|
||||
|
||||
@ -212,6 +212,7 @@ void MetalDevice::SetFeatures()
|
||||
}
|
||||
|
||||
m_features.dual_source_blend = true;
|
||||
m_features.framebuffer_fetch = false; // TODO
|
||||
m_features.per_sample_shading = true;
|
||||
m_features.noperspective_interpolation = true;
|
||||
m_features.supports_texture_buffers = true;
|
||||
|
||||
@ -259,7 +259,7 @@ void OpenGLDevice::InsertDebugMessage(const char* msg)
|
||||
|
||||
if (msg[0] != '\0')
|
||||
{
|
||||
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_NOTIFICATION,
|
||||
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, GL_DEBUG_SEVERITY_NOTIFICATION,
|
||||
static_cast<GLsizei>(std::strlen(msg)), msg);
|
||||
}
|
||||
#endif
|
||||
@ -430,6 +430,8 @@ bool OpenGLDevice::CheckFeatures(bool* buggy_pbo)
|
||||
(max_dual_source_draw_buffers > 0) &&
|
||||
(GLAD_GL_VERSION_3_3 || GLAD_GL_ARB_blend_func_extended || GLAD_GL_EXT_blend_func_extended);
|
||||
|
||||
m_features.framebuffer_fetch = (GLAD_GL_EXT_shader_framebuffer_fetch || GLAD_GL_ARM_shader_framebuffer_fetch);
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Partial texture buffer uploads appear to be broken in macOS's OpenGL driver.
|
||||
m_features.supports_texture_buffers = false;
|
||||
|
||||
@ -18,7 +18,7 @@ namespace {
|
||||
class PostProcessingGLSLShaderGen : public ShaderGen
|
||||
{
|
||||
public:
|
||||
PostProcessingGLSLShaderGen(RenderAPI render_api, bool supports_dual_source_blend);
|
||||
PostProcessingGLSLShaderGen(RenderAPI render_api, bool supports_dual_source_blend, bool supports_framebuffer_fetch);
|
||||
~PostProcessingGLSLShaderGen();
|
||||
|
||||
std::string GeneratePostProcessingVertexShader(const PostProcessing::GLSLShader& shader);
|
||||
@ -117,7 +117,8 @@ bool PostProcessing::GLSLShader::CompilePipeline(GPUTexture::Format format, u32
|
||||
if (m_pipeline)
|
||||
m_pipeline.reset();
|
||||
|
||||
PostProcessingGLSLShaderGen shadergen(g_gpu_device->GetRenderAPI(), g_gpu_device->GetFeatures().dual_source_blend);
|
||||
PostProcessingGLSLShaderGen shadergen(g_gpu_device->GetRenderAPI(), g_gpu_device->GetFeatures().dual_source_blend,
|
||||
g_gpu_device->GetFeatures().framebuffer_fetch);
|
||||
|
||||
std::unique_ptr<GPUShader> vs =
|
||||
g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GeneratePostProcessingVertexShader(*this));
|
||||
@ -320,8 +321,9 @@ void PostProcessing::GLSLShader::LoadOptions()
|
||||
}
|
||||
}
|
||||
|
||||
PostProcessingGLSLShaderGen::PostProcessingGLSLShaderGen(RenderAPI render_api, bool supports_dual_source_blend)
|
||||
: ShaderGen(render_api, supports_dual_source_blend)
|
||||
PostProcessingGLSLShaderGen::PostProcessingGLSLShaderGen(RenderAPI render_api, bool supports_dual_source_blend,
|
||||
bool supports_framebuffer_fetch)
|
||||
: ShaderGen(render_api, supports_dual_source_blend, supports_framebuffer_fetch)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -14,10 +14,11 @@
|
||||
|
||||
Log_SetChannel(ShaderGen);
|
||||
|
||||
ShaderGen::ShaderGen(RenderAPI render_api, bool supports_dual_source_blend)
|
||||
ShaderGen::ShaderGen(RenderAPI render_api, bool supports_dual_source_blend, bool supports_framebuffer_fetch)
|
||||
: m_render_api(render_api), m_glsl(render_api != RenderAPI::D3D11 && render_api != RenderAPI::D3D12),
|
||||
m_spirv(render_api == RenderAPI::Vulkan || render_api == RenderAPI::Metal),
|
||||
m_supports_dual_source_blend(supports_dual_source_blend), m_use_glsl_interface_blocks(false)
|
||||
m_supports_dual_source_blend(supports_dual_source_blend), m_supports_framebuffer_fetch(supports_framebuffer_fetch),
|
||||
m_use_glsl_interface_blocks(false)
|
||||
{
|
||||
#if defined(ENABLE_OPENGL) || defined(ENABLE_VULKAN) || defined(__APPLE__)
|
||||
if (m_glsl)
|
||||
@ -62,6 +63,11 @@ void ShaderGen::DefineMacro(std::stringstream& ss, const char* name, bool enable
|
||||
ss << "#define " << name << " " << BoolToUInt32(enabled) << "\n";
|
||||
}
|
||||
|
||||
void ShaderGen::DefineMacro(std::stringstream& ss, const char* name, s32 value)
|
||||
{
|
||||
ss << "#define " << name << " " << value << "\n";
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPENGL
|
||||
void ShaderGen::SetGLSLVersionString()
|
||||
{
|
||||
@ -123,6 +129,8 @@ void ShaderGen::WriteHeader(std::stringstream& ss)
|
||||
ss << "#extension GL_EXT_blend_func_extended : require\n";
|
||||
if (GLAD_GL_ARB_blend_func_extended)
|
||||
ss << "#extension GL_ARB_blend_func_extended : require\n";
|
||||
if (GLAD_GL_EXT_shader_framebuffer_fetch)
|
||||
ss << "#extension GL_EXT_shader_framebuffer_fetch : require\n";
|
||||
|
||||
// Test for V3D driver - we have to fudge coordinates slightly.
|
||||
if (std::strstr(reinterpret_cast<const char*>(glGetString(GL_VENDOR)), "Broadcom") &&
|
||||
@ -151,6 +159,11 @@ void ShaderGen::WriteHeader(std::stringstream& ss)
|
||||
// Enable SSBOs if it's not required by the version.
|
||||
if (!GLAD_GL_VERSION_4_3 && !GLAD_GL_ES_VERSION_3_1 && GLAD_GL_ARB_shader_storage_buffer_object)
|
||||
ss << "#extension GL_ARB_shader_storage_buffer_object : require\n";
|
||||
|
||||
if (GLAD_GL_EXT_shader_framebuffer_fetch)
|
||||
ss << "#extension GL_EXT_shader_framebuffer_fetch : require\n";
|
||||
else if (GLAD_GL_ARM_shader_framebuffer_fetch)
|
||||
ss << "#extension GL_ARM_shader_framebuffer_fetch : require\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -486,7 +499,7 @@ void ShaderGen::DeclareFragmentEntryPoint(
|
||||
const std::initializer_list<std::pair<const char*, const char*>>& additional_inputs,
|
||||
bool declare_fragcoord /* = false */, u32 num_color_outputs /* = 1 */, bool depth_output /* = false */,
|
||||
bool msaa /* = false */, bool ssaa /* = false */, bool declare_sample_id /* = false */,
|
||||
bool noperspective_color /* = false */)
|
||||
bool noperspective_color /* = false */, bool framebuffer_fetch /* = false */)
|
||||
{
|
||||
if (m_glsl)
|
||||
{
|
||||
@ -540,24 +553,43 @@ void ShaderGen::DeclareFragmentEntryPoint(
|
||||
if (depth_output)
|
||||
ss << "#define o_depth gl_FragDepth\n";
|
||||
|
||||
const char* target_0_qualifier = "out";
|
||||
#ifdef ENABLE_OPENGL
|
||||
if ((m_render_api == RenderAPI::OpenGL || m_render_api == RenderAPI::OpenGLES) && m_supports_framebuffer_fetch &&
|
||||
framebuffer_fetch)
|
||||
{
|
||||
if (GLAD_GL_EXT_shader_framebuffer_fetch)
|
||||
{
|
||||
target_0_qualifier = "inout";
|
||||
ss << "#define LAST_FRAG_COLOR o_col0\n";
|
||||
}
|
||||
else if (GLAD_GL_ARM_shader_framebuffer_fetch)
|
||||
{
|
||||
ss << "#define LAST_FRAG_COLOR gl_LastFragColorARM\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_use_glsl_binding_layout)
|
||||
{
|
||||
if (m_supports_dual_source_blend)
|
||||
{
|
||||
for (u32 i = 0; i < num_color_outputs; i++)
|
||||
ss << "layout(location = 0, index = " << i << ") out float4 o_col" << i << ";\n";
|
||||
{
|
||||
ss << "layout(location = 0, index = " << i << ") " << ((i == 0) ? target_0_qualifier : "out")
|
||||
<< " float4 o_col" << i << ";\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(num_color_outputs <= 1);
|
||||
for (u32 i = 0; i < num_color_outputs; i++)
|
||||
ss << "layout(location = " << i << ") out float4 o_col" << i << ";\n";
|
||||
ss << "layout(location = 0) " << target_0_qualifier << " float4 o_col0;\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 i = 0; i < num_color_outputs; i++)
|
||||
ss << "out float4 o_col" << i << ";\n";
|
||||
ss << ((i == 0) ? target_0_qualifier : "out") << " float4 o_col" << i << ";\n";
|
||||
}
|
||||
|
||||
ss << "\n";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
@ -11,7 +11,7 @@
|
||||
class ShaderGen
|
||||
{
|
||||
public:
|
||||
ShaderGen(RenderAPI render_api, bool supports_dual_source_blend);
|
||||
ShaderGen(RenderAPI render_api, bool supports_dual_source_blend, bool supports_framebuffer_fetch);
|
||||
~ShaderGen();
|
||||
|
||||
static bool UseGLSLBindingLayout();
|
||||
@ -36,6 +36,7 @@ protected:
|
||||
#endif
|
||||
|
||||
void DefineMacro(std::stringstream& ss, const char* name, bool enabled);
|
||||
void DefineMacro(std::stringstream& ss, const char* name, s32 value);
|
||||
void WriteHeader(std::stringstream& ss);
|
||||
void WriteUniformBufferDeclaration(std::stringstream& ss, bool push_constant_on_vulkan);
|
||||
void DeclareUniformBuffer(std::stringstream& ss, const std::initializer_list<const char*>& members,
|
||||
@ -51,12 +52,13 @@ protected:
|
||||
const std::initializer_list<std::pair<const char*, const char*>>& additional_inputs,
|
||||
bool declare_fragcoord = false, u32 num_color_outputs = 1, bool depth_output = false,
|
||||
bool msaa = false, bool ssaa = false, bool declare_sample_id = false,
|
||||
bool noperspective_color = false);
|
||||
bool noperspective_color = false, bool framebuffer_fetch = false);
|
||||
|
||||
RenderAPI m_render_api;
|
||||
bool m_glsl;
|
||||
bool m_spirv;
|
||||
bool m_supports_dual_source_blend;
|
||||
bool m_supports_framebuffer_fetch;
|
||||
bool m_use_glsl_interface_blocks;
|
||||
bool m_use_glsl_binding_layout;
|
||||
bool m_has_uniform_buffer = false;
|
||||
|
||||
@ -2194,6 +2194,7 @@ bool VulkanDevice::CheckFeatures()
|
||||
m_max_multisamples = 1;
|
||||
|
||||
m_features.dual_source_blend = m_device_features.dualSrcBlend; // TODO: Option to disable
|
||||
m_features.framebuffer_fetch = false; // TODO: Option to disable
|
||||
|
||||
if (!m_features.dual_source_blend)
|
||||
Log_WarningPrintf("Vulkan driver is missing dual-source blending. This will have an impact on performance.");
|
||||
|
||||
Reference in New Issue
Block a user