mirror of https://github.com/PCSX2/pcsx2.git
GS/Vulkan: Implement shadeboost
This commit is contained in:
parent
5e336138d0
commit
486764be03
|
@ -0,0 +1,71 @@
|
|||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Contrast, saturation, brightness
|
||||
** Code of this function is from TGM's shader pack
|
||||
** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057
|
||||
** TGM's author comment about the license (included in the previous link)
|
||||
** "do with it, what you want! its total free!
|
||||
** (but would be nice, if you say that you used my shaders :wink: ) but not necessary"
|
||||
*/
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(push_constant) uniform cb0
|
||||
{
|
||||
vec4 params;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
|
||||
// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150%
|
||||
vec4 ContrastSaturationBrightness(vec4 color)
|
||||
{
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
const float AvgLumG = 0.5;
|
||||
const float AvgLumB = 0.5;
|
||||
|
||||
const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
|
||||
vec3 brtColor = color.rgb * brt;
|
||||
float dot_intensity = dot(brtColor, LumCoeff);
|
||||
vec3 intensity = vec3(dot_intensity, dot_intensity, dot_intensity);
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
|
||||
color.rgb = conColor;
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 c = texture(samp0, v_tex);
|
||||
o_col0 = ContrastSaturationBrightness(c);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -120,7 +120,8 @@ bool GSDeviceVK::Create(HostDisplay* display)
|
|||
if (!CreateBuffers())
|
||||
return false;
|
||||
|
||||
if (!CompileConvertPipelines() || !CompileInterlacePipelines() || !CompileMergePipelines())
|
||||
if (!CompileConvertPipelines() || !CompileInterlacePipelines() ||
|
||||
!CompileMergePipelines() || !CompileShadeBoostPipeline())
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to compile utility pipelines");
|
||||
return false;
|
||||
|
@ -147,9 +148,15 @@ void GSDeviceVK::Destroy()
|
|||
GSDevice::Destroy();
|
||||
}
|
||||
|
||||
void GSDeviceVK::ResetAPIState() { EndRenderPass(); }
|
||||
void GSDeviceVK::ResetAPIState()
|
||||
{
|
||||
EndRenderPass();
|
||||
}
|
||||
|
||||
void GSDeviceVK::RestoreAPIState() { InvalidateCachedState(); }
|
||||
void GSDeviceVK::RestoreAPIState()
|
||||
{
|
||||
InvalidateCachedState();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OGL_DEBUG
|
||||
static std::array<float, 3> Palette(float phase, const std::array<float, 3>& a, const std::array<float, 3>& b,
|
||||
|
@ -860,6 +867,22 @@ void GSDeviceVK::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool
|
|||
static_cast<GSTextureVK*>(dTex)->TransitionToLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
void GSDeviceVK::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4])
|
||||
{
|
||||
const GSVector4 sRect(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
const GSVector4i dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
|
||||
EndRenderPass();
|
||||
OMSetRenderTargets(dTex, nullptr, dRect, false);
|
||||
SetUtilityTexture(sTex, m_point_sampler);
|
||||
BeginRenderPass(m_utility_color_render_pass_discard, dRect);
|
||||
SetPipeline(m_shadeboost_pipeline);
|
||||
SetUtilityPushConstants(params, sizeof(float) * 4);
|
||||
DrawStretchRect(sRect, GSVector4(dRect), dTex->GetSize());
|
||||
EndRenderPass();
|
||||
|
||||
static_cast<GSTextureVK*>(dTex)->TransitionToLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
void GSDeviceVK::IASetVertexBuffer(const void* vertex, size_t stride, size_t count)
|
||||
{
|
||||
const u32 size = static_cast<u32>(stride) * static_cast<u32>(count);
|
||||
|
@ -1603,6 +1626,53 @@ bool GSDeviceVK::CompileMergePipelines()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GSDeviceVK::CompileShadeBoostPipeline()
|
||||
{
|
||||
std::optional<std::string> shader = Host::ReadResourceFileToString("shaders/vulkan/shadeboost.glsl");
|
||||
if (!shader)
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to read shaders/vulkan/shadeboost.glsl.");
|
||||
return false;
|
||||
}
|
||||
|
||||
VkRenderPass rp = g_vulkan_context->GetRenderPass(
|
||||
LookupNativeFormat(GSTexture::Format::Color), VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
|
||||
if (!rp)
|
||||
return false;
|
||||
|
||||
VkShaderModule vs = GetUtilityVertexShader(*shader);
|
||||
VkShaderModule ps = GetUtilityFragmentShader(*shader);
|
||||
ScopedGuard shader_guard([&vs, &ps]() {
|
||||
Vulkan::Util::SafeDestroyShaderModule(vs);
|
||||
Vulkan::Util::SafeDestroyShaderModule(ps);
|
||||
});
|
||||
if (vs == VK_NULL_HANDLE || ps == VK_NULL_HANDLE)
|
||||
return false;
|
||||
|
||||
Vulkan::GraphicsPipelineBuilder gpb;
|
||||
AddUtilityVertexAttributes(gpb);
|
||||
gpb.SetPipelineLayout(m_utility_pipeline_layout);
|
||||
gpb.SetDynamicViewportAndScissorState();
|
||||
gpb.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
|
||||
gpb.SetNoCullRasterizationState();
|
||||
gpb.SetNoDepthTestState();
|
||||
gpb.SetNoBlendingState();
|
||||
gpb.SetRenderPass(rp, 0);
|
||||
gpb.SetVertexShader(vs);
|
||||
gpb.SetFragmentShader(ps);
|
||||
|
||||
// we enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
m_shadeboost_pipeline = gpb.Create(g_vulkan_context->GetDevice(), g_vulkan_shader_cache->GetPipelineCache(true), false);
|
||||
if (!m_shadeboost_pipeline)
|
||||
return false;
|
||||
|
||||
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_shadeboost_pipeline, "Shadeboost pipeline");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSDeviceVK::CheckStagingBufferSize(u32 required_size)
|
||||
{
|
||||
if (m_readback_staging_buffer_size >= required_size)
|
||||
|
@ -1685,6 +1755,8 @@ void GSDeviceVK::DestroyResources()
|
|||
Vulkan::Util::SafeDestroyPipeline(m_date_image_setup_pipelines[ds][datm]);
|
||||
}
|
||||
}
|
||||
Vulkan::Util::SafeDestroyPipeline(m_shadeboost_pipeline);
|
||||
|
||||
for (auto& it : m_samplers)
|
||||
Vulkan::Util::SafeDestroySampler(it.second);
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ private:
|
|||
VkPipeline m_hdr_finish_pipelines[2][2] = {}; // [depth][feedback_loop]
|
||||
VkRenderPass m_date_image_setup_render_passes[2][2] = {}; // [depth][clear]
|
||||
VkPipeline m_date_image_setup_pipelines[2][2] = {}; // [depth][datm]
|
||||
VkPipeline m_shadeboost_pipeline = {};
|
||||
|
||||
std::unordered_map<u32, VkShaderModule> m_tfx_vertex_shaders;
|
||||
std::unordered_map<u32, VkShaderModule> m_tfx_geometry_shaders;
|
||||
|
@ -153,6 +154,7 @@ private:
|
|||
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE,
|
||||
const GSRegEXTBUF& EXTBUF, const GSVector4& c) final;
|
||||
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final;
|
||||
void DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4]) final;
|
||||
|
||||
VkSampler GetSampler(GSHWDrawConfig::SamplerSelector ss);
|
||||
void ClearSamplerCache() final;
|
||||
|
@ -175,6 +177,7 @@ private:
|
|||
bool CompileConvertPipelines();
|
||||
bool CompileInterlacePipelines();
|
||||
bool CompileMergePipelines();
|
||||
bool CompileShadeBoostPipeline();
|
||||
|
||||
bool CheckStagingBufferSize(u32 required_size);
|
||||
void DestroyStagingBuffer();
|
||||
|
@ -218,9 +221,6 @@ public:
|
|||
bool DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map) override;
|
||||
void DownloadTextureComplete() override;
|
||||
|
||||
GSTexture* DrawForReadback(GSTexture* src, const GSVector4& sRect, int w, int h, int format = 0, int ps_shader = 0);
|
||||
bool ReadbackTexture(GSTexture* src, const GSVector4i& rect, u32 level, GSTexture::GSMap* dst);
|
||||
|
||||
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) override;
|
||||
void DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, const GSVector4i& dst_rc);
|
||||
|
||||
|
|
|
@ -456,7 +456,7 @@ PostTab::PostTab(wxWindow* parent)
|
|||
m_ui.addCheckBox(shader_box.inner, "Texture Filtering of Display", "linear_present", IDC_LINEAR_PRESENT);
|
||||
m_ui.addCheckBox(shader_box.inner, "FXAA Shader (PgUp)", "fxaa", IDC_FXAA, not_vk_prereq);
|
||||
|
||||
CheckboxPrereq shade_boost_check(m_ui.addCheckBox(shader_box.inner, "Enable Shade Boost", "ShadeBoost", IDC_SHADEBOOST, not_vk_prereq));
|
||||
CheckboxPrereq shade_boost_check(m_ui.addCheckBox(shader_box.inner, "Enable Shade Boost", "ShadeBoost", IDC_SHADEBOOST));
|
||||
|
||||
PaddedBoxSizer<wxStaticBoxSizer> shade_boost_box(wxVERTICAL, this, "Shade Boost");
|
||||
auto* shader_boost_grid = new wxFlexGridSizer(2, space, space);
|
||||
|
|
Loading…
Reference in New Issue