diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 7f15da86f..38d8d5488 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -227,7 +227,8 @@ bool Instance::CreateDevice() { auto feature_chain = physical_device.getFeatures2(); + vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR, + vk::PhysicalDeviceCustomBorderColorFeaturesEXT>(); // Not having geometry shaders will cause issues with accelerated rendering. const vk::PhysicalDeviceFeatures available = feature_chain.get().features; @@ -243,7 +244,7 @@ bool Instance::CreateDevice() { } // Helper lambda for adding extensions - std::array enabled_extensions; + std::array enabled_extensions; u32 enabled_extension_count = 0; auto AddExtension = [&](std::string_view name) -> bool { @@ -267,6 +268,7 @@ bool Instance::CreateDevice() { timeline_semaphores = AddExtension(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME); extended_dynamic_state = AddExtension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); push_descriptors = AddExtension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); + custom_border_color = AddExtension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); // Search queue families for graphics and present queues auto family_properties = physical_device.getQueueFamilyProperties(); @@ -336,7 +338,8 @@ bool Instance::CreateDevice() { vk::PhysicalDeviceDepthClipControlFeaturesEXT{.depthClipControl = true}, vk::PhysicalDeviceIndexTypeUint8FeaturesEXT{.indexTypeUint8 = true}, feature_chain.get(), - feature_chain.get()}; + feature_chain.get(), + feature_chain.get()}; // Create logical device try { diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 88f88f838..c5f970a32 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -100,6 +100,11 @@ public: return push_descriptors; } + /// Returns true when VK_EXT_custom_border_color is supported + bool IsCustomBorderColorSupported() const { + return custom_border_color; + } + /// Returns the vendor ID of the physical device u32 GetVendorID() const { return device_properties.vendorID; @@ -150,6 +155,7 @@ private: bool timeline_semaphores = false; bool extended_dynamic_state = false; bool push_descriptors = false; + bool custom_border_color = false; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index bbc7b7511..9f11525a2 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1588,8 +1588,21 @@ bool RasterizerVulkan::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con } vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) { + const bool use_border_color = instance.IsCustomBorderColorSupported() && + (info.wrap_s == SamplerInfo::TextureConfig::ClampToBorder || + info.wrap_t == SamplerInfo::TextureConfig::ClampToBorder); auto properties = instance.GetPhysicalDevice().getProperties(); + + const auto color = PicaToVK::ColorRGBA8(info.border_color); + const vk::SamplerCustomBorderColorCreateInfoEXT border_color_info = { + .customBorderColor = vk::ClearColorValue{ + .float32 = std::array{color[0], color[1], color[2], color[3]} + }, + .format = vk::Format::eUndefined + }; + const vk::SamplerCreateInfo sampler_info = { + .pNext = use_border_color ? &border_color_info : nullptr, .magFilter = PicaToVK::TextureFilterMode(info.mag_filter), .minFilter = PicaToVK::TextureFilterMode(info.min_filter), .mipmapMode = PicaToVK::TextureMipFilterMode(info.mip_filter), @@ -1602,7 +1615,8 @@ vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) { .compareOp = vk::CompareOp::eAlways, .minLod = info.lod_min, .maxLod = info.lod_max, - .borderColor = vk::BorderColor::eIntOpaqueBlack, + .borderColor = use_border_color ? vk::BorderColor::eFloatCustomEXT + : vk::BorderColor::eIntOpaqueBlack, .unnormalizedCoordinates = false}; vk::Device device = instance.GetDevice();