Переглянути джерело

testffmpeg: fixed Vulkan validation errors

The semaphores need to be submitted in order
Sam Lantinga 1 рік тому
батько
коміт
97f97109d1
3 змінених файлів з 49 додано та 30 видалено
  1. 22 0
      test/testffmpeg.c
  2. 20 25
      test/testffmpeg_vulkan.c
  3. 7 5
      test/testffmpeg_vulkan.h

+ 22 - 0
test/testffmpeg.c

@@ -881,6 +881,22 @@ static SDL_bool GetTextureForFrame(AVFrame *frame, SDL_Texture **texture)
     }
 }
 
+static int BeginFrameRendering(AVFrame *frame)
+{
+    if (frame->format == AV_PIX_FMT_VULKAN) {
+        return BeginVulkanFrameRendering(vulkan_context, frame, renderer);
+    }
+    return 0;
+}
+
+static int FinishFrameRendering(AVFrame *frame)
+{
+    if (frame->format == AV_PIX_FMT_VULKAN) {
+        return FinishVulkanFrameRendering(vulkan_context, frame, renderer);
+    }
+    return 0;
+}
+
 static void DisplayVideoTexture(AVFrame *frame)
 {
     /* Update the video texture */
@@ -913,6 +929,10 @@ static void HandleVideoFrame(AVFrame *frame, double pts)
         now = (double)(SDL_GetTicks() - video_start) / 1000.0;
     }
 
+    if (BeginFrameRendering(frame) < 0) {
+        return;
+    }
+
     SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
     SDL_RenderClear(renderer);
 
@@ -922,6 +942,8 @@ static void HandleVideoFrame(AVFrame *frame, double pts)
     MoveSprite();
 
     SDL_RenderPresent(renderer);
+
+    FinishFrameRendering(frame);
 }
 
 static AVCodecContext *OpenAudioStream(AVFormatContext *ic, int stream, const AVCodec *codec)

+ 20 - 25
test/testffmpeg_vulkan.c

@@ -773,10 +773,18 @@ static int CreateCommandBuffers(VulkanVideoContext *context, SDL_Renderer *rende
     return 0;
 }
 
-static int ScheduleFrameTransferToSDL(VulkanVideoContext *context, AVFrame *frame)
+int BeginVulkanFrameRendering(VulkanVideoContext *context, AVFrame *frame, SDL_Renderer *renderer)
 {
+    AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
+    AVVulkanFramesContext *vk = (AVVulkanFramesContext *)(frames->hwctx);
     AVVkFrame *pVkFrame = (AVVkFrame *)frame->data[0];
 
+    if (CreateCommandBuffers(context, renderer) < 0) {
+        return -1;
+    }
+
+    vk->lock_frame(frames, pVkFrame);
+
     VkTimelineSemaphoreSubmitInfo timeline = { 0 };
     timeline.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO;
     timeline.waitSemaphoreValueCount = 1;
@@ -834,15 +842,22 @@ static int ScheduleFrameTransferToSDL(VulkanVideoContext *context, AVFrame *fram
 
     VkResult result = context->vkQueueSubmit(context->graphicsQueue, 1, &submitInfo, 0);
     if (result != VK_SUCCESS) {
-        return SDL_SetError("vkQueueSubmit(): %s", getVulkanResultString(result));
+        /* Don't return an error here, we need to complete the frame operation */
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION , "vkQueueSubmit(): %s", getVulkanResultString(result));
     }
+
+    SDL_AddVulkanRenderSemaphores(renderer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (Sint64)context->waitSemaphores[context->commandBufferIndex], (Sint64)context->signalSemaphores[context->commandBufferIndex]);
+
     return 0;
 }
 
-static int ScheduleFrameTransferToFFMPEG(VulkanVideoContext *context, AVFrame *frame)
+int FinishVulkanFrameRendering(VulkanVideoContext *context, AVFrame *frame, SDL_Renderer *renderer)
 {
+    AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
+    AVVulkanFramesContext *vk = (AVVulkanFramesContext *)(frames->hwctx);
     AVVkFrame *pVkFrame = (AVVkFrame *)frame->data[0];
 
+    /* Transition the frame back to ffmpeg */
     ++pVkFrame->sem_value[0];
 
     VkTimelineSemaphoreSubmitInfo timeline = { 0 };
@@ -862,28 +877,12 @@ static int ScheduleFrameTransferToFFMPEG(VulkanVideoContext *context, AVFrame *f
 
     VkResult result = context->vkQueueSubmit(context->graphicsQueue, 1, &submitInfo, 0);
     if (result != VK_SUCCESS) {
-        return SDL_SetError("vkQueueSubmit(): %s", getVulkanResultString(result));
+        /* Don't return an error here, we need to complete the frame operation */
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "vkQueueSubmit(): %s", getVulkanResultString(result));
     }
-    return 0;
-}
 
-static int PrepareFrameRendering(VulkanVideoContext *context, AVFrame *frame, SDL_Renderer *renderer)
-{
-    AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
-    AVVulkanFramesContext *vk = (AVVulkanFramesContext *)(frames->hwctx);
-    AVVkFrame *pVkFrame = (AVVkFrame *)frame->data[0];
-
-    if (CreateCommandBuffers(context, renderer) < 0) {
-        return -1;
-    }
-
-    vk->lock_frame(frames, pVkFrame);
-    ScheduleFrameTransferToSDL(context, frame);
-    ScheduleFrameTransferToFFMPEG(context, frame);
     vk->unlock_frame(frames, pVkFrame);
 
-    SDL_AddVulkanRenderSemaphores(renderer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (Sint64)context->waitSemaphores[context->commandBufferIndex], (Sint64)context->signalSemaphores[context->commandBufferIndex]);
-
     context->commandBufferIndex = (context->commandBufferIndex + 1) % context->commandBufferCount;
 
     return 0;
@@ -896,10 +895,6 @@ SDL_Texture *CreateVulkanVideoTexture(VulkanVideoContext *context, AVFrame *fram
     AVVkFrame *pVkFrame = (AVVkFrame *)frame->data[0];
     Uint32 format;
 
-    if (PrepareFrameRendering(context, frame, renderer) < 0) {
-        return NULL;
-    }
-
     switch (vk->format[0]) {
     case VK_FORMAT_G8B8G8R8_422_UNORM:
         format = SDL_PIXELFORMAT_YUY2;

+ 7 - 5
test/testffmpeg_vulkan.h

@@ -15,8 +15,10 @@
 
 typedef struct VulkanVideoContext VulkanVideoContext;
 
-VulkanVideoContext *CreateVulkanVideoContext(SDL_Window *window);
-void SetupVulkanRenderProperties(VulkanVideoContext *context, SDL_PropertiesID props);
-void SetupVulkanDeviceContextData(VulkanVideoContext *context, AVVulkanDeviceContext *ctx);
-SDL_Texture *CreateVulkanVideoTexture(VulkanVideoContext *context, AVFrame *frame, SDL_Renderer *renderer, SDL_PropertiesID props);
-void DestroyVulkanVideoContext(VulkanVideoContext *context);
+extern VulkanVideoContext *CreateVulkanVideoContext(SDL_Window *window);
+extern void SetupVulkanRenderProperties(VulkanVideoContext *context, SDL_PropertiesID props);
+extern void SetupVulkanDeviceContextData(VulkanVideoContext *context, AVVulkanDeviceContext *ctx);
+extern SDL_Texture *CreateVulkanVideoTexture(VulkanVideoContext *context, AVFrame *frame, SDL_Renderer *renderer, SDL_PropertiesID props);
+extern int BeginVulkanFrameRendering(VulkanVideoContext *context, AVFrame *frame, SDL_Renderer *renderer);
+extern int FinishVulkanFrameRendering(VulkanVideoContext *context, AVFrame *frame, SDL_Renderer *renderer);
+extern void DestroyVulkanVideoContext(VulkanVideoContext *context);