#pragma once #include "renderer.h" #include #include #include class PlVkRenderer : public IFFmpegRenderer { public: PlVkRenderer(IFFmpegRenderer* backendRenderer); virtual ~PlVkRenderer() override; virtual bool initialize(PDECODER_PARAMETERS params) override; virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary** options) override; virtual void renderFrame(AVFrame* frame) override; virtual bool testRenderFrame(AVFrame* frame) override; virtual void waitToRender() override; virtual void cleanupRenderContext() override; virtual void notifyOverlayUpdated(Overlay::OverlayType) override; virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO) override; virtual int getRendererAttributes() override; virtual int getDecoderCapabilities() override; virtual bool needsTestFrame() override; virtual bool isPixelFormatSupported(int videoFormat, enum AVPixelFormat pixelFormat) override; virtual AVPixelFormat getPreferredPixelFormat(int videoFormat) override; virtual RendererType getRendererType() override; private: static void lockQueue(AVHWDeviceContext *dev_ctx, uint32_t queue_family, uint32_t index); static void unlockQueue(AVHWDeviceContext *dev_ctx, uint32_t queue_family, uint32_t index); static void overlayUploadComplete(void* opaque); bool mapAvFrameToPlacebo(const AVFrame *frame, pl_frame* mappedFrame); bool getQueue(VkQueueFlags requiredFlags, uint32_t* queueIndex, uint32_t* queueCount); bool chooseVulkanDevice(PDECODER_PARAMETERS params); bool tryInitializeDevice(VkPhysicalDevice device, VkPhysicalDeviceProperties* deviceProps, PDECODER_PARAMETERS decoderParams); bool isExtensionSupportedByPhysicalDevice(VkPhysicalDevice device, const char* extensionName); bool isPresentModeSupportedByPhysicalDevice(VkPhysicalDevice device, VkPresentModeKHR presentMode); bool isColorSpaceSupportedByPhysicalDevice(VkPhysicalDevice device, VkColorSpaceKHR colorSpace); bool isSurfacePresentationSupportedByPhysicalDevice(VkPhysicalDevice device); // The backend renderer if we're frontend-only IFFmpegRenderer* m_Backend; // SDL state SDL_Window* m_Window = nullptr; // The libplacebo rendering state pl_log m_Log = nullptr; pl_vk_inst m_PlVkInstance = nullptr; VkSurfaceKHR m_VkSurface = nullptr; pl_vulkan m_Vulkan = nullptr; pl_swapchain m_Swapchain = nullptr; pl_renderer m_Renderer = nullptr; pl_tex m_Textures[PL_MAX_PLANES] = {}; pl_color_space m_LastColorspace = {}; // Pending swapchain state shared between waitToRender(), renderFrame(), and cleanupRenderContext() pl_swapchain_frame m_SwapchainFrame = {}; bool m_HasPendingSwapchainFrame = false; // Overlay state SDL_SpinLock m_OverlayLock = 0; struct { // The staging overlay state is copied here under the overlay lock in the render thread. // // These values can be safely read by the render thread outside of the overlay lock, // but the copy from stagingOverlay to overlay must only happen under the overlay // lock when hasStagingOverlay is true. bool hasOverlay; pl_overlay overlay; // This state is written by the overlay update thread // // NB: hasStagingOverlay may be false even if there is a staging overlay texture present, // because this is how the overlay update path indicates that the overlay is not currently // safe for the render thread to read. // // It is safe for the overlay update thread to write to stagingOverlay outside of the lock, // as long as hasStagingOverlay is false. bool hasStagingOverlay; pl_overlay stagingOverlay; } m_Overlays[Overlay::OverlayMax] = {}; // Device context used for hwaccel decoders AVBufferRef* m_HwDeviceCtx = nullptr; // Vulkan functions we call directly PFN_vkDestroySurfaceKHR fn_vkDestroySurfaceKHR = nullptr; PFN_vkGetPhysicalDeviceQueueFamilyProperties fn_vkGetPhysicalDeviceQueueFamilyProperties = nullptr; PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fn_vkGetPhysicalDeviceSurfacePresentModesKHR = nullptr; PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fn_vkGetPhysicalDeviceSurfaceFormatsKHR = nullptr; PFN_vkEnumeratePhysicalDevices fn_vkEnumeratePhysicalDevices = nullptr; PFN_vkGetPhysicalDeviceProperties fn_vkGetPhysicalDeviceProperties = nullptr; PFN_vkGetPhysicalDeviceSurfaceSupportKHR fn_vkGetPhysicalDeviceSurfaceSupportKHR = nullptr; PFN_vkEnumerateDeviceExtensionProperties fn_vkEnumerateDeviceExtensionProperties = nullptr; };