Revert "Remove manual hwframe ctx setup for D3D11VA"

We need this back to avoid the copy that's tanking performance on Intel iGPUs.

This reverts commit 2cef09471b80d46ea3b59a936494a44a68ad5d67.
This commit is contained in:
Cameron Gutman 2024-06-22 12:34:10 -05:00
parent 3aaa09bb7d
commit b6bb96223d
2 changed files with 58 additions and 4 deletions

View File

@ -93,7 +93,8 @@ D3D11VARenderer::D3D11VARenderer(int decoderSelectionPass)
m_VideoTexture(nullptr),
m_OverlayLock(0),
m_OverlayPixelShader(nullptr),
m_HwDeviceContext(nullptr)
m_HwDeviceContext(nullptr),
m_HwFramesContext(nullptr)
{
RtlZeroMemory(m_OverlayVertexBuffers, sizeof(m_OverlayVertexBuffers));
RtlZeroMemory(m_OverlayTextures, sizeof(m_OverlayTextures));
@ -139,6 +140,10 @@ D3D11VARenderer::~D3D11VARenderer()
SAFE_COM_RELEASE(m_RenderTargetView);
SAFE_COM_RELEASE(m_SwapChain);
if (m_HwFramesContext != nullptr) {
av_buffer_unref(&m_HwFramesContext);
}
// Force destruction of the swapchain immediately
if (m_DeviceContext != nullptr) {
m_DeviceContext->ClearState();
@ -429,6 +434,10 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
return false;
}
// Surfaces must be 16 pixel aligned for H.264 and 128 pixel aligned for everything else
// https://github.com/FFmpeg/FFmpeg/blob/a234e5cd80224c95a205c1f3e297d8c04a1374c3/libavcodec/dxva2.c#L609-L616
m_TextureAlignment = (params->videoFormat & VIDEO_FORMAT_MASK_H264) ? 16 : 128;
if (!setupRenderingResources()) {
return false;
}
@ -462,10 +471,44 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
}
}
{
m_HwFramesContext = av_hwframe_ctx_alloc(m_HwDeviceContext);
if (!m_HwFramesContext) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to allocate D3D11VA frame context");
return false;
}
AVHWFramesContext* framesContext = (AVHWFramesContext*)m_HwFramesContext->data;
// We require NV12 or P010 textures for our shader
framesContext->format = AV_PIX_FMT_D3D11;
framesContext->sw_format = (params->videoFormat & VIDEO_FORMAT_MASK_10BIT) ?
AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
framesContext->width = FFALIGN(params->width, m_TextureAlignment);
framesContext->height = FFALIGN(params->height, m_TextureAlignment);
// We can have up to 16 reference frames plus a working surface
framesContext->initial_pool_size = 17;
AVD3D11VAFramesContext* d3d11vaFramesContext = (AVD3D11VAFramesContext*)framesContext->hwctx;
d3d11vaFramesContext->BindFlags = D3D11_BIND_DECODER;
int err = av_hwframe_ctx_init(m_HwFramesContext);
if (err < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to initialize D3D11VA frame context: %d",
err);
return false;
}
// Create our video texture and SRVs
if (!setupVideoTexture()) {
return false;
}
}
return true;
}
@ -480,6 +523,14 @@ bool D3D11VARenderer::prepareDecoderContext(AVCodecContext* context, AVDictionar
return true;
}
bool D3D11VARenderer::prepareDecoderContextInGetFormat(AVCodecContext *context, AVPixelFormat)
{
// hw_frames_ctx must be initialized in ffGetFormat().
context->hw_frames_ctx = av_buffer_ref(m_HwFramesContext);
return true;
}
void D3D11VARenderer::renderFrame(AVFrame* frame)
{
// Acquire the context lock for rendering to prevent concurrent

View File

@ -16,6 +16,7 @@ public:
virtual ~D3D11VARenderer() override;
virtual bool initialize(PDECODER_PARAMETERS params) override;
virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary**) override;
virtual bool prepareDecoderContextInGetFormat(AVCodecContext* context, AVPixelFormat pixelFormat) override;
virtual void renderFrame(AVFrame* frame) override;
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
virtual int getRendererAttributes() override;
@ -47,6 +48,7 @@ private:
SDL_mutex* m_ContextLock;
DECODER_PARAMETERS m_DecoderParams;
int m_TextureAlignment;
int m_DisplayWidth;
int m_DisplayHeight;
int m_LastColorSpace;
@ -70,5 +72,6 @@ private:
ID3D11PixelShader* m_OverlayPixelShader;
AVBufferRef* m_HwDeviceContext;
AVBufferRef* m_HwFramesContext;
};