HostDisplay: Use border sampling for post processing shaders

This commit is contained in:
Connor McLaughlin 2022-10-13 22:53:09 +10:00
parent c528a96215
commit ccfe3925fc
12 changed files with 78 additions and 17 deletions

View file

@ -440,6 +440,11 @@ void SamplerBuilder::SetAddressMode(VkSamplerAddressMode u, VkSamplerAddressMode
m_ci.addressModeW = w;
}
void SamplerBuilder::SetBorderColor(VkBorderColor color)
{
m_ci.borderColor = color;
}
void SamplerBuilder::SetPointSampler(VkSamplerAddressMode address_mode /* = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER */)
{
Clear();

View file

@ -149,9 +149,10 @@ public:
void SetFilter(VkFilter mag_filter, VkFilter min_filter, VkSamplerMipmapMode mip_filter);
void SetAddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w);
void SetBorderColor(VkBorderColor color);
void SetPointSampler(VkSamplerAddressMode address_mode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
void SetLinearSampler(bool mipmaps, VkSamplerAddressMode address_mode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
void SetPointSampler(VkSamplerAddressMode address_mode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
void SetLinearSampler(bool mipmaps, VkSamplerAddressMode address_mode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
private:
VkSamplerCreateInfo m_ci;

View file

@ -521,7 +521,7 @@ bool GPU_HW_Vulkan::CreateSamplers()
VkDevice device = g_vulkan_context->GetDevice();
Vulkan::SamplerBuilder sbuilder;
sbuilder.SetPointSampler(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
sbuilder.SetPointSampler(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
sbuilder.SetAddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT,
VK_SAMPLER_ADDRESS_MODE_REPEAT);
m_point_sampler = sbuilder.Create(device);
@ -529,7 +529,7 @@ bool GPU_HW_Vulkan::CreateSamplers()
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_point_sampler, "Point Sampler");
sbuilder.SetLinearSampler(false, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
sbuilder.SetLinearSampler(false, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
sbuilder.SetAddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT,
VK_SAMPLER_ADDRESS_MODE_REPEAT);
m_linear_sampler = sbuilder.Create(device);
@ -537,7 +537,7 @@ bool GPU_HW_Vulkan::CreateSamplers()
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_linear_sampler, "Linear Sampler");
sbuilder.SetLinearSampler(true, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
sbuilder.SetLinearSampler(true, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
m_trilinear_sampler = sbuilder.Create(device);
if (m_trilinear_sampler == VK_NULL_HANDLE)
return false;

View file

@ -655,6 +655,17 @@ bool D3D11HostDisplay::CreateResources()
if (FAILED(hr))
return false;
sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
sampler_desc.BorderColor[0] = 0.0f;
sampler_desc.BorderColor[1] = 0.0f;
sampler_desc.BorderColor[2] = 0.0f;
sampler_desc.BorderColor[3] = 1.0f;
hr = m_device->CreateSamplerState(&sampler_desc, m_border_sampler.GetAddressOf());
if (FAILED(hr))
return false;
return true;
}
@ -665,6 +676,7 @@ void D3D11HostDisplay::DestroyResources()
m_post_processing_stages.clear();
m_display_uniform_buffer.Release();
m_border_sampler.Reset();
m_linear_sampler.Reset();
m_point_sampler.Reset();
m_display_alpha_pixel_shader.Reset();
@ -1082,7 +1094,7 @@ void D3D11HostDisplay::ApplyPostProcessingChain(ID3D11RenderTargetView* final_ta
m_context->VSSetShader(pps.vertex_shader.Get(), nullptr, 0);
m_context->PSSetShader(pps.pixel_shader.Get(), nullptr, 0);
m_context->PSSetShaderResources(0, 1, texture->GetD3DSRVArray());
m_context->PSSetSamplers(0, 1, m_point_sampler.GetAddressOf());
m_context->PSSetSamplers(0, 1, m_border_sampler.GetAddressOf());
const auto map =
m_display_uniform_buffer.Map(m_context.Get(), m_display_uniform_buffer.GetSize(), pps.uniforms_size);

View file

@ -132,6 +132,7 @@ protected:
ComPtr<ID3D11PixelShader> m_display_alpha_pixel_shader;
ComPtr<ID3D11SamplerState> m_point_sampler;
ComPtr<ID3D11SamplerState> m_linear_sampler;
ComPtr<ID3D11SamplerState> m_border_sampler;
D3D11::StreamBuffer m_display_uniform_buffer;
ComPtr<ID3D11Texture2D> m_readback_staging_texture;

View file

@ -565,6 +565,18 @@ bool D3D12HostDisplay::CreateResources()
g_d3d12_context->GetDevice()->CreateSampler(&desc, m_linear_sampler.cpu_handle);
if (!g_d3d12_context->GetSamplerHeapManager().Allocate(&m_border_sampler))
return false;
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
desc.BorderColor[0] = 0.0f;
desc.BorderColor[1] = 0.0f;
desc.BorderColor[2] = 0.0f;
desc.BorderColor[3] = 1.0f;
g_d3d12_context->GetDevice()->CreateSampler(&desc, m_border_sampler.cpu_handle);
return true;
}
@ -578,6 +590,7 @@ void D3D12HostDisplay::DestroyResources()
m_post_processing_root_signature.Reset();
m_readback_staging_texture.Destroy(false);
g_d3d12_context->GetSamplerHeapManager().Free(&m_border_sampler);
g_d3d12_context->GetSamplerHeapManager().Free(&m_linear_sampler);
g_d3d12_context->GetSamplerHeapManager().Free(&m_point_sampler);
m_software_cursor_pipeline.Reset();
@ -1074,7 +1087,7 @@ void D3D12HostDisplay::ApplyPostProcessingChain(ID3D12GraphicsCommandList* cmdli
cmdlist->SetPipelineState(pps.pipeline.Get());
cmdlist->SetGraphicsRootDescriptorTable(1, texture->GetSRVDescriptor());
cmdlist->SetGraphicsRootDescriptorTable(2, m_point_sampler);
cmdlist->SetGraphicsRootDescriptorTable(2, m_border_sampler);
cmdlist->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
cmdlist->DrawInstanced(3, 1, 0, 0);

View file

@ -124,6 +124,7 @@ protected:
ComPtr<ID3D12PipelineState> m_software_cursor_pipeline;
D3D12::DescriptorHandle m_point_sampler;
D3D12::DescriptorHandle m_linear_sampler;
D3D12::DescriptorHandle m_border_sampler;
D3D12::Texture m_display_pixels_texture;
D3D12::StagingTexture m_readback_staging_texture;

View file

@ -457,9 +457,9 @@ static bool ImGui_ImplVulkan_CreateFontSampler(VkDevice device)
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.minLod = -1000;
info.maxLod = 1000;
info.maxAnisotropy = 1.0f;

View file

@ -510,6 +510,20 @@ void main()
glGenSamplers(1, &m_display_linear_sampler);
glSamplerParameteri(m_display_linear_sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glSamplerParameteri(m_display_linear_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenSamplers(1, &m_display_border_sampler);
glSamplerParameteri(m_display_border_sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(m_display_border_sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// If we don't have border clamp.. too bad, just hope for the best.
if (!m_gl_context->IsGLES() || GLAD_GL_ES_VERSION_3_2 || GLAD_GL_NV_texture_border_clamp ||
GLAD_GL_EXT_texture_border_clamp || GLAD_GL_OES_texture_border_clamp)
{
static constexpr const float border_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
glSamplerParameteri(m_display_border_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glSamplerParameteri(m_display_border_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(m_display_border_sampler, GL_TEXTURE_BORDER_COLOR, border_color);
}
}
else
{
@ -594,6 +608,11 @@ void OpenGLHostDisplay::DestroyResources()
glDeleteVertexArrays(1, &m_display_vao);
m_display_vao = 0;
}
if (m_display_border_sampler != 0)
{
glDeleteSamplers(1, &m_display_border_sampler);
m_display_border_sampler = 0;
}
if (m_display_linear_sampler != 0)
{
glDeleteSamplers(1, &m_display_linear_sampler);
@ -657,9 +676,9 @@ bool OpenGLHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>
if (HasDisplayTexture() && !m_post_processing_chain.IsEmpty())
{
ApplyPostProcessingChain(texture.GetGLFramebufferID(), left, height - top - draw_height, draw_width, draw_height,
static_cast<GL::Texture*>(m_display_texture), m_display_texture_view_x,
m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
width, height);
static_cast<GL::Texture*>(m_display_texture), m_display_texture_view_x,
m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
width, height);
}
else
{
@ -952,7 +971,7 @@ void OpenGLHostDisplay::ApplyPostProcessingChain(GLuint final_target, s32 final_
pps.program.Bind();
static_cast<const GL::Texture*>(texture)->Bind();
glBindSampler(0, m_display_nearest_sampler);
glBindSampler(0, m_display_border_sampler);
const auto map_result = m_post_processing_ubo->Map(m_uniform_buffer_alignment, pps.uniforms_size);
m_post_processing_chain.GetShaderStage(i).FillUniformBuffer(

View file

@ -112,6 +112,7 @@ protected:
GLuint m_display_vao = 0;
GLuint m_display_nearest_sampler = 0;
GLuint m_display_linear_sampler = 0;
GLuint m_display_border_sampler = 0;
GLuint m_uniform_buffer_alignment = 1;
std::unique_ptr<GL::StreamBuffer> m_texture_stream_buffer;

View file

@ -507,16 +507,22 @@ void main()
vkDestroyShaderModule(device, cursor_fragment_shader, nullptr);
Vulkan::SamplerBuilder sbuilder;
sbuilder.SetPointSampler(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
sbuilder.SetPointSampler(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
m_point_sampler = sbuilder.Create(device, true);
if (m_point_sampler == VK_NULL_HANDLE)
return false;
sbuilder.SetLinearSampler(false, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
sbuilder.SetLinearSampler(false, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
m_linear_sampler = sbuilder.Create(device);
if (m_linear_sampler == VK_NULL_HANDLE)
return false;
sbuilder.SetPointSampler(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
sbuilder.SetBorderColor(VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK);
m_border_sampler = sbuilder.Create(device);
if (m_border_sampler == VK_NULL_HANDLE)
return false;
return true;
}
@ -536,6 +542,7 @@ void VulkanHostDisplay::DestroyResources()
Vulkan::Util::SafeDestroyPipeline(m_cursor_pipeline);
Vulkan::Util::SafeDestroyPipelineLayout(m_pipeline_layout);
Vulkan::Util::SafeDestroyDescriptorSetLayout(m_descriptor_set_layout);
Vulkan::Util::SafeDestroySampler(m_border_sampler);
Vulkan::Util::SafeDestroySampler(m_point_sampler);
Vulkan::Util::SafeDestroySampler(m_linear_sampler);
}
@ -1149,7 +1156,7 @@ void VulkanHostDisplay::ApplyPostProcessingChain(VkFramebuffer target_fb, s32 fi
}
Vulkan::DescriptorSetUpdateBuilder dsupdate;
dsupdate.AddCombinedImageSamplerDescriptorWrite(ds, 1, texture->GetView(), m_point_sampler, texture->GetLayout());
dsupdate.AddCombinedImageSamplerDescriptorWrite(ds, 1, texture->GetView(), m_border_sampler, texture->GetLayout());
if (use_push_constants)
{

View file

@ -121,6 +121,7 @@ protected:
VkPipeline m_display_pipeline = VK_NULL_HANDLE;
VkSampler m_point_sampler = VK_NULL_HANDLE;
VkSampler m_linear_sampler = VK_NULL_HANDLE;
VkSampler m_border_sampler = VK_NULL_HANDLE;
VmaAllocation m_readback_staging_allocation = VK_NULL_HANDLE;
VkBuffer m_readback_staging_buffer = VK_NULL_HANDLE;