Mesa (main): d3d12: Add pipe_video_codec::process_frame implementation

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jul 21 23:05:21 UTC 2022


Module: Mesa
Branch: main
Commit: 323cf5a68d31ca7a885570b88a5a8bcdcadb0162
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=323cf5a68d31ca7a885570b88a5a8bcdcadb0162

Author: Sil Vilerino <sivileri at microsoft.com>
Date:   Fri Jul 15 08:03:56 2022 -0400

d3d12: Add pipe_video_codec::process_frame implementation

Reviewed-by: Jesse Natalie <jenatali at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17557>

---

 src/gallium/drivers/d3d12/d3d12_common.h       |  13 +
 src/gallium/drivers/d3d12/d3d12_video_proc.cpp | 680 +++++++++++++++++++++++++
 src/gallium/drivers/d3d12/d3d12_video_proc.h   | 139 +++++
 src/gallium/drivers/d3d12/meson.build          |   1 +
 4 files changed, 833 insertions(+)

diff --git a/src/gallium/drivers/d3d12/d3d12_common.h b/src/gallium/drivers/d3d12/d3d12_common.h
index 0237843cc2c..749979071ff 100644
--- a/src/gallium/drivers/d3d12/d3d12_common.h
+++ b/src/gallium/drivers/d3d12/d3d12_common.h
@@ -34,6 +34,7 @@
 
 #define D3D12_IGNORE_SDK_LAYERS
 #include <directx/d3d12.h>
+#include <directx/d3d12video.h>
 
 #if defined(__cplusplus)
 #if !defined(_WIN32) || defined(_MSC_VER) || D3D12_SDK_VERSION < 606
@@ -62,6 +63,11 @@ GetAdapterLuid(ID3D12Device *dev)
 {
    return dev->GetAdapterLuid();
 }
+inline D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC
+GetOutputStreamDesc(ID3D12VideoProcessor *proc)
+{
+   return proc->GetOutputStreamDesc();
+}
 #else
 inline D3D12_CPU_DESCRIPTOR_HANDLE
 GetCPUDescriptorHandleForHeapStart(ID3D12DescriptorHeap *heap)
@@ -98,6 +104,13 @@ GetAdapterLuid(ID3D12Device *dev)
    dev->GetAdapterLuid(&ret);
    return ret;
 }
+inline D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC
+GetOutputStreamDesc(ID3D12VideoProcessor *proc)
+{
+   D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC ret;
+   proc->GetOutputStreamDesc(&ret);
+   return ret;
+}
 #endif
 #endif
 
diff --git a/src/gallium/drivers/d3d12/d3d12_video_proc.cpp b/src/gallium/drivers/d3d12/d3d12_video_proc.cpp
new file mode 100644
index 00000000000..8cc5f0c3fb4
--- /dev/null
+++ b/src/gallium/drivers/d3d12/d3d12_video_proc.cpp
@@ -0,0 +1,680 @@
+/*
+ * Copyright © Microsoft Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "d3d12_context.h"
+#include "d3d12_screen.h"
+#include "d3d12_video_proc.h"
+#include "d3d12_residency.h"
+#include "d3d12_util.h"
+#include "d3d12_resource.h"
+#include "d3d12_video_buffer.h"
+
+void
+d3d12_video_processor_begin_frame(struct pipe_video_codec * codec,
+                                struct pipe_video_buffer *target,
+                                struct pipe_picture_desc *picture)
+{
+    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
+    debug_printf("[d3d12_video_processor] d3d12_video_processor_begin_frame - "
+                "fenceValue: %d\n",
+                pD3D12Proc->m_fenceValue);
+
+    // Setup process frame arguments for output/target texture.
+    struct d3d12_video_buffer *pOutputVideoBuffer = (struct d3d12_video_buffer *) target;
+
+    // Make the resources permanently resident for video use
+    d3d12_promote_to_permanent_residency(pD3D12Proc->m_pD3D12Screen, pOutputVideoBuffer->texture);
+
+    ID3D12Resource *pDstD3D12Res = d3d12_resource_resource(pOutputVideoBuffer->texture);    
+    auto dstDesc = GetDesc(pDstD3D12Res);
+    pD3D12Proc->m_OutputArguments = {
+        {
+            {
+                    pDstD3D12Res, // ID3D12Resource *pTexture2D;
+                    0, // UINT Subresource;
+            },
+            {
+                    NULL, // ID3D12Resource *pTexture2D;
+                    0 // UINT Subresource;
+            }
+        },
+        { 0, 0, (int) dstDesc.Width, (int) dstDesc.Height }
+    };
+    
+    debug_printf("d3d12_video_processor_begin_frame: Beginning new scene with Output ID3D12Resource: %p (%d %d)\n", pDstD3D12Res, (int) dstDesc.Width, (int) dstDesc.Height);
+}
+
+void
+d3d12_video_processor_end_frame(struct pipe_video_codec * codec,
+                              struct pipe_video_buffer *target,
+                              struct pipe_picture_desc *picture)
+{
+    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
+    debug_printf("[d3d12_video_processor] d3d12_video_processor_end_frame - "
+                "fenceValue: %d\n",
+                pD3D12Proc->m_fenceValue);
+
+    auto curOutputDesc = GetOutputStreamDesc(pD3D12Proc->m_spVideoProcessor.Get());
+    auto curOutputTexFmt = GetDesc(pD3D12Proc->m_OutputArguments.OutputStream[0].pTexture2D).Format;
+    
+    bool inputFmtsMatch = pD3D12Proc->m_inputStreamDescs.size() == pD3D12Proc->m_ProcessInputs.size();
+    unsigned curInputIdx = 0;
+    while( (curInputIdx < pD3D12Proc->m_inputStreamDescs.size()) && inputFmtsMatch)    
+    {
+        inputFmtsMatch = inputFmtsMatch && (pD3D12Proc->m_inputStreamDescs[curInputIdx].Format == GetDesc(pD3D12Proc->m_ProcessInputs[curInputIdx].InputStream[0].pTexture2D).Format);
+        curInputIdx++;
+    }
+
+    bool inputCountMatches = (pD3D12Proc->m_ProcessInputs.size() == pD3D12Proc->m_spVideoProcessor->GetNumInputStreamDescs());
+    bool outputFmtMatches = (curOutputDesc.Format == curOutputTexFmt);
+    bool needsVPRecreation = (
+        !inputCountMatches // Requested batch has different number of Inputs to be blit'd
+        || !outputFmtMatches // output texture format different than vid proc object expects
+        || !inputFmtsMatch // inputs texture formats different than vid proc object expects
+    );
+
+    if(needsVPRecreation) {
+        debug_printf("[d3d12_video_processor] d3d12_video_processor_end_frame - Attempting to re-create ID3D12VideoProcessor "
+                      "input count matches %d inputFmtsMatch: %d outputFmtsMatch %d \n", inputCountMatches, inputFmtsMatch, outputFmtMatches);
+        
+        DXGI_COLOR_SPACE_TYPE InputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
+        DXGI_FORMAT OutputFormat = curOutputTexFmt;
+        DXGI_COLOR_SPACE_TYPE OutputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
+        
+        std::vector<DXGI_FORMAT> InputFormats;
+        for(D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS1 curInput : pD3D12Proc->m_ProcessInputs)
+        {
+            InputFormats.push_back(GetDesc(curInput.InputStream[0].pTexture2D).Format);
+        }
+
+        if(!d3d12_video_processor_check_caps_and_create_processor(pD3D12Proc, InputFormats, InputColorSpace, OutputFormat, OutputColorSpace))
+        {
+            debug_printf("[d3d12_video_processor] d3d12_video_processor_end_frame - Failure when "
+                      " trying to re-create the ID3D12VideoProcessor for current batch streams configuration\n");
+            assert(false);
+        }      
+    }
+
+    // Schedule barrier transitions
+    std::vector<D3D12_RESOURCE_BARRIER> barrier_transitions;
+    barrier_transitions.push_back(CD3DX12_RESOURCE_BARRIER::Transition(
+                                pD3D12Proc->m_OutputArguments.OutputStream[0].pTexture2D,
+                                D3D12_RESOURCE_STATE_COMMON,
+                                D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE));
+
+    for(D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS1 curInput : pD3D12Proc->m_ProcessInputs)
+        barrier_transitions.push_back(CD3DX12_RESOURCE_BARRIER::Transition(
+                                    curInput.InputStream[0].pTexture2D,
+                                    D3D12_RESOURCE_STATE_COMMON,
+                                    D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ));
+    
+    pD3D12Proc->m_spCommandList->ResourceBarrier(static_cast<uint32_t>(barrier_transitions.size()), barrier_transitions.data());
+
+    // Schedule process operation
+
+    pD3D12Proc->m_spCommandList->ProcessFrames1(pD3D12Proc->m_spVideoProcessor.Get(), &pD3D12Proc->m_OutputArguments, pD3D12Proc->m_ProcessInputs.size(), pD3D12Proc->m_ProcessInputs.data());
+
+    // Schedule reverse (back to common) transitions before command list closes for current frame
+
+    for (auto &BarrierDesc : barrier_transitions)
+        std::swap(BarrierDesc.Transition.StateBefore, BarrierDesc.Transition.StateAfter);
+
+    pD3D12Proc->m_spCommandList->ResourceBarrier(static_cast<uint32_t>(barrier_transitions.size()), barrier_transitions.data());
+}
+
+void
+d3d12_video_processor_process_frame(struct pipe_video_codec *codec,
+                        struct pipe_video_buffer *input_texture,
+                        const struct pipe_vpp_desc *process_properties)
+{
+    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
+
+    // Get the underlying resources from the pipe_video_buffers
+    struct d3d12_video_buffer *pInputVideoBuffer = (struct d3d12_video_buffer *) input_texture;
+
+    // Make the resources permanently resident for video use
+    d3d12_promote_to_permanent_residency(pD3D12Proc->m_pD3D12Screen, pInputVideoBuffer->texture);
+
+    ID3D12Resource *pSrcD3D12Res = d3d12_resource_resource(pInputVideoBuffer->texture);
+
+    // y0 = top
+    // x0 = left
+    // x1 = right
+    // y1 = bottom
+
+    debug_printf("d3d12_video_processor_process_frame: Adding Input ID3D12Resource: %p to scene (Output target %p)\n", pSrcD3D12Res, pD3D12Proc->m_OutputArguments.OutputStream[0].pTexture2D);
+    debug_printf("d3d12_video_processor_process_frame: Input box: top: %d left: %d right: %d bottom: %d\n", process_properties->src_region.y0, process_properties->src_region.x0, process_properties->src_region.x1, process_properties->src_region.y1);
+    debug_printf("d3d12_video_processor_process_frame: Output box: top: %d left: %d right: %d bottom: %d\n", process_properties->dst_region.y0, process_properties->dst_region.x0, process_properties->dst_region.x1, process_properties->dst_region.y1);
+    debug_printf("d3d12_video_processor_process_frame: Requested alpha blend mode %d global alpha: %f \n", process_properties->blend.mode, process_properties->blend.global_alpha);
+
+    // Setup process frame arguments for current input texture.
+
+    unsigned curInputStreamIndex = pD3D12Proc->m_ProcessInputs.size();
+    D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS1 InputArguments = {
+        {
+        { // D3D12_VIDEO_PROCESS_INPUT_STREAM InputStream[0];
+                pSrcD3D12Res, // ID3D12Resource *pTexture2D;
+                0, // UINT Subresource
+                {//D3D12_VIDEO_PROCESS_REFERENCE_SET ReferenceSet;
+                    0, //UINT NumPastFrames;
+                    NULL, //ID3D12Resource **ppPastFrames;
+                    NULL, // UINT *pPastSubresources;
+                    0, //UINT NumFutureFrames;
+                    NULL, //ID3D12Resource **ppFutureFrames;
+                    NULL //UINT *pFutureSubresources;
+                }
+        },
+        { // D3D12_VIDEO_PROCESS_INPUT_STREAM InputStream[1];
+                NULL, //ID3D12Resource *pTexture2D;
+                0, //UINT Subresource;
+                {//D3D12_VIDEO_PROCESS_REFERENCE_SET ReferenceSet;
+                    0, //UINT NumPastFrames;
+                    NULL, //ID3D12Resource **ppPastFrames;
+                    NULL, // UINT *pPastSubresources;
+                    0, //UINT NumFutureFrames;
+                    NULL, //ID3D12Resource **ppFutureFrames;
+                    NULL //UINT *pFutureSubresources;
+                }
+        }
+        },
+        { // D3D12_VIDEO_PROCESS_TRANSFORM Transform;
+            // y0 = top
+            // x0 = left
+            // x1 = right
+            // y1 = bottom
+            // typedef struct _RECT
+            // {
+            //     int left;
+            //     int top;
+            //     int right;
+            //     int bottom;
+            // } RECT;
+            { process_properties->src_region.x0/*left*/, process_properties->src_region.y0/*top*/, process_properties->src_region.x1/*right*/, process_properties->src_region.y1/*bottom*/ },
+            { process_properties->dst_region.x0/*left*/, process_properties->dst_region.y0/*top*/, process_properties->dst_region.x1/*right*/, process_properties->dst_region.y1/*bottom*/ }, // D3D12_RECT DestinationRectangle;
+            pD3D12Proc->m_inputStreamDescs[curInputStreamIndex].EnableOrientation ? d3d12_video_processor_convert_pipe_rotation(process_properties->orientation) : D3D12_VIDEO_PROCESS_ORIENTATION_DEFAULT, // D3D12_VIDEO_PROCESS_ORIENTATION Orientation;
+        },
+        D3D12_VIDEO_PROCESS_INPUT_STREAM_FLAG_NONE,
+        { // D3D12_VIDEO_PROCESS_INPUT_STREAM_RATE RateInfo;
+            0,
+            0,
+        },
+        // INT                                    FilterLevels[32];
+        {
+            0, // Trailing zeroes on the rest
+        },
+        //D3D12_VIDEO_PROCESS_ALPHA_BLENDING;
+        { 
+            (process_properties->blend.mode == PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA),
+            process_properties->blend.global_alpha
+        },
+        // D3D12_VIDEO_FIELD_TYPE FieldType
+        D3D12_VIDEO_FIELD_TYPE_NONE,
+    };
+
+    debug_printf("ProcessFrame InArgs Orientation %d \n\tSrc top: %d left: %d right: %d bottom: %d\n\tDst top: %d left: %d right: %d bottom: %d\n", InputArguments.Transform.Orientation, 
+        InputArguments.Transform.SourceRectangle.top, InputArguments.Transform.SourceRectangle.left, InputArguments.Transform.SourceRectangle.right, InputArguments.Transform.SourceRectangle.bottom,
+        InputArguments.Transform.DestinationRectangle.top, InputArguments.Transform.DestinationRectangle.left, InputArguments.Transform.DestinationRectangle.right, InputArguments.Transform.DestinationRectangle.bottom);
+
+    pD3D12Proc->m_ProcessInputs.push_back(InputArguments);    
+    
+    ///
+    /// Flush work to the GPU and blocking wait until GPU finishes
+    ///
+    pD3D12Proc->m_needsGPUFlush = true;
+}
+
+void
+d3d12_video_processor_destroy(struct pipe_video_codec * codec)
+{
+    if (codec == nullptr) {
+        return;
+    }
+    d3d12_video_processor_flush(codec);   // Flush pending work before destroying.
+
+    // Call dtor to make ComPtr work
+    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
+    delete pD3D12Proc;
+}
+
+void
+d3d12_video_processor_flush(struct pipe_video_codec * codec)
+{
+    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
+    assert(pD3D12Proc);
+    assert(pD3D12Proc->m_spD3D12VideoDevice);
+    assert(pD3D12Proc->m_spCommandQueue);
+
+    // Flush buffer_subdata batch and Wait the m_spCommandQueue for GPU upload completion
+    // before executing the current batch below. Input objects coming from the pipe_context (ie. input texture) must be fully finished working with before processor can read them.
+    struct pipe_fence_handle *completion_fence = NULL;
+    debug_printf("[d3d12_video_processor] d3d12_video_processor_flush - Flushing pD3D12Proc->m_pD3D12Context->base. and GPU sync between Video/Context queues before flushing Video Process Queue.\n");
+    pD3D12Proc->m_pD3D12Context->base.flush(&pD3D12Proc->m_pD3D12Context->base, &completion_fence, PIPE_FLUSH_ASYNC | PIPE_FLUSH_HINT_FINISH);
+    assert(completion_fence);
+    struct d3d12_fence *casted_completion_fence = d3d12_fence(completion_fence);
+    pD3D12Proc->m_spCommandQueue->Wait(casted_completion_fence->cmdqueue_fence, casted_completion_fence->value);   
+
+    debug_printf("[d3d12_video_processor] d3d12_video_processor_flush started. Will flush video queue work and CPU wait on "
+                    "fenceValue: %d\n",
+                    pD3D12Proc->m_fenceValue);
+
+    if (!pD3D12Proc->m_needsGPUFlush) {
+        debug_printf("[d3d12_video_processor] d3d12_video_processor_flush started. Nothing to flush, all up to date.\n");
+    } else {
+        HRESULT hr = pD3D12Proc->m_pD3D12Screen->dev->GetDeviceRemovedReason();
+        if (hr != S_OK) {
+            debug_printf("[d3d12_video_processor] d3d12_video_processor_flush"
+                            " - D3D12Device was removed BEFORE commandlist "
+                            "execution with HR %x.\n",
+                            hr);
+            goto flush_fail;
+        }
+
+        // Close and execute command list and wait for idle on CPU blocking
+        // this method before resetting list and allocator for next submission.
+
+        if (pD3D12Proc->m_transitionsBeforeCloseCmdList.size() > 0) {
+            pD3D12Proc->m_spCommandList->ResourceBarrier(pD3D12Proc->m_transitionsBeforeCloseCmdList.size(),
+                                                            pD3D12Proc->m_transitionsBeforeCloseCmdList.data());
+            pD3D12Proc->m_transitionsBeforeCloseCmdList.clear();
+        }
+
+        hr = pD3D12Proc->m_spCommandList->Close();
+        if (FAILED(hr)) {
+            debug_printf("[d3d12_video_processor] d3d12_video_processor_flush - Can't close command list with HR %x\n", hr);
+            goto flush_fail;
+        }
+
+        ID3D12CommandList *ppCommandLists[1] = { pD3D12Proc->m_spCommandList.Get() };
+        pD3D12Proc->m_spCommandQueue->ExecuteCommandLists(1, ppCommandLists);
+        pD3D12Proc->m_spCommandQueue->Signal(pD3D12Proc->m_spFence.Get(), pD3D12Proc->m_fenceValue);
+        pD3D12Proc->m_spFence->SetEventOnCompletion(pD3D12Proc->m_fenceValue, nullptr);
+        debug_printf("[d3d12_video_processor] d3d12_video_processor_flush - ExecuteCommandLists finished on signal with "
+                        "fenceValue: %d\n",
+                        pD3D12Proc->m_fenceValue);
+
+        hr = pD3D12Proc->m_spCommandAllocator->Reset();
+        if (FAILED(hr)) {
+            debug_printf(
+                "[d3d12_video_processor] d3d12_video_processor_flush - resetting ID3D12CommandAllocator failed with HR %x\n",
+                hr);
+            goto flush_fail;
+        }
+
+        hr = pD3D12Proc->m_spCommandList->Reset(pD3D12Proc->m_spCommandAllocator.Get());
+        if (FAILED(hr)) {
+            debug_printf(
+                "[d3d12_video_processor] d3d12_video_processor_flush - resetting ID3D12GraphicsCommandList failed with HR %x\n",
+                hr);
+            goto flush_fail;
+        }
+
+        // Validate device was not removed
+        hr = pD3D12Proc->m_pD3D12Screen->dev->GetDeviceRemovedReason();
+        if (hr != S_OK) {
+            debug_printf("[d3d12_video_processor] d3d12_video_processor_flush"
+                            " - D3D12Device was removed AFTER commandlist "
+                            "execution with HR %x, but wasn't before.\n",
+                            hr);
+            goto flush_fail;
+        }
+
+        debug_printf(
+            "[d3d12_video_processor] d3d12_video_processor_flush - GPU signaled execution finalized for fenceValue: %d\n",
+            pD3D12Proc->m_fenceValue);
+
+        pD3D12Proc->m_fenceValue++;
+        pD3D12Proc->m_needsGPUFlush = false;
+    }
+    pD3D12Proc->m_ProcessInputs.clear();
+    // Free the fence after completion finished
+    if(completion_fence)
+        pD3D12Proc->m_pD3D12Screen->base.fence_reference(&pD3D12Proc->m_pD3D12Screen->base, &completion_fence, NULL);
+
+    return;
+
+flush_fail:
+    debug_printf("[d3d12_video_processor] d3d12_video_processor_flush failed for fenceValue: %d\n", pD3D12Proc->m_fenceValue);
+    assert(false);
+}
+
+struct pipe_video_codec *
+d3d12_video_processor_create(struct pipe_context *context, const struct pipe_video_codec *codec)
+{
+   ///
+   /// Initialize d3d12_video_processor
+   ///
+
+   // Not using new doesn't call ctor and the initializations in the class declaration are lost
+   struct d3d12_video_processor *pD3D12Proc = new d3d12_video_processor;
+
+   pD3D12Proc->base = *codec;
+
+   pD3D12Proc->base.context = context;
+   pD3D12Proc->base.width = codec->width;
+   pD3D12Proc->base.height = codec->height;
+   pD3D12Proc->base.destroy = d3d12_video_processor_destroy;
+   pD3D12Proc->base.begin_frame = d3d12_video_processor_begin_frame;
+   pD3D12Proc->base.process_frame = d3d12_video_processor_process_frame;
+   pD3D12Proc->base.end_frame = d3d12_video_processor_end_frame;
+   pD3D12Proc->base.flush = d3d12_video_processor_flush;
+
+   ///
+
+   ///
+   /// Try initializing D3D12 Video device and check for device caps
+   ///
+
+   struct d3d12_context *pD3D12Ctx = (struct d3d12_context *) context;
+   pD3D12Proc->m_pD3D12Context = pD3D12Ctx;
+   pD3D12Proc->m_pD3D12Screen = d3d12_screen(pD3D12Ctx->base.screen);
+
+    // Assume defaults for now, can re-create if necessary when d3d12_video_processor_end_frame kicks off the processing
+    DXGI_COLOR_SPACE_TYPE InputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
+    std::vector<DXGI_FORMAT> InputFormats = { DXGI_FORMAT_NV12 };
+    DXGI_FORMAT OutputFormat = DXGI_FORMAT_NV12;
+    DXGI_COLOR_SPACE_TYPE OutputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
+
+   ///
+   /// Create processor objects
+   ///
+   if (FAILED(pD3D12Proc->m_pD3D12Screen->dev->QueryInterface(
+          IID_PPV_ARGS(pD3D12Proc->m_spD3D12VideoDevice.GetAddressOf())))) {
+      debug_printf("[d3d12_video_processor] d3d12_video_create_processor - D3D12 Device has no Video support\n");
+      goto failed;
+   }    
+
+   if (!d3d12_video_processor_check_caps_and_create_processor(pD3D12Proc, InputFormats, InputColorSpace, OutputFormat, OutputColorSpace)) {
+      debug_printf("[d3d12_video_processor] d3d12_video_create_processor - Failure on "
+                      "d3d12_video_processor_check_caps_and_create_processor\n");
+      goto failed;
+   }
+
+   if (!d3d12_video_processor_create_command_objects(pD3D12Proc)) {
+      debug_printf(
+         "[d3d12_video_processor] d3d12_video_create_processor - Failure on d3d12_video_processor_create_command_objects\n");
+      goto failed;
+   }
+
+    debug_printf("[d3d12_video_processor] d3d12_video_create_processor - Created successfully!\n");
+
+   return &pD3D12Proc->base;
+
+failed:
+   if (pD3D12Proc != nullptr) {
+      d3d12_video_processor_destroy(&pD3D12Proc->base);
+   }
+
+   return nullptr;
+}
+
+bool
+d3d12_video_processor_check_caps_and_create_processor(struct d3d12_video_processor *pD3D12Proc,
+                                                        std::vector<DXGI_FORMAT> InputFormats,
+                                                        DXGI_COLOR_SPACE_TYPE InputColorSpace,
+                                                        DXGI_FORMAT OutputFormat,
+                                                        DXGI_COLOR_SPACE_TYPE OutputColorSpace)
+{
+    HRESULT hr = S_OK;
+
+    D3D12_VIDEO_FIELD_TYPE FieldType = D3D12_VIDEO_FIELD_TYPE_NONE;
+    D3D12_VIDEO_FRAME_STEREO_FORMAT StereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE;
+    DXGI_RATIONAL FrameRate = { 30, 1 };
+    DXGI_RATIONAL AspectRatio = { 1, 1 };
+
+    struct ResolStruct {
+        uint Width;
+        uint Height;
+    };
+
+    ResolStruct resolutionsList[] = {
+        { 8192, 8192 },   // 8k
+        { 8192, 4320 },   // 8k - alternative
+        { 7680, 4800 },   // 8k - alternative
+        { 7680, 4320 },   // 8k - alternative
+        { 4096, 2304 },   // 2160p (4K)
+        { 4096, 2160 },   // 2160p (4K) - alternative
+        { 2560, 1440 },   // 1440p
+        { 1920, 1200 },   // 1200p
+        { 1920, 1080 },   // 1080p
+        { 1280, 720 },    // 720p
+        { 800, 600 },
+    };
+
+    pD3D12Proc->m_SupportCaps = 
+    {
+        0, // NodeIndex
+        { resolutionsList[0].Width, resolutionsList[0].Height, { InputFormats[0], InputColorSpace } },
+        FieldType,
+        StereoFormat,
+        FrameRate,
+        { OutputFormat, OutputColorSpace },
+        StereoFormat,
+        FrameRate,
+    };
+
+    uint32_t idxResol = 0;
+    bool bSupportsAny = false;
+    while ((idxResol < ARRAY_SIZE(resolutionsList)) && !bSupportsAny) {
+        pD3D12Proc->m_SupportCaps.InputSample.Width = resolutionsList[idxResol].Width;
+        pD3D12Proc->m_SupportCaps.InputSample.Height = resolutionsList[idxResol].Height;
+        if (SUCCEEDED(pD3D12Proc->m_spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_PROCESS_SUPPORT, &pD3D12Proc->m_SupportCaps, sizeof(pD3D12Proc->m_SupportCaps)))) {
+            bSupportsAny = ((pD3D12Proc->m_SupportCaps.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) != 0);
+        }
+        idxResol++;
+    }
+
+    if ((pD3D12Proc->m_SupportCaps.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) != D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED)
+    {
+        if((pD3D12Proc->m_SupportCaps.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) != D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) {
+        debug_printf("[d3d12_video_processor] d3d12_video_processor_check_caps_and_create_processor - D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED not returned by driver. "
+                            "failed with SupportFlags %x\n",
+                            pD3D12Proc->m_SupportCaps.SupportFlags);
+        }
+    }
+
+    D3D12_VIDEO_PROCESS_FILTER_FLAGS enabledFilterFlags = D3D12_VIDEO_PROCESS_FILTER_FLAG_NONE;
+
+    bool enableOrientation = (
+        ((pD3D12Proc->m_SupportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ROTATION) != 0)
+        || ((pD3D12Proc->m_SupportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_FLIP) != 0)
+    );
+
+    D3D12_VIDEO_PROCESS_INPUT_STREAM_DESC inputStreamDesc = {
+        InputFormats[0],
+        InputColorSpace,
+        AspectRatio,                            // SourceAspectRatio;
+        AspectRatio,                            // DestinationAspectRatio;
+        FrameRate,                              // FrameRate
+        pD3D12Proc->m_SupportCaps.ScaleSupport.OutputSizeRange, // SourceSizeRange
+        pD3D12Proc->m_SupportCaps.ScaleSupport.OutputSizeRange, // DestinationSizeRange
+        enableOrientation,
+        enabledFilterFlags,
+        StereoFormat,
+        FieldType,
+        D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_NONE,
+        ((pD3D12Proc->m_SupportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_BLENDING) != 0)
+        && ((pD3D12Proc->m_SupportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_FILL) != 0), // EnableAlphaBlending
+        {},                                     // LumaKey
+        0,                                      // NumPastFrames
+        0,                                      // NumFutureFrames
+        FALSE                                   // EnableAutoProcessing
+    };
+
+    D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC outputStreamDesc =
+    {
+        pD3D12Proc->m_SupportCaps.OutputFormat.Format,
+        OutputColorSpace,
+        D3D12_VIDEO_PROCESS_ALPHA_FILL_MODE_OPAQUE, // AlphaFillMode
+        0u,                                         // AlphaFillModeSourceStreamIndex
+        {0, 0, 0, 0},                               // BackgroundColor
+        FrameRate,                                  // FrameRate
+        FALSE                                       // EnableStereo
+    };
+    
+    // gets the required past/future frames for VP creation
+    {
+        D3D12_FEATURE_DATA_VIDEO_PROCESS_REFERENCE_INFO referenceInfo = {};
+        referenceInfo.NodeIndex = 0;
+        D3D12_VIDEO_PROCESS_FEATURE_FLAGS featureFlags = D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
+        featureFlags |= outputStreamDesc.AlphaFillMode ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_FILL : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
+        featureFlags |= inputStreamDesc.LumaKey.Enable ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_LUMA_KEY : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
+        featureFlags |= (inputStreamDesc.StereoFormat != D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE || outputStreamDesc.EnableStereo) ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_STEREO : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
+        featureFlags |= inputStreamDesc.EnableOrientation ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_ROTATION | D3D12_VIDEO_PROCESS_FEATURE_FLAG_FLIP : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
+        featureFlags |= inputStreamDesc.EnableAlphaBlending ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_BLENDING : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
+
+        referenceInfo.DeinterlaceMode = inputStreamDesc.DeinterlaceMode;
+        referenceInfo.Filters = inputStreamDesc.FilterFlags;
+        referenceInfo.FeatureSupport = featureFlags;
+        referenceInfo.InputFrameRate = inputStreamDesc.FrameRate;
+        referenceInfo.OutputFrameRate = outputStreamDesc.FrameRate;
+        referenceInfo.EnableAutoProcessing = inputStreamDesc.EnableAutoProcessing;
+
+        hr = pD3D12Proc->m_spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_PROCESS_REFERENCE_INFO, &referenceInfo, sizeof(referenceInfo));
+        if (FAILED(hr)) {
+        debug_printf("[d3d12_video_processor] d3d12_video_processor_check_caps_and_create_processor - CheckFeatureSupport "
+                        "failed with HR %x\n",
+                        hr);
+        return false;
+        }
+
+        inputStreamDesc.NumPastFrames = referenceInfo.PastFrames;
+        inputStreamDesc.NumFutureFrames = referenceInfo.FutureFrames;
+    }
+
+    pD3D12Proc->m_outputStreamDesc = outputStreamDesc;
+    
+    debug_printf("[d3d12_video_processor]\t Creating Video Processor\n");
+    debug_printf("[d3d12_video_processor]\t NumInputs: %d\n", (int) InputFormats.size());
+
+    pD3D12Proc->m_inputStreamDescs.clear();
+    for (unsigned i = 0; i < InputFormats.size(); i++)
+    {
+        inputStreamDesc.Format = InputFormats[i];
+        pD3D12Proc->m_inputStreamDescs.push_back(inputStreamDesc);
+        debug_printf("[d3d12_video_processor]\t Input Stream #%d Format: %d\n", i, inputStreamDesc.Format);
+    }
+    debug_printf("[d3d12_video_processor]\t Output Stream Format: %d\n", pD3D12Proc->m_outputStreamDesc.Format);
+
+    hr = pD3D12Proc->m_spD3D12VideoDevice->CreateVideoProcessor(pD3D12Proc->m_NodeMask,
+                                                            &pD3D12Proc->m_outputStreamDesc,
+                                                            pD3D12Proc->m_inputStreamDescs.size(),
+                                                            pD3D12Proc->m_inputStreamDescs.data(),
+                                                            IID_PPV_ARGS(pD3D12Proc->m_spVideoProcessor.GetAddressOf()));
+    if (FAILED(hr)) {
+        debug_printf("[d3d12_video_processor] d3d12_video_processor_check_caps_and_create_processor - CreateVideoProcessor "
+                    "failed with HR %x\n",
+                    hr);
+        return false;
+    }
+
+   return true;
+}
+
+bool
+d3d12_video_processor_create_command_objects(struct d3d12_video_processor *pD3D12Proc)
+{
+    assert(pD3D12Proc->m_spD3D12VideoDevice);
+
+    D3D12_COMMAND_QUEUE_DESC commandQueueDesc = { D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS };
+    HRESULT hr = pD3D12Proc->m_pD3D12Screen->dev->CreateCommandQueue(
+                &commandQueueDesc,
+                IID_PPV_ARGS(pD3D12Proc->m_spCommandQueue.GetAddressOf()));
+
+    if (FAILED(hr)) {
+        debug_printf("[d3d12_video_processor] d3d12_video_processor_create_command_objects - Call to CreateCommandQueue "
+                        "failed with HR %x\n",
+                        hr);
+        return false;
+    }
+
+    hr = pD3D12Proc->m_pD3D12Screen->dev->CreateFence(0,
+         D3D12_FENCE_FLAG_NONE,
+         IID_PPV_ARGS(&pD3D12Proc->m_spFence));
+
+    if (FAILED(hr)) {
+        debug_printf(
+            "[d3d12_video_processor] d3d12_video_processor_create_command_objects - Call to CreateFence failed with HR %x\n",
+            hr);
+        return false;
+    }
+
+    hr = pD3D12Proc->m_pD3D12Screen->dev->CreateCommandAllocator(
+        D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
+        IID_PPV_ARGS(pD3D12Proc->m_spCommandAllocator.GetAddressOf()));
+
+    if (FAILED(hr)) {
+        debug_printf("[d3d12_video_processor] d3d12_video_processor_create_command_objects - Call to "
+                        "CreateCommandAllocator failed with HR %x\n",
+                        hr);
+        return false;
+    }
+
+    hr = pD3D12Proc->m_pD3D12Screen->dev->CreateCommandList(0,
+        D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
+        pD3D12Proc->m_spCommandAllocator.Get(),
+        nullptr,
+        IID_PPV_ARGS(pD3D12Proc->m_spCommandList.GetAddressOf()));
+
+    if (FAILED(hr)) {
+        debug_printf("[d3d12_video_processor] d3d12_video_processor_create_command_objects - Call to CreateCommandList "
+                        "failed with HR %x\n",
+                        hr);
+        return false;
+    }
+
+    return true;
+}
+
+D3D12_VIDEO_PROCESS_ORIENTATION
+d3d12_video_processor_convert_pipe_rotation(enum pipe_video_vpp_orientation orientation_flags)
+{
+    D3D12_VIDEO_PROCESS_ORIENTATION result = D3D12_VIDEO_PROCESS_ORIENTATION_DEFAULT;
+
+    if(orientation_flags & PIPE_VIDEO_VPP_ROTATION_90)
+    {
+        result = (orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) ? D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_90_FLIP_HORIZONTAL : D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_90;
+        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: %s\n", (orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) ? "D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_90_FLIP_HORIZONTAL" : "D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_90");
+    }
+    else if(orientation_flags & PIPE_VIDEO_VPP_ROTATION_180)
+    {
+        result = D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_180;
+        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_180\n");
+    }
+    else if(orientation_flags & PIPE_VIDEO_VPP_ROTATION_270)
+    {
+        result = (orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) ? D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_270_FLIP_HORIZONTAL : D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_270;
+        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: %s\n", (orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) ? "D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_270_FLIP_HORIZONTAL" : "D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_270");
+    }
+    else if(orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL)
+    {
+        result = D3D12_VIDEO_PROCESS_ORIENTATION_FLIP_HORIZONTAL;
+        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: D3D12_VIDEO_PROCESS_ORIENTATION_FLIP_HORIZONTAL\n");
+    }
+    else if(orientation_flags & PIPE_VIDEO_VPP_FLIP_VERTICAL)
+    {
+        result = D3D12_VIDEO_PROCESS_ORIENTATION_FLIP_VERTICAL;
+        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: D3D12_VIDEO_PROCESS_ORIENTATION_FLIP_VERTICAL\n");
+    }
+
+    return result;
+}
diff --git a/src/gallium/drivers/d3d12/d3d12_video_proc.h b/src/gallium/drivers/d3d12/d3d12_video_proc.h
new file mode 100644
index 00000000000..edef7fa203f
--- /dev/null
+++ b/src/gallium/drivers/d3d12/d3d12_video_proc.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright © Microsoft Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef D3D12_VIDEO_PROC_H
+#define D3D12_VIDEO_PROC_H
+#include "d3d12_video_types.h"
+
+
+///
+/// Pipe video interface starts
+///
+
+/**
+ * creates a video processor
+ */
+struct pipe_video_codec *
+d3d12_video_create_processor(struct pipe_context *context, const struct pipe_video_codec *templ);
+
+/**
+ * destroy this video processor
+ */
+void
+d3d12_video_processor_destroy(struct pipe_video_codec *codec);
+
+/**
+ * start processing of a new frame
+ */
+void
+d3d12_video_processor_begin_frame(struct pipe_video_codec * codec,
+                                struct pipe_video_buffer *target,
+                                struct pipe_picture_desc *picture);
+
+/**
+ * Perform post-process effect
+ */
+void
+d3d12_video_processor_process_frame(struct pipe_video_codec *codec,
+                        struct pipe_video_buffer *input_texture,
+                        const struct pipe_vpp_desc *process_properties);
+/**
+ * end processing of the current frame
+ */
+void
+d3d12_video_processor_end_frame(struct pipe_video_codec * codec,
+                              struct pipe_video_buffer *target,
+                              struct pipe_picture_desc *picture);
+/**
+
+ * flush any outstanding command buffers to the hardware
+ * should be called before a video_buffer is acessed by the gallium frontend again
+ */
+void
+d3d12_video_processor_flush(struct pipe_video_codec *codec);
+
+///
+/// Pipe video interface ends
+///
+
+///
+/// d3d12_video_processor functions starts
+///
+
+struct d3d12_video_processor
+{
+   struct pipe_video_codec base;
+   struct d3d12_screen  *m_pD3D12Screen;
+   struct d3d12_context *m_pD3D12Context;
+
+   ///
+   /// D3D12 objects and context info
+   ///
+
+   const uint m_NodeMask  = 0u;
+   const uint m_NodeIndex = 0u;
+
+   ComPtr<ID3D12Fence> m_spFence;
+   uint                m_fenceValue = 1u;
+
+   ComPtr<ID3D12VideoDevice>             m_spD3D12VideoDevice;
+   
+   D3D12_FEATURE_DATA_VIDEO_PROCESS_SUPPORT           m_SupportCaps;
+   D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC             m_outputStreamDesc;
+   std::vector<D3D12_VIDEO_PROCESS_INPUT_STREAM_DESC> m_inputStreamDescs;
+   ComPtr<ID3D12VideoProcessor1>                      m_spVideoProcessor;
+   ComPtr<ID3D12CommandQueue>                         m_spCommandQueue;
+   ComPtr<ID3D12CommandAllocator>                     m_spCommandAllocator;
+   ComPtr<ID3D12VideoProcessCommandList1>             m_spCommandList;
+
+   std::vector<D3D12_RESOURCE_BARRIER> m_transitionsBeforeCloseCmdList;
+
+   // Current state between begin and end frame
+   D3D12_VIDEO_PROCESS_OUTPUT_STREAM_ARGUMENTS m_OutputArguments;
+   std::vector<D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS1> m_ProcessInputs;
+
+   // Indicates if GPU commands have not been flushed and are pending.
+   bool m_needsGPUFlush = false;
+};
+
+struct pipe_video_codec *
+d3d12_video_processor_create(struct pipe_context *context, const struct pipe_video_codec *codec);
+
+bool
+d3d12_video_processor_check_caps_and_create_processor(struct d3d12_video_processor *pD3D12Proc,
+                                                        std::vector<DXGI_FORMAT> InputFormats,
+                                                        DXGI_COLOR_SPACE_TYPE InputColorSpace,
+                                                        DXGI_FORMAT OutputFormat,
+                                                        DXGI_COLOR_SPACE_TYPE OutputColorSpace);
+
+bool
+d3d12_video_processor_create_command_objects(struct d3d12_video_processor *pD3D12Proc);
+
+D3D12_VIDEO_PROCESS_ORIENTATION
+d3d12_video_processor_convert_pipe_rotation(enum pipe_video_vpp_orientation orientation);
+
+///
+/// d3d12_video_processor functions ends
+///
+
+#endif
diff --git a/src/gallium/drivers/d3d12/meson.build b/src/gallium/drivers/d3d12/meson.build
index a0de2cb1866..5dfd44924b7 100644
--- a/src/gallium/drivers/d3d12/meson.build
+++ b/src/gallium/drivers/d3d12/meson.build
@@ -62,6 +62,7 @@ if with_gallium_d3d12_video
     'd3d12_video_texture_array_dpb_manager.cpp',
     'd3d12_video_array_of_textures_dpb_manager.cpp',
     'd3d12_video_screen.cpp',
+    'd3d12_video_proc.cpp',
   ]
 endif
 



More information about the mesa-commit mailing list