Skip to content

Commit

Permalink
HostDisplay: Use border sampling for post processing shaders
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Oct 13, 2022
1 parent c528a96 commit ccfe392
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 17 deletions.
5 changes: 5 additions & 0 deletions src/common/vulkan/builders.cpp
Expand Up @@ -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();
Expand Down
5 changes: 3 additions & 2 deletions src/common/vulkan/builders.h
Expand Up @@ -149,9 +149,10 @@ class SamplerBuilder

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;
Expand Down
6 changes: 3 additions & 3 deletions src/core/gpu_hw_vulkan.cpp
Expand Up @@ -521,23 +521,23 @@ 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);
if (m_point_sampler == VK_NULL_HANDLE)
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);
if (m_linear_sampler == VK_NULL_HANDLE)
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;
Expand Down
14 changes: 13 additions & 1 deletion src/frontend-common/d3d11_host_display.cpp
Expand Up @@ -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;
}

Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/frontend-common/d3d11_host_display.h
Expand Up @@ -132,6 +132,7 @@ class D3D11HostDisplay final : public HostDisplay
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;
Expand Down
15 changes: 14 additions & 1 deletion src/frontend-common/d3d12_host_display.cpp
Expand Up @@ -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;
}

Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/frontend-common/d3d12_host_display.h
Expand Up @@ -124,6 +124,7 @@ class D3D12HostDisplay final : public HostDisplay
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;
Expand Down
6 changes: 3 additions & 3 deletions src/frontend-common/imgui_impl_vulkan.cpp
Expand Up @@ -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;
Expand Down
27 changes: 23 additions & 4 deletions src/frontend-common/opengl_host_display.cpp
Expand Up @@ -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
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions src/frontend-common/opengl_host_display.h
Expand Up @@ -112,6 +112,7 @@ class OpenGLHostDisplay final : public HostDisplay
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;
Expand Down
13 changes: 10 additions & 3 deletions src/frontend-common/vulkan_host_display.cpp
Expand Up @@ -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;
}

Expand All @@ -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);
}
Expand Down Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions src/frontend-common/vulkan_host_display.h
Expand Up @@ -121,6 +121,7 @@ class VulkanHostDisplay final : public HostDisplay
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;
Expand Down

0 comments on commit ccfe392

Please sign in to comment.