mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 07:28:11 +02:00
mediafoundation: Move dpb_buffer_manager::get_read_only_handle into d3d12 driver and cache resource
Reviewed-by: Pohsiang (John) Hsu <pohhsu@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38750>
This commit is contained in:
parent
16c98f4f18
commit
3917a5d12a
6 changed files with 135 additions and 125 deletions
|
|
@ -33,17 +33,19 @@ extern "C" {
|
|||
struct ID3D12Device;
|
||||
struct ID3D12CommandQueue;
|
||||
struct ID3D12Resource;
|
||||
struct pipe_video_buffer;
|
||||
struct pipe_context;
|
||||
struct pipe_resource;
|
||||
|
||||
struct d3d12_interop_video_buffer_associated_data
|
||||
{
|
||||
/*
|
||||
* Subresource index within the underlying ID3D12Resource
|
||||
* representing this video buffer.
|
||||
*
|
||||
* This is useful when the underlying resource is a texture array
|
||||
* and each video buffer maps to a different subresource within it.
|
||||
* Function to get read-only resource from video buffer.
|
||||
*/
|
||||
uint32_t subresource_index;
|
||||
bool (*get_read_only_resource)(struct pipe_video_buffer *buffer,
|
||||
struct pipe_context *pipe,
|
||||
struct pipe_resource **readonly_resource,
|
||||
uint32_t *subresource_index);
|
||||
};
|
||||
|
||||
struct d3d12_interop_device_info {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,111 @@
|
|||
#include "d3d12_format.h"
|
||||
#include "d3d12_screen.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
static bool
|
||||
d3d12_video_buffer_get_read_only_resource(struct pipe_video_buffer *buffer,
|
||||
struct pipe_context *pipe,
|
||||
struct pipe_resource **pReadOnlyResource,
|
||||
uint32_t *pSubresourceIndex)
|
||||
{
|
||||
if( !buffer || !pipe || !pReadOnlyResource || !pSubresourceIndex )
|
||||
return false;
|
||||
|
||||
*pReadOnlyResource = nullptr;
|
||||
*pSubresourceIndex = 0;
|
||||
|
||||
struct d3d12_video_buffer *d3d12_buf = (struct d3d12_video_buffer *) buffer;
|
||||
|
||||
// If we have already created a read-only resource for this buffer, reuse it
|
||||
if (d3d12_buf->readonly_resource)
|
||||
{
|
||||
*pReadOnlyResource = (struct pipe_resource *) d3d12_buf->readonly_resource;
|
||||
*pSubresourceIndex = d3d12_buf->subresource_index;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get pipe resources from the video buffer
|
||||
struct pipe_resource *buf_resources[VL_NUM_COMPONENTS];
|
||||
memset( buf_resources, 0, sizeof( buf_resources ) );
|
||||
buffer->get_resources( buffer, &buf_resources[0] );
|
||||
|
||||
if( !buf_resources[0] )
|
||||
return false;
|
||||
|
||||
// Get the winsys handle for the resource
|
||||
struct winsys_handle src_wshandle = {};
|
||||
src_wshandle.type = WINSYS_HANDLE_TYPE_D3D12_RES;
|
||||
|
||||
if( !pipe->screen->resource_get_handle( pipe->screen, pipe, buf_resources[0], &src_wshandle, 0 /*usage*/ ) ||
|
||||
!src_wshandle.com_obj )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a read-only shared handle from the D3D12 resource
|
||||
HANDLE originalHandle = nullptr;
|
||||
|
||||
// First, create a shared handle with full access from the original resource
|
||||
struct d3d12_screen *screen = (struct d3d12_screen *) pipe->screen;
|
||||
HRESULT hr = screen->dev->CreateSharedHandle( static_cast<ID3D12Resource *>( src_wshandle.com_obj ),
|
||||
nullptr, // Security attributes (default)
|
||||
GENERIC_ALL, // Full access for the original handle
|
||||
nullptr, // Name
|
||||
&originalHandle );
|
||||
if( FAILED( hr ) )
|
||||
return false;
|
||||
|
||||
// Duplicate the handle with restricted (read-only) access rights
|
||||
// This creates a new handle that can only be used for reading
|
||||
assert(originalHandle);
|
||||
src_wshandle = {};
|
||||
src_wshandle.type = WINSYS_HANDLE_TYPE_FD;
|
||||
BOOL duplicateResult = DuplicateHandle( GetCurrentProcess(), // Source process handle
|
||||
originalHandle, // Source handle
|
||||
GetCurrentProcess(), // Target process handle
|
||||
&src_wshandle.handle, // Target handle
|
||||
GENERIC_READ, // Desired access (read-only)
|
||||
FALSE, // Inherit handle
|
||||
0 ); // Options
|
||||
|
||||
// Clean up the original handle since we only need the read-only version
|
||||
CloseHandle( originalHandle );
|
||||
|
||||
assert( src_wshandle.handle );
|
||||
if( !duplicateResult || !src_wshandle.handle )
|
||||
{
|
||||
debug_printf( "[d3d12_video_buffer_get_read_only_resource] Invalid handle for reconstructed picture resource\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a winsys handle for the read-only resource
|
||||
// and import it back as a pipe_resource
|
||||
*pReadOnlyResource = pipe->screen->resource_from_handle( pipe->screen, NULL, &src_wshandle, 0 /*usage*/ );
|
||||
|
||||
CloseHandle( src_wshandle.handle ); // Close our local copy of the handle after import
|
||||
|
||||
if( !*pReadOnlyResource )
|
||||
{
|
||||
assert( *pReadOnlyResource );
|
||||
debug_printf( "[d3d12_video_buffer_get_read_only_resource] Failed to import reconstructed picture resource\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cache the resource for future use
|
||||
// The d3d12_video_buffer manages the lifetime of this resource
|
||||
// and the app is given a weak reference to it via pReadOnlyResource
|
||||
// The cached resource will be destroyed when the video buffer is destroyed
|
||||
d3d12_buf->readonly_resource = (void*) *pReadOnlyResource;
|
||||
|
||||
// Return the subresource index
|
||||
// from the video buffer which will contain the subresource index
|
||||
// if the underlying resource uses texture arrays
|
||||
*pSubresourceIndex = d3d12_buf->subresource_index;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
static struct pipe_video_buffer *
|
||||
d3d12_video_buffer_create_impl(struct pipe_context *pipe,
|
||||
const struct pipe_video_buffer *tmpl,
|
||||
|
|
@ -66,6 +171,9 @@ d3d12_video_buffer_create_impl(struct pipe_context *pipe,
|
|||
pD3D12VideoBuffer->base.interlaced = tmpl->interlaced;
|
||||
pD3D12VideoBuffer->base.contiguous_planes = true;
|
||||
pD3D12VideoBuffer->base.associated_data = &pD3D12VideoBuffer->d3d12_video_buffer_associated_data;
|
||||
#ifdef _WIN32
|
||||
pD3D12VideoBuffer->d3d12_video_buffer_associated_data.get_read_only_resource = d3d12_video_buffer_get_read_only_resource;
|
||||
#endif // _WIN32
|
||||
pD3D12VideoBuffer->idx_texarray_slots = 0;
|
||||
pD3D12VideoBuffer->m_spVideoTexArrayDPBPoolInUse.reset();
|
||||
|
||||
|
|
@ -253,6 +361,11 @@ d3d12_video_buffer_destroy(struct pipe_video_buffer *buffer)
|
|||
}
|
||||
}
|
||||
|
||||
// Clean up readonly_resource
|
||||
if (pD3D12VideoBuffer->readonly_resource) {
|
||||
pipe_resource_reference((struct pipe_resource**)&pD3D12VideoBuffer->readonly_resource, NULL);
|
||||
}
|
||||
|
||||
delete pD3D12VideoBuffer;
|
||||
}
|
||||
|
||||
|
|
@ -535,7 +648,7 @@ d3d12_video_create_dpb_buffer_texarray(struct pipe_video_codec *codec,
|
|||
if (((*pD3D12Enc->m_spVideoTexArrayDPBPoolInUse) & (1 << i)) == 0)
|
||||
{
|
||||
buf->idx_texarray_slots = i;
|
||||
buf->d3d12_video_buffer_associated_data.subresource_index = i;
|
||||
buf->subresource_index = i;
|
||||
(*pD3D12Enc->m_spVideoTexArrayDPBPoolInUse) |= (1 << buf->idx_texarray_slots); // Mark i-th bit as used
|
||||
bFoundEmptySlot = true;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -109,6 +109,9 @@ struct d3d12_video_buffer
|
|||
// Points to the same address as d3d12_video_encoder::m_spVideoTexArrayDPBPoolInUse
|
||||
std::shared_ptr<uint32_t> m_spVideoTexArrayDPBPoolInUse;
|
||||
struct d3d12_interop_video_buffer_associated_data d3d12_video_buffer_associated_data = {};
|
||||
|
||||
uint32_t subresource_index = 0;
|
||||
void* readonly_resource = nullptr;
|
||||
};
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -31,86 +31,6 @@
|
|||
#include "dpb_buffer_manager.tmh"
|
||||
|
||||
|
||||
HRESULT
|
||||
dpb_buffer_manager::get_read_only_handle( struct pipe_video_buffer *buffer,
|
||||
struct pipe_context *pipe,
|
||||
ComPtr<ID3D12Device> &device,
|
||||
HANDLE *pReadOnlyHandle,
|
||||
UINT *pSubresourceIndex )
|
||||
{
|
||||
if( !buffer || !pipe || !device || !pReadOnlyHandle || !pSubresourceIndex )
|
||||
return E_POINTER;
|
||||
|
||||
*pReadOnlyHandle = nullptr;
|
||||
|
||||
// Get pipe resources from the video buffer
|
||||
struct pipe_resource *buf_resources[VL_NUM_COMPONENTS];
|
||||
memset( buf_resources, 0, sizeof( buf_resources ) );
|
||||
buffer->get_resources( buffer, &buf_resources[0] );
|
||||
|
||||
if( !buf_resources[0] )
|
||||
return E_INVALIDARG;
|
||||
|
||||
// Get the winsys handle for the resource
|
||||
struct winsys_handle src_wshandle = {};
|
||||
src_wshandle.type = WINSYS_HANDLE_TYPE_D3D12_RES;
|
||||
|
||||
if( !pipe->screen->resource_get_handle( pipe->screen, pipe, buf_resources[0], &src_wshandle, 0 /*usage*/ ) )
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if( !src_wshandle.com_obj )
|
||||
return E_FAIL;
|
||||
|
||||
// Create a read-only shared handle from the D3D12 resource
|
||||
HRESULT hr = S_OK;
|
||||
HANDLE originalHandle = nullptr;
|
||||
|
||||
// First, create a shared handle with full access from the original resource
|
||||
hr = device->CreateSharedHandle( static_cast<ID3D12Resource *>( src_wshandle.com_obj ),
|
||||
nullptr, // Security attributes (default)
|
||||
GENERIC_ALL, // Full access for the original handle
|
||||
nullptr, // Name
|
||||
&originalHandle );
|
||||
if( FAILED( hr ) || !originalHandle )
|
||||
return hr;
|
||||
|
||||
// Duplicate the handle with restricted (read-only) access rights
|
||||
// This creates a new handle that can only be used for reading
|
||||
BOOL duplicateResult = DuplicateHandle( GetCurrentProcess(), // Source process handle
|
||||
originalHandle, // Source handle
|
||||
GetCurrentProcess(), // Target process handle
|
||||
pReadOnlyHandle, // Target handle
|
||||
GENERIC_READ, // Desired access (read-only)
|
||||
FALSE, // Inherit handle
|
||||
0 ); // Options
|
||||
|
||||
// Clean up the original handle since we only need the read-only version
|
||||
CloseHandle( originalHandle );
|
||||
|
||||
if( !duplicateResult || !*pReadOnlyHandle )
|
||||
{
|
||||
return HRESULT_FROM_WIN32( GetLastError() );
|
||||
}
|
||||
|
||||
// Retrieve subresource index if available
|
||||
// from the associated data of the video buffer
|
||||
// which will contain the subresource index
|
||||
// if the underlying resource uses texture arrays
|
||||
if( buffer->associated_data )
|
||||
{
|
||||
struct d3d12_interop_video_buffer_associated_data *associated_data =
|
||||
static_cast<struct d3d12_interop_video_buffer_associated_data *>( buffer->associated_data );
|
||||
*pSubresourceIndex = associated_data->subresource_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pSubresourceIndex = 0; // Default to 0 if no associated data
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// retrieve a buffer from the pool
|
||||
struct pipe_video_buffer *
|
||||
|
|
|
|||
|
|
@ -44,14 +44,6 @@ class dpb_buffer_manager
|
|||
// release a buffer back to the pool
|
||||
void release_dpb_buffer( struct pipe_video_buffer *target );
|
||||
|
||||
/**
|
||||
* get a read-only shared handle from the video buffer's internal D3D12 resource
|
||||
*/
|
||||
static HRESULT get_read_only_handle( struct pipe_video_buffer *buffer,
|
||||
struct pipe_context *pipe,
|
||||
ComPtr<ID3D12Device> &device,
|
||||
HANDLE *pReadOnlyHandle,
|
||||
UINT *pSubresourceIndex );
|
||||
|
||||
private:
|
||||
const void *m_logId = {};
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "mfbufferhelp.h"
|
||||
#include "mfpipeinterop.h"
|
||||
#include "wpptrace.h"
|
||||
#include "gallium/drivers/d3d12/d3d12_interop_public.h"
|
||||
|
||||
#include "mftransform.tmh"
|
||||
|
||||
|
|
@ -2574,38 +2575,17 @@ CDX12EncHMFT::ProcessInput( DWORD dwInputStreamIndex, IMFSample *pSample, DWORD
|
|||
}
|
||||
|
||||
// Get read-only handle directly from the video buffer
|
||||
HANDLE readOnlyHandle = nullptr;
|
||||
HRESULT hr =
|
||||
dpb_buffer_manager::get_read_only_handle( src_buffer,
|
||||
m_pPipeContext,
|
||||
m_spDevice,
|
||||
&readOnlyHandle,
|
||||
&pDX12EncodeContext->PipeResourceReconstructedPictureSubresource );
|
||||
CHECKHR_GOTO( hr, done );
|
||||
CHECKNULL_GOTO( readOnlyHandle, E_FAIL, done );
|
||||
if( !readOnlyHandle )
|
||||
debug_printf( "[dx12 hmft 0x%p] Failed to get read-only handle from video buffer\n", this );
|
||||
|
||||
struct winsys_handle src_wshandle = {};
|
||||
src_wshandle.type = WINSYS_HANDLE_TYPE_FD;
|
||||
src_wshandle.handle = readOnlyHandle;
|
||||
|
||||
assert( src_wshandle.handle );
|
||||
if( !src_wshandle.handle )
|
||||
struct d3d12_interop_video_buffer_associated_data *associated_data =
|
||||
static_cast<struct d3d12_interop_video_buffer_associated_data *>( src_buffer->associated_data );
|
||||
if(associated_data->get_read_only_resource &&
|
||||
(!associated_data->get_read_only_resource( src_buffer,
|
||||
m_pPipeContext,
|
||||
&pDX12EncodeContext->pPipeResourceReconstructedPicture,
|
||||
&pDX12EncodeContext->PipeResourceReconstructedPictureSubresource ) || !pDX12EncodeContext->pPipeResourceReconstructedPicture) )
|
||||
{
|
||||
debug_printf( "[dx12 hmft 0x%p] Invalid handle for reconstructed picture resource\n", this );
|
||||
CHECKHR_GOTO( E_FAIL, done );
|
||||
debug_printf( "[dx12 hmft 0x%p] Failed to get read-only resource from reference video buffer\n", this );
|
||||
}
|
||||
// Import the reconstructed picture resource from handle
|
||||
pDX12EncodeContext->pPipeResourceReconstructedPicture =
|
||||
m_pPipeContext->screen->resource_from_handle( m_pPipeContext->screen, NULL, &src_wshandle, 0 /*usage*/ );
|
||||
assert( pDX12EncodeContext->pPipeResourceReconstructedPicture );
|
||||
if( !pDX12EncodeContext->pPipeResourceReconstructedPicture )
|
||||
{
|
||||
debug_printf( "[dx12 hmft 0x%p] Failed to import reconstructed picture resource\n", this );
|
||||
CHECKHR_GOTO( E_FAIL, done );
|
||||
}
|
||||
CloseHandle( readOnlyHandle );
|
||||
CHECKNULL_GOTO( pDX12EncodeContext->pPipeResourceReconstructedPicture, E_FAIL, done );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue