d3d12: Use EnqueueMakeResident with GPU Wait for video permanent residency promotions

Reviewed-by: Pohsiang (John) Hsu <pohhsu@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38057>
This commit is contained in:
Silvio Vilerino
2025-10-23 10:40:00 -04:00
committed by Marge Bot
parent ca3ba3f924
commit 7e1982a7eb
4 changed files with 85 additions and 18 deletions
+49 -8
View File
@@ -281,8 +281,26 @@ d3d12_deinit_residency(struct d3d12_screen *screen)
}
void
d3d12_promote_to_permanent_residency(struct d3d12_screen *screen, struct d3d12_resource** resources, unsigned count)
d3d12_promote_to_permanent_residency(
struct d3d12_screen *screen,
struct d3d12_resource** resources,
unsigned count,
ID3D12Fence* pResidencyFence, /* NULL implies usage of synchronous MakeResident */
uint64_t *pResidencyFenceValue /* Out: value to wait on for residency for this call */
)
{
#if MESA_DEBUG
if (pResidencyFence && !pResidencyFenceValue)
{
debug_printf("D3D12: d3d12_promote_to_permanent_residency called with a fence but no fence value out parameter!\n");
assert(false);
}
if (pResidencyFence && pResidencyFenceValue) {
debug_printf("D3D12: promote_to_permanent_residency called with %u resources, current fence value: %" PRIu64 "\n", count, *pResidencyFenceValue);
}
#endif // MESA_DEBUG
if (count == 0)
return;
@@ -291,11 +309,29 @@ d3d12_promote_to_permanent_residency(struct d3d12_screen *screen, struct d3d12_r
ID3D12Pageable *pageables_to_make_resident[residency_batch_size];
unsigned num_to_make_resident = 0;
auto flush_batch = [](struct d3d12_screen *screen, ID3D12Pageable **pageables, unsigned count) {
auto flush_batch = [](struct d3d12_screen *screen, ID3D12Pageable **pageables, unsigned count, ID3D12Fence* pResidencyFence, uint64_t *pResidencyFenceValue) {
if (count > 0) {
ASSERTED HRESULT hr = screen->dev->MakeResident(count, pageables);
ASSERTED HRESULT hr = S_OK;
if (!pResidencyFence)
{
hr = screen->dev->MakeResident(count, pageables);
if(SUCCEEDED(hr))
{
debug_printf("D3D12: Promoted %u resources to permanent residency (synchronous)\n", count);
}
}
else
{
hr = screen->dev->EnqueueMakeResident(D3D12_RESIDENCY_FLAG_NONE, count, pageables,
pResidencyFence, (*pResidencyFenceValue) + 1);
if(SUCCEEDED(hr))
{
(*pResidencyFenceValue)++;
debug_printf("D3D12: Promoted %u resources to permanent residency (asynchronous) with fence object %p and fence value %" PRIu64 " and hr %x\n", count, pResidencyFence, *pResidencyFenceValue, (unsigned)hr);
}
}
assert(SUCCEEDED(hr));
debug_printf("D3D12: Promoted %u resources to permanent residency\n", count);
}
};
@@ -311,19 +347,24 @@ d3d12_promote_to_permanent_residency(struct d3d12_screen *screen, struct d3d12_r
assert(num_to_make_resident < residency_batch_size);
pageables_to_make_resident[num_to_make_resident++] = base_bo->res;
if (num_to_make_resident == residency_batch_size) {
flush_batch(screen, pageables_to_make_resident, num_to_make_resident);
flush_batch(screen, pageables_to_make_resident, num_to_make_resident, pResidencyFence, pResidencyFenceValue);
num_to_make_resident = 0;
}
}
}
}
flush_batch(screen, pageables_to_make_resident, num_to_make_resident);
flush_batch(screen, pageables_to_make_resident, num_to_make_resident, pResidencyFence, pResidencyFenceValue);
mtx_unlock(&screen->submit_mutex);
}
void
d3d12_promote_to_permanent_residency(struct d3d12_screen *screen, struct d3d12_resource* resource)
d3d12_promote_to_permanent_residency(
struct d3d12_screen *screen,
struct d3d12_resource* resource,
ID3D12Fence* pResidencyFence, /* NULL implies usage of synchronous MakeResident */
uint64_t *pResidencyFenceValue /* Out: value to wait on for residency for this call */
)
{
// Early out for null resource or if the bo is already permanently resident
if (!resource)
@@ -336,5 +377,5 @@ d3d12_promote_to_permanent_residency(struct d3d12_screen *screen, struct d3d12_r
return;
}
d3d12_promote_to_permanent_residency(screen, &resource, 1);
d3d12_promote_to_permanent_residency(screen, &resource, 1, pResidencyFence, pResidencyFenceValue);
}
+13 -2
View File
@@ -36,7 +36,18 @@ void
d3d12_deinit_residency(struct d3d12_screen *screen);
void
d3d12_promote_to_permanent_residency(struct d3d12_screen *screen, struct d3d12_resource** resources, unsigned count);
d3d12_promote_to_permanent_residency(
struct d3d12_screen *screen,
struct d3d12_resource** resources,
unsigned count,
ID3D12Fence* pResidencyFence = NULL,
uint64_t *pResidencyFenceValue = NULL
);
void
d3d12_promote_to_permanent_residency(struct d3d12_screen *screen, struct d3d12_resource* resource);
d3d12_promote_to_permanent_residency(
struct d3d12_screen *screen,
struct d3d12_resource* resource,
ID3D12Fence* pResidencyFence = NULL,
uint64_t *pResidencyFenceValue = NULL
);
+21 -8
View File
@@ -123,6 +123,9 @@ d3d12_video_encoder_flush(struct pipe_video_codec *codec)
pD3D12Enc->m_spEncodeCommandQueue->Wait(casted_completion_fence->cmdqueue_fence, casted_completion_fence->value);
pD3D12Enc->m_pD3D12Screen->base.fence_reference(&pD3D12Enc->m_pD3D12Screen->base, &completion_fence, NULL);
// Wait on residency fence for this frame to ensure all resources used in encoding are resident
pD3D12Enc->m_spEncodeCommandQueue->Wait(pD3D12Enc->m_spResidencyFence.Get(), pD3D12Enc->m_ResidencyFenceValue);
struct d3d12_fence *input_surface_fence = pD3D12Enc->m_inflightResourcesPool[current_pool_idx].m_InputSurfaceFence;
if (input_surface_fence)
d3d12_fence_wait_impl(input_surface_fence, pD3D12Enc->m_spEncodeCommandQueue.Get(),
@@ -2378,6 +2381,14 @@ d3d12_video_encoder_create_command_objects(struct d3d12_video_encoder *pD3D12Enc
return false;
}
hr = pD3D12Enc->m_pD3D12Screen->dev->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&pD3D12Enc->m_spResidencyFence));
if (FAILED(hr)) {
debug_printf(
"[d3d12_video_encoder] d3d12_video_encoder_create_command_objects - Call to CreateFence failed with HR %x\n",
(unsigned)hr);
return false;
}
hr = pD3D12Enc->m_pD3D12Screen->dev->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&pD3D12Enc->m_spLastSliceFence));
if (FAILED(hr)) {
debug_printf(
@@ -3293,12 +3304,10 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
}
// Make permanently resident for video use - batch promote all slice buffers
if (num_slice_objects > 0) {
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, pD3D12Enc->m_pOutputBitstreamBuffers.data(), num_slice_objects);
}
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, pD3D12Enc->m_pOutputBitstreamBuffers.data(), num_slice_objects, pD3D12Enc->m_spResidencyFence.Get(), &pD3D12Enc->m_ResidencyFenceValue);
// Make permanently resident for video use
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, pInputVideoBuffer->texture);
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, &pInputVideoBuffer->texture, 1, pD3D12Enc->m_spResidencyFence.Get(), &pD3D12Enc->m_ResidencyFenceValue);
size_t current_metadata_slot = d3d12_video_encoder_metadata_current_index(pD3D12Enc);
@@ -3801,7 +3810,8 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAGS optionalMetadataFlags = D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_NONE;
if (pD3D12Enc->m_currentEncodeConfig.m_GPUQPStatsResource) {
optionalMetadataFlags |= D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_QP_MAP;
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, pD3D12Enc->m_currentEncodeConfig.m_GPUQPStatsResource);
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, &pD3D12Enc->m_currentEncodeConfig.m_GPUQPStatsResource,
1, pD3D12Enc->m_spResidencyFence.Get(), &pD3D12Enc->m_ResidencyFenceValue);
d3d12_transition_resource_state(d3d12_context(pD3D12Enc->base.context),
pD3D12Enc->m_currentEncodeConfig.m_GPUQPStatsResource,
D3D12_RESOURCE_STATE_COMMON,
@@ -3813,7 +3823,8 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
ID3D12Resource* d12_gpu_stats_satd_map = NULL;
if (pD3D12Enc->m_currentEncodeConfig.m_GPUSATDStatsResource) {
optionalMetadataFlags |= D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_SATD_MAP;
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, pD3D12Enc->m_currentEncodeConfig.m_GPUSATDStatsResource);
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, &pD3D12Enc->m_currentEncodeConfig.m_GPUSATDStatsResource,
1, pD3D12Enc->m_spResidencyFence.Get(), &pD3D12Enc->m_ResidencyFenceValue);
d3d12_transition_resource_state(d3d12_context(pD3D12Enc->base.context),
pD3D12Enc->m_currentEncodeConfig.m_GPUSATDStatsResource,
D3D12_RESOURCE_STATE_COMMON,
@@ -3825,7 +3836,8 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
ID3D12Resource* d12_gpu_stats_rc_bitallocation_map = NULL;
if (pD3D12Enc->m_currentEncodeConfig.m_GPURCBitAllocationStatsResource) {
optionalMetadataFlags |= D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_RC_BIT_ALLOCATION_MAP;
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, pD3D12Enc->m_currentEncodeConfig.m_GPURCBitAllocationStatsResource);
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, &pD3D12Enc->m_currentEncodeConfig.m_GPURCBitAllocationStatsResource,
1, pD3D12Enc->m_spResidencyFence.Get(), &pD3D12Enc->m_ResidencyFenceValue);
d3d12_transition_resource_state(d3d12_context(pD3D12Enc->base.context),
pD3D12Enc->m_currentEncodeConfig.m_GPURCBitAllocationStatsResource,
D3D12_RESOURCE_STATE_COMMON,
@@ -3837,7 +3849,8 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
ID3D12Resource* d12_gpu_stats_psnr = NULL;
if (pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource) {
optionalMetadataFlags |= D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_FRAME_PSNR;
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource);
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, &pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource,
1, pD3D12Enc->m_spResidencyFence.Get(), &pD3D12Enc->m_ResidencyFenceValue);
d3d12_transition_resource_state(d3d12_context(pD3D12Enc->base.context),
pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource,
D3D12_RESOURCE_STATE_COMMON,
@@ -581,9 +581,11 @@ struct d3d12_video_encoder
size_t m_MaxMetadataBuffersCount = 0;
ComPtr<ID3D12Fence> m_spFence;
ComPtr<ID3D12Fence> m_spResidencyFence;
ComPtr<ID3D12Fence> m_spLastSliceFence;
uint64_t m_fenceValue = 1u;
uint64_t m_LastSliceFenceValue = 1u;
uint64_t m_ResidencyFenceValue = 0u;
bool m_bPendingWorkNotFlushed = false;
ComPtr<ID3D12VideoDevice3> m_spD3D12VideoDevice;