diff options
Diffstat (limited to 'src/video_core')
9 files changed, 81 insertions, 29 deletions
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.cpp b/src/video_core/renderer_opengl/gl_fence_manager.cpp index 151290101..293ad7d59 100644 --- a/src/video_core/renderer_opengl/gl_fence_manager.cpp +++ b/src/video_core/renderer_opengl/gl_fence_manager.cpp @@ -31,9 +31,8 @@ bool GLInnerFence::IsSignaled() const { return true; } ASSERT(sync_object.handle != 0); - GLsizei length; GLint sync_status; - glGetSynciv(sync_object.handle, GL_SYNC_STATUS, sizeof(GLint), &length, &sync_status); + glGetSynciv(sync_object.handle, GL_SYNC_STATUS, 1, nullptr, &sync_status); return sync_status == GL_SIGNALED; } diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index f8495896c..9e6732abd 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp @@ -243,10 +243,6 @@ GraphicsPipeline::GraphicsPipeline( case Settings::ShaderBackend::GLASM: if (!sources[stage].empty()) { assembly_programs[stage] = CompileProgram(sources[stage], AssemblyStage(stage)); - if (in_parallel) { - // Make sure program is built before continuing when building in parallel - glGetString(GL_PROGRAM_ERROR_STRING_NV); - } } break; case Settings::ShaderBackend::SPIRV: @@ -256,20 +252,18 @@ GraphicsPipeline::GraphicsPipeline( break; } } - if (in_parallel && backend != Settings::ShaderBackend::GLASM) { - // Make sure programs have built if we are building shaders in parallel - for (OGLProgram& program : source_programs) { - if (program.handle != 0) { - GLint status{}; - glGetProgramiv(program.handle, GL_LINK_STATUS, &status); - } - } + if (in_parallel) { + std::lock_guard lock{built_mutex}; + built_fence.Create(); + // Flush this context to ensure compilation commands and fence are in the GPU pipe. + glFlush(); + built_condvar.notify_one(); + } else { + is_built = true; } if (shader_notify) { shader_notify->MarkShaderComplete(); } - is_built = true; - built_condvar.notify_one(); }}; if (thread_worker) { thread_worker->QueueWork(std::move(func)); @@ -440,7 +434,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { buffer_cache.UpdateGraphicsBuffers(is_indexed); buffer_cache.BindHostGeometryBuffers(is_indexed); - if (!is_built.load(std::memory_order::relaxed)) { + if (!IsBuilt()) { WaitForBuild(); } const bool use_assembly{assembly_programs[0].handle != 0}; @@ -585,8 +579,26 @@ void GraphicsPipeline::GenerateTransformFeedbackState() { } void GraphicsPipeline::WaitForBuild() { - std::unique_lock lock{built_mutex}; - built_condvar.wait(lock, [this] { return is_built.load(std::memory_order::relaxed); }); + if (built_fence.handle == 0) { + std::unique_lock lock{built_mutex}; + built_condvar.wait(lock, [this] { return built_fence.handle != 0; }); + } + ASSERT(glClientWaitSync(built_fence.handle, 0, GL_TIMEOUT_IGNORED) != GL_WAIT_FAILED); + is_built = true; +} + +bool GraphicsPipeline::IsBuilt() noexcept { + if (is_built) { + return true; + } + if (built_fence.handle == 0) { + return false; + } + // Timeout of zero means this is non-blocking + const auto sync_status = glClientWaitSync(built_fence.handle, 0, 0); + ASSERT(sync_status != GL_WAIT_FAILED); + is_built = sync_status != GL_TIMEOUT_EXPIRED; + return is_built; } } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index 4e28d9a42..311d49f3f 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h @@ -100,9 +100,7 @@ public: return writes_global_memory; } - [[nodiscard]] bool IsBuilt() const noexcept { - return is_built.load(std::memory_order::relaxed); - } + [[nodiscard]] bool IsBuilt() noexcept; template <typename Spec> static auto MakeConfigureSpecFunc() { @@ -154,7 +152,8 @@ private: std::mutex built_mutex; std::condition_variable built_condvar; - std::atomic_bool is_built{false}; + OGLSync built_fence{}; + bool is_built{false}; }; } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index daba42ed9..db5bf1d30 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h @@ -184,6 +184,8 @@ inline GLenum VertexFormat(Maxwell::VertexAttribute attrib) { case Maxwell::VertexAttribute::Size::Size_32_32_32: case Maxwell::VertexAttribute::Size::Size_32_32_32_32: return GL_FLOAT; + case Maxwell::VertexAttribute::Size::Size_11_11_10: + return GL_UNSIGNED_INT_10F_11F_11F_REV; default: break; } diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 751e4792b..1c136c410 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp @@ -495,6 +495,8 @@ VkFormat VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttrib return VK_FORMAT_R32G32B32_SFLOAT; case Maxwell::VertexAttribute::Size::Size_32_32_32_32: return VK_FORMAT_R32G32B32A32_SFLOAT; + case Maxwell::VertexAttribute::Size::Size_11_11_10: + return VK_FORMAT_B10G11R11_UFLOAT_PACK32; default: break; } diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index c71a1f44d..621a6a071 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -100,6 +100,8 @@ VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { return VK_FORMAT_A8B8G8R8_UNORM_PACK32; case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM: return VK_FORMAT_R5G6B5_UNORM_PACK16; + case Tegra::FramebufferConfig::PixelFormat::B8G8R8A8_UNORM: + return VK_FORMAT_B8G8R8A8_UNORM; default: UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", static_cast<u32>(framebuffer.pixel_format)); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 0ba56ff1e..0f62779de 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -554,10 +554,12 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im }; } -[[nodiscard]] bool IsFormatFlipped(PixelFormat format) { +[[nodiscard]] bool IsFormatFlipped(PixelFormat format, bool emulate_bgr565) { switch (format) { case PixelFormat::A1B5G5R5_UNORM: return true; + case PixelFormat::B5G6R5_UNORM: + return emulate_bgr565; default: return false; } @@ -1488,7 +1490,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI }; if (!info.IsRenderTarget()) { swizzle = info.Swizzle(); - if (IsFormatFlipped(format)) { + if (IsFormatFlipped(format, device->MustEmulateBGR565())) { std::ranges::transform(swizzle, swizzle.begin(), SwapBlueRed); } if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0) { diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 153702c0b..effde73c9 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -39,6 +39,11 @@ constexpr std::array DEPTH16_UNORM_STENCIL8_UINT{ VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_UNDEFINED, }; + +constexpr std::array B5G6R5_UNORM_PACK16{ + VK_FORMAT_R5G6B5_UNORM_PACK16, + VK_FORMAT_UNDEFINED, +}; } // namespace Alternatives enum class NvidiaArchitecture { @@ -87,6 +92,8 @@ constexpr const VkFormat* GetFormatAlternatives(VkFormat format) { return Alternatives::DEPTH24_UNORM_STENCIL8_UINT.data(); case VK_FORMAT_D16_UNORM_S8_UINT: return Alternatives::DEPTH16_UNORM_STENCIL8_UINT.data(); + case VK_FORMAT_B5G6R5_UNORM_PACK16: + return Alternatives::B5G6R5_UNORM_PACK16.data(); default: return nullptr; } @@ -224,9 +231,14 @@ std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) { return supported_extensions; } +bool IsExtensionSupported(std::span<const std::string> supported_extensions, + std::string_view extension) { + return std::ranges::find(supported_extensions, extension) != supported_extensions.end(); +} + NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical, std::span<const std::string> exts) { - if (std::ranges::find(exts, VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME) != exts.end()) { + if (IsExtensionSupported(exts, VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) { VkPhysicalDeviceFragmentShadingRatePropertiesKHR shading_rate_props{}; shading_rate_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR; @@ -239,7 +251,7 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical, return NvidiaArchitecture::AmpereOrNewer; } } - if (std::ranges::find(exts, VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME) != exts.end()) { + if (IsExtensionSupported(exts, VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME)) { return NvidiaArchitecture::Turing; } return NvidiaArchitecture::VoltaOrOlder; @@ -604,7 +616,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR break; } } - if (ext_extended_dynamic_state && driver_id == VK_DRIVER_ID_MESA_RADV) { + const bool is_radv = driver_id == VK_DRIVER_ID_MESA_RADV; + if (ext_extended_dynamic_state && is_radv) { // Mask driver version variant const u32 version = (properties.driverVersion << 3) >> 3; if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) { @@ -613,6 +626,17 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR ext_extended_dynamic_state = false; } } + if (ext_vertex_input_dynamic_state && is_radv) { + // TODO(ameerj): Blacklist only offending driver versions + // TODO(ameerj): Confirm if RDNA1 is affected + const bool is_rdna2 = + IsExtensionSupported(supported_extensions, VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME); + if (is_rdna2) { + LOG_WARNING(Render_Vulkan, + "RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware"); + ext_vertex_input_dynamic_state = false; + } + } sets_per_pool = 64; const bool is_amd = @@ -628,7 +652,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR has_broken_cube_compatibility = true; } } - const bool is_amd_or_radv = is_amd || driver_id == VK_DRIVER_ID_MESA_RADV; + const bool is_amd_or_radv = is_amd || is_radv; if (ext_sampler_filter_minmax && is_amd_or_radv) { // Disable ext_sampler_filter_minmax on AMD GCN4 and lower as it is broken. if (!is_float16_supported) { @@ -639,6 +663,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR } const bool is_intel_windows = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS; + const bool is_intel_anv = driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA; if (ext_vertex_input_dynamic_state && is_intel_windows) { LOG_WARNING(Render_Vulkan, "Blacklisting Intel for VK_EXT_vertex_input_dynamic_state"); ext_vertex_input_dynamic_state = false; @@ -652,6 +677,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR LOG_WARNING(Render_Vulkan, "Intel proprietary drivers do not support MSAA image blits"); cant_blit_msaa = true; } + if (is_intel_anv) { + LOG_WARNING(Render_Vulkan, "ANV driver does not support native BGR format"); + must_emulate_bgr565 = true; + } supports_d24_depth = IsFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT, diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 37d140ebd..34b1add16 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -354,6 +354,10 @@ public: return cant_blit_msaa; } + bool MustEmulateBGR565() const { + return must_emulate_bgr565; + } + private: /// Checks if the physical device is suitable. void CheckSuitability(bool requires_swapchain) const; @@ -448,6 +452,7 @@ private: bool has_nsight_graphics{}; ///< Has Nsight Graphics attached bool supports_d24_depth{}; ///< Supports D24 depth buffers. bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. + bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. // Telemetry parameters std::string vendor_name; ///< Device's driver name. |