diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index 27a07faf43..6bec02ab7c 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -321,23 +321,53 @@ void VKGSRender::load_texture_env() continue; } - sampler_state->format_ex = tex.format_ex(); - if (sampler_state->is_cyclic_reference) { check_for_cyclic_refs |= true; } - if (!is_sampler_dirty && sampler_state->format_class != previous_format_class) + if (!is_sampler_dirty) { - // Host details changed but RSX is not aware - m_graphics_state |= rsx::fragment_program_state_dirty; + if (sampler_state->format_class != previous_format_class) + { + // Host details changed but RSX is not aware + m_graphics_state |= rsx::fragment_program_state_dirty; + } + + if (fs_sampler_handles[i]) + { + // Nothing to change, use cached sampler + continue; + } } - if (!is_sampler_dirty && fs_sampler_handles[i]) + sampler_state->format_ex = tex.format_ex(); + + if (sampler_state->format_ex.texel_remap_control && + sampler_state->image_handle && + sampler_state->upload_context == rsx::texture_upload_context::shader_read) [[ unlikely ]] { - // Nothing to change, use cached sampler - continue; + // Check if we need to override the view format + const auto vk_format = sampler_state->image_handle->format(); + VkFormat format_override = vk_format;; + rsx::flags32_t flags_to_erase = 0u; + + if (sampler_state->format_ex.hw_SNORM_possible()) + { + format_override = vk::get_compatible_snorm_format(vk_format); + flags_to_erase = rsx::texture_control_bits::SEXT_MASK; + } + else if (sampler_state->format_ex.hw_SRGB_possible()) + { + format_override = vk::get_compatible_srgb_format(vk_format); + flags_to_erase = rsx::texture_control_bits::GAMMA_CTRL_MASK; + } + + if (format_override != VK_FORMAT_UNDEFINED && format_override != vk_format) + { + sampler_state->image_handle = sampler_state->image_handle->as(format_override); + sampler_state->format_ex.texel_remap_control &= (~flags_to_erase); + } } VkFilter mag_filter; diff --git a/rpcs3/Emu/RSX/VK/VKFormats.cpp b/rpcs3/Emu/RSX/VK/VKFormats.cpp index f766a70e79..ed824de77d 100644 --- a/rpcs3/Emu/RSX/VK/VKFormats.cpp +++ b/rpcs3/Emu/RSX/VK/VKFormats.cpp @@ -244,16 +244,80 @@ namespace vk { switch (rgb_format) { + // 8-bit + case VK_FORMAT_R8_UNORM: + return VK_FORMAT_R8_SRGB; + case VK_FORMAT_R8G8_UNORM: + return VK_FORMAT_R8G8_SRGB; + case VK_FORMAT_R8G8B8A8_UNORM: + return VK_FORMAT_R8G8B8A8_SRGB; case VK_FORMAT_B8G8R8A8_UNORM: return VK_FORMAT_B8G8R8A8_SRGB; + // 16-bit + case VK_FORMAT_R16_UNORM: + case VK_FORMAT_R16G16_UNORM: + return VK_FORMAT_UNDEFINED; // No match + case VK_FORMAT_A1R5G5B5_UNORM_PACK16: + case VK_FORMAT_R4G4B4A4_UNORM_PACK16: + case VK_FORMAT_R5G6B5_UNORM_PACK16: + case VK_FORMAT_R5G5B5A1_UNORM_PACK16: + return VK_FORMAT_UNDEFINED; // No match + // DXT case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return VK_FORMAT_BC1_RGBA_SRGB_BLOCK; case VK_FORMAT_BC2_UNORM_BLOCK: return VK_FORMAT_BC2_SRGB_BLOCK; case VK_FORMAT_BC3_UNORM_BLOCK: return VK_FORMAT_BC3_SRGB_BLOCK; + // Depth + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + return VK_FORMAT_UNDEFINED; // Unsupported default: - return rgb_format; + rsx_log.error("[SRGB_FMT] Unexpected VkFormat 0x%x", static_cast(rgb_format)); + return VK_FORMAT_UNDEFINED; + } + } + + VkFormat get_compatible_snorm_format(VkFormat rgb_format) + { + switch (rgb_format) + { + // 8-bit + case VK_FORMAT_R8_UNORM: + return VK_FORMAT_R8_SNORM; + case VK_FORMAT_R8G8_UNORM: + return VK_FORMAT_R8G8_SNORM; + case VK_FORMAT_R8G8B8A8_UNORM: + return VK_FORMAT_R8G8B8A8_SNORM; + case VK_FORMAT_B8G8R8A8_UNORM: + return VK_FORMAT_B8G8R8A8_SNORM; + // 16-bit + case VK_FORMAT_R16_UNORM: + return VK_FORMAT_R16_SNORM; + case VK_FORMAT_R16G16_UNORM: + return VK_FORMAT_R16G16_SNORM; + case VK_FORMAT_A1R5G5B5_UNORM_PACK16: + case VK_FORMAT_R4G4B4A4_UNORM_PACK16: + case VK_FORMAT_R5G6B5_UNORM_PACK16: + case VK_FORMAT_R5G5B5A1_UNORM_PACK16: + return VK_FORMAT_UNDEFINED; // No match + // DXT + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + case VK_FORMAT_BC2_UNORM_BLOCK: + case VK_FORMAT_BC3_UNORM_BLOCK: + return VK_FORMAT_UNDEFINED; // No match + // Depth + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + return VK_FORMAT_UNDEFINED; // Unsupported + default: + rsx_log.error("[SEXT_FMT] Unexpected VkFormat 0x%x", static_cast(rgb_format)); + return VK_FORMAT_UNDEFINED; } } diff --git a/rpcs3/Emu/RSX/VK/VKFormats.h b/rpcs3/Emu/RSX/VK/VKFormats.h index 85b52ca56b..fae25f92b7 100644 --- a/rpcs3/Emu/RSX/VK/VKFormats.h +++ b/rpcs3/Emu/RSX/VK/VKFormats.h @@ -19,6 +19,7 @@ namespace vk VkFormat get_compatible_depth_surface_format(const gpu_formats_support& support, rsx::surface_depth_format2 format); VkFormat get_compatible_sampler_format(const gpu_formats_support& support, u32 format); VkFormat get_compatible_srgb_format(VkFormat rgb_format); + VkFormat get_compatible_snorm_format(VkFormat rgb_format); u8 get_format_texel_width(VkFormat format); std::pair get_format_element_size(VkFormat format); std::pair get_format_convert_flags(VkFormat format);