Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vulkan: Make scaling shaders compatible + fixes #1392

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Cafe/GraphicPack/GraphicPack2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,7 @@ bool GraphicPack2::Activate()
auto option_upscale = rules.FindOption("upscaleMagFilter");
if(option_upscale && boost::iequals(*option_upscale, "NearestNeighbor"))
m_output_settings.upscale_filter = LatteTextureView::MagFilter::kNearestNeighbor;
auto option_downscale = rules.FindOption("NearestNeighbor");
auto option_downscale = rules.FindOption("downscaleMagFilter");
goeiecool9999 marked this conversation as resolved.
Show resolved Hide resolved
if (option_downscale && boost::iequals(*option_downscale, "NearestNeighbor"))
m_output_settings.downscale_filter = LatteTextureView::MagFilter::kNearestNeighbor;
}
Expand Down
9 changes: 1 addition & 8 deletions src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -933,13 +933,6 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
if (shader == nullptr)
{
sint32 scaling_filter = downscaling ? GetConfig().downscale_filter : GetConfig().upscale_filter;

if (g_renderer->GetType() == RendererAPI::Vulkan)
{
// force linear or nearest neighbor filter
if(scaling_filter != kLinearFilter && scaling_filter != kNearestNeighborFilter)
scaling_filter = kLinearFilter;
}

if (scaling_filter == kLinearFilter)
{
Expand All @@ -957,7 +950,7 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
else
shader = RendererOutputShader::s_bicubic_shader;

filter = LatteTextureView::MagFilter::kNearestNeighbor;
filter = LatteTextureView::MagFilter::kLinear;
}
else if (scaling_filter == kBicubicHermiteFilter)
{
Expand Down
11 changes: 7 additions & 4 deletions src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -570,20 +570,23 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
g_renderer->ClearColorbuffer(padView);
}

sint32 effectiveWidth, effectiveHeight;
texView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);

shader_unbind(RendererShader::ShaderType::kGeometry);
shader_bind(shader->GetVertexShader());
shader_bind(shader->GetFragmentShader());
shader->SetUniformParameters(*texView, { effectiveWidth, effectiveHeight }, { imageWidth, imageHeight });
shader->SetUniformParameters(*texView, {imageWidth, imageHeight});

// set viewport
glViewportIndexedf(0, imageX, imageY, imageWidth, imageHeight);

LatteTextureViewGL* texViewGL = (LatteTextureViewGL*)texView;
texture_bindAndActivate(texView, 0);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texViewGL->samplerState.clampS = texViewGL->samplerState.clampT = 0xFF;

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, useLinearTexFilter ? GL_LINEAR : GL_NEAREST);
texViewGL->samplerState.filterMin = 0xFFFFFFFF;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, useLinearTexFilter ? GL_LINEAR : GL_NEAREST);
texViewGL->samplerState.filterMag = 0xFFFFFFFF;

Expand Down
213 changes: 82 additions & 131 deletions src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,7 @@
#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h"

const std::string RendererOutputShader::s_copy_shader_source =
R"(#version 420

#ifdef VULKAN
layout(location = 0) in vec2 passUV;
layout(binding = 0) uniform sampler2D textureSrc;
layout(location = 0) out vec4 colorOut0;
#else
in vec2 passUV;
layout(binding=0) uniform sampler2D textureSrc;
layout(location = 0) out vec4 colorOut0;
#endif

R"(
void main()
{
colorOut0 = vec4(texture(textureSrc, passUV).rgb,1.0);
Expand All @@ -22,20 +11,6 @@ void main()

const std::string RendererOutputShader::s_bicubic_shader_source =
R"(
#version 420

#ifdef VULKAN
layout(location = 0) in vec2 passUV;
layout(binding = 0) uniform sampler2D textureSrc;
layout(binding = 1) uniform vec2 textureSrcResolution;
layout(location = 0) out vec4 colorOut0;
#else
in vec2 passUV;
layout(binding=0) uniform sampler2D textureSrc;
uniform vec2 textureSrcResolution;
layout(location = 0) out vec4 colorOut0;
#endif

vec4 cubic(float x)
{
float x2 = x * x;
Expand All @@ -48,24 +23,23 @@ vec4 cubic(float x)
return w / 6.0;
}

vec4 bcFilter(vec2 texcoord, vec2 texscale)
vec4 bcFilter(vec2 uv, vec4 texelSize)
{
float fx = fract(texcoord.x);
float fy = fract(texcoord.y);
texcoord.x -= fx;
texcoord.y -= fy;
vec2 pixel = uv*texelSize.zw - 0.5;
vec2 pixelFrac = fract(pixel);
vec2 pixelInt = pixel - pixelFrac;

vec4 xcubic = cubic(fx);
vec4 ycubic = cubic(fy);
vec4 xcubic = cubic(pixelFrac.x);
vec4 ycubic = cubic(pixelFrac.y);

vec4 c = vec4(texcoord.x - 0.5, texcoord.x + 1.5, texcoord.y - 0.5, texcoord.y + 1.5);
vec4 c = vec4(pixelInt.x - 0.5, pixelInt.x + 1.5, pixelInt.y - 0.5, pixelInt.y + 1.5);
vec4 s = vec4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x + ycubic.y, ycubic.z + ycubic.w);
vec4 offset = c + vec4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) / s;

vec4 sample0 = texture(textureSrc, vec2(offset.x, offset.z) * texscale);
vec4 sample1 = texture(textureSrc, vec2(offset.y, offset.z) * texscale);
vec4 sample2 = texture(textureSrc, vec2(offset.x, offset.w) * texscale);
vec4 sample3 = texture(textureSrc, vec2(offset.y, offset.w) * texscale);
vec4 sample0 = texture(textureSrc, vec2(offset.x, offset.z) * texelSize.xy);
vec4 sample1 = texture(textureSrc, vec2(offset.y, offset.z) * texelSize.xy);
vec4 sample2 = texture(textureSrc, vec2(offset.x, offset.w) * texelSize.xy);
vec4 sample3 = texture(textureSrc, vec2(offset.y, offset.w) * texelSize.xy);

float sx = s.x / (s.x + s.y);
float sy = s.z / (s.z + s.w);
Expand All @@ -76,20 +50,13 @@ vec4 bcFilter(vec2 texcoord, vec2 texscale)
}

void main(){
colorOut0 = vec4(bcFilter(passUV*textureSrcResolution, vec2(1.0,1.0)/textureSrcResolution).rgb,1.0);
vec4 texelSize = vec4( 1.0 / textureSrcResolution.xy, textureSrcResolution.xy);
colorOut0 = vec4(bcFilter(passUV, texelSize).rgb,1.0);
}
)";

const std::string RendererOutputShader::s_hermite_shader_source =
R"(#version 420

in vec4 gl_FragCoord;
in vec2 passUV;
layout(binding=0) uniform sampler2D textureSrc;
uniform vec2 textureSrcResolution;
uniform vec2 outputResolution;
layout(location = 0) out vec4 colorOut0;

R"(
// https://www.shadertoy.com/view/MllSzX

vec3 CubicHermite (vec3 A, vec3 B, vec3 C, vec3 D, float t)
Expand All @@ -111,7 +78,7 @@ vec3 BicubicHermiteTexture(vec2 uv, vec4 texelSize)
vec2 frac = fract(pixel);
pixel = floor(pixel) / texelSize.zw - vec2(texelSize.xy/2.0);

vec4 doubleSize = texelSize*texelSize;
vec4 doubleSize = texelSize*2.0;

vec3 C00 = texture(textureSrc, pixel + vec2(-texelSize.x ,-texelSize.y)).rgb;
vec3 C10 = texture(textureSrc, pixel + vec2( 0.0 ,-texelSize.y)).rgb;
Expand Down Expand Up @@ -142,15 +109,17 @@ vec3 BicubicHermiteTexture(vec2 uv, vec4 texelSize)
}

void main(){
vec4 texelSize = vec4( 1.0 / outputResolution.xy, outputResolution.xy);
vec4 texelSize = vec4( 1.0 / textureSrcResolution.xy, textureSrcResolution.xy);
colorOut0 = vec4(BicubicHermiteTexture(passUV, texelSize), 1.0);
}
)";

RendererOutputShader::RendererOutputShader(const std::string& vertex_source, const std::string& fragment_source)
{
auto finalFragmentSrc = PrependFragmentPreamble(fragment_source);

m_vertex_shader = g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, vertex_source, false, false);
m_fragment_shader = g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, fragment_source, false, false);
m_fragment_shader = g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false);

m_vertex_shader->PreponeCompilation(true);
m_fragment_shader->PreponeCompilation(true);
Expand All @@ -163,74 +132,45 @@ RendererOutputShader::RendererOutputShader(const std::string& vertex_source, con

if (g_renderer->GetType() == RendererAPI::OpenGL)
{
m_attributes[0].m_loc_texture_src_resolution = m_vertex_shader->GetUniformLocation("textureSrcResolution");
m_attributes[0].m_loc_input_resolution = m_vertex_shader->GetUniformLocation("inputResolution");
m_attributes[0].m_loc_output_resolution = m_vertex_shader->GetUniformLocation("outputResolution");
m_uniformLocations[0].m_loc_textureSrcResolution = m_vertex_shader->GetUniformLocation("textureSrcResolution");
m_uniformLocations[0].m_loc_nativeResolution = m_vertex_shader->GetUniformLocation("nativeResolution");
m_uniformLocations[0].m_loc_outputResolution = m_vertex_shader->GetUniformLocation("outputResolution");

m_attributes[1].m_loc_texture_src_resolution = m_fragment_shader->GetUniformLocation("textureSrcResolution");
m_attributes[1].m_loc_input_resolution = m_fragment_shader->GetUniformLocation("inputResolution");
m_attributes[1].m_loc_output_resolution = m_fragment_shader->GetUniformLocation("outputResolution");
}
else
{
cemuLog_logDebug(LogType::Force, "RendererOutputShader() - todo for Vulkan");
m_attributes[0].m_loc_texture_src_resolution = -1;
m_attributes[0].m_loc_input_resolution = -1;
m_attributes[0].m_loc_output_resolution = -1;

m_attributes[1].m_loc_texture_src_resolution = -1;
m_attributes[1].m_loc_input_resolution = -1;
m_attributes[1].m_loc_output_resolution = -1;
m_uniformLocations[1].m_loc_textureSrcResolution = m_fragment_shader->GetUniformLocation("textureSrcResolution");
m_uniformLocations[1].m_loc_nativeResolution = m_fragment_shader->GetUniformLocation("nativeResolution");
m_uniformLocations[1].m_loc_outputResolution = m_fragment_shader->GetUniformLocation("outputResolution");
}

}

void RendererOutputShader::SetUniformParameters(const LatteTextureView& texture_view, const Vector2i& input_res, const Vector2i& output_res) const
void RendererOutputShader::SetUniformParameters(const LatteTextureView& texture_view, const Vector2i& output_res) const
{
float res[2];
// vertex shader
if (m_attributes[0].m_loc_texture_src_resolution != -1)
{
res[0] = (float)texture_view.baseTexture->width;
res[1] = (float)texture_view.baseTexture->height;
m_vertex_shader->SetUniform2fv(m_attributes[0].m_loc_texture_src_resolution, res, 1);
}

if (m_attributes[0].m_loc_input_resolution != -1)
{
res[0] = (float)input_res.x;
res[1] = (float)input_res.y;
m_vertex_shader->SetUniform2fv(m_attributes[0].m_loc_input_resolution, res, 1);
}

if (m_attributes[0].m_loc_output_resolution != -1)
{
res[0] = (float)output_res.x;
res[1] = (float)output_res.y;
m_vertex_shader->SetUniform2fv(m_attributes[0].m_loc_output_resolution, res, 1);
}

// fragment shader
if (m_attributes[1].m_loc_texture_src_resolution != -1)
{
res[0] = (float)texture_view.baseTexture->width;
res[1] = (float)texture_view.baseTexture->height;
m_fragment_shader->SetUniform2fv(m_attributes[1].m_loc_texture_src_resolution, res, 1);
}

if (m_attributes[1].m_loc_input_resolution != -1)
{
res[0] = (float)input_res.x;
res[1] = (float)input_res.y;
m_fragment_shader->SetUniform2fv(m_attributes[1].m_loc_input_resolution, res, 1);
}

if (m_attributes[1].m_loc_output_resolution != -1)
{
res[0] = (float)output_res.x;
res[1] = (float)output_res.y;
m_fragment_shader->SetUniform2fv(m_attributes[1].m_loc_output_resolution, res, 1);
}
sint32 effectiveWidth, effectiveHeight;
texture_view.baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
auto setUniforms = [&](RendererShader* shader, const UniformLocations& locations){
float res[2];
if (locations.m_loc_textureSrcResolution != -1)
{
res[0] = (float)effectiveWidth;
res[1] = (float)effectiveHeight;
shader->SetUniform2fv(locations.m_loc_textureSrcResolution, res, 1);
}

if (locations.m_loc_nativeResolution != -1)
{
res[0] = (float)texture_view.baseTexture->width;
res[1] = (float)texture_view.baseTexture->height;
shader->SetUniform2fv(locations.m_loc_nativeResolution, res, 1);
}

if (locations.m_loc_outputResolution != -1)
{
res[0] = (float)output_res.x;
res[1] = (float)output_res.y;
shader->SetUniform2fv(locations.m_loc_outputResolution, res, 1);
}
};
setUniforms(m_vertex_shader, m_uniformLocations[0]);
setUniforms(m_fragment_shader, m_uniformLocations[1]);
}

RendererOutputShader* RendererOutputShader::s_copy_shader;
Expand Down Expand Up @@ -341,6 +281,27 @@ void main(){
)";
return vertex_source.str();
}

std::string RendererOutputShader::PrependFragmentPreamble(const std::string& shaderSrc)
{
return R"(#version 430
#ifdef VULKAN
layout(push_constant) uniform pc {
vec2 textureSrcResolution;
vec2 nativeResolution;
vec2 outputResolution;
};
#else
uniform vec2 textureSrcResolution;
uniform vec2 nativeResolution;
uniform vec2 outputResolution;
#endif

layout(location = 0) in vec2 passUV;
layout(binding = 0) uniform sampler2D textureSrc;
layout(location = 0) out vec4 colorOut0;
)" + shaderSrc;
}
void RendererOutputShader::InitializeStatic()
{
std::string vertex_source, vertex_source_ud;
Expand All @@ -349,28 +310,18 @@ void RendererOutputShader::InitializeStatic()
{
vertex_source = GetOpenGlVertexSource(false);
vertex_source_ud = GetOpenGlVertexSource(true);

s_copy_shader = new RendererOutputShader(vertex_source, s_copy_shader_source);
s_copy_shader_ud = new RendererOutputShader(vertex_source_ud, s_copy_shader_source);

s_bicubic_shader = new RendererOutputShader(vertex_source, s_bicubic_shader_source);
s_bicubic_shader_ud = new RendererOutputShader(vertex_source_ud, s_bicubic_shader_source);

s_hermit_shader = new RendererOutputShader(vertex_source, s_hermite_shader_source);
s_hermit_shader_ud = new RendererOutputShader(vertex_source_ud, s_hermite_shader_source);
}
else
{
vertex_source = GetVulkanVertexSource(false);
vertex_source_ud = GetVulkanVertexSource(true);
}
s_copy_shader = new RendererOutputShader(vertex_source, s_copy_shader_source);
s_copy_shader_ud = new RendererOutputShader(vertex_source_ud, s_copy_shader_source);

s_copy_shader = new RendererOutputShader(vertex_source, s_copy_shader_source);
s_copy_shader_ud = new RendererOutputShader(vertex_source_ud, s_copy_shader_source);

/* s_bicubic_shader = new RendererOutputShader(vertex_source, s_bicubic_shader_source); TODO
s_bicubic_shader_ud = new RendererOutputShader(vertex_source_ud, s_bicubic_shader_source);
s_bicubic_shader = new RendererOutputShader(vertex_source, s_bicubic_shader_source);
s_bicubic_shader_ud = new RendererOutputShader(vertex_source_ud, s_bicubic_shader_source);

s_hermit_shader = new RendererOutputShader(vertex_source, s_hermite_shader_source);
s_hermit_shader_ud = new RendererOutputShader(vertex_source_ud, s_hermite_shader_source);*/
}
s_hermit_shader = new RendererOutputShader(vertex_source, s_hermite_shader_source);
s_hermit_shader_ud = new RendererOutputShader(vertex_source_ud, s_hermite_shader_source);
}
14 changes: 8 additions & 6 deletions src/Cafe/HW/Latte/Renderer/RendererOuputShader.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class RendererOutputShader
RendererOutputShader(const std::string& vertex_source, const std::string& fragment_source);
virtual ~RendererOutputShader() = default;

void SetUniformParameters(const LatteTextureView& texture_view, const Vector2i& input_res, const Vector2i& output_res) const;
void SetUniformParameters(const LatteTextureView& texture_view, const Vector2i& output_res) const;

RendererShader* GetVertexShader() const
{
Expand All @@ -43,16 +43,18 @@ class RendererOutputShader
static std::string GetVulkanVertexSource(bool render_upside_down);
static std::string GetOpenGlVertexSource(bool render_upside_down);

static std::string PrependFragmentPreamble(const std::string& shaderSrc);

protected:
RendererShader* m_vertex_shader;
RendererShader* m_fragment_shader;

struct
struct UniformLocations
{
sint32 m_loc_texture_src_resolution = -1;
sint32 m_loc_input_resolution = -1;
sint32 m_loc_output_resolution = -1;
} m_attributes[2]{};
sint32 m_loc_textureSrcResolution = -1;
sint32 m_loc_nativeResolution = -1;
sint32 m_loc_outputResolution = -1;
} m_uniformLocations[2]{};

private:
static const std::string s_copy_shader_source;
Expand Down
Loading
Loading