VirtualBox

Ignore:
Timestamp:
May 19, 2023 7:35:22 AM (21 months ago)
Author:
vboxsync
Message:

WDDM: UpdateSubresourceUP uses a pool of staging buffers. bugref:9845

Location:
trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/dx
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/dx/VBoxDX.cpp

    r98103 r99855  
    679679    pResource->pKMResource = NULL;
    680680    pResource->uMap = 0;
    681     pResource->pStagingResource = 0;
    682681    RTListInit(&pResource->listSRV);
    683682    RTListInit(&pResource->listRTV);
     
    689688
    690689
    691 bool vboxDXCreateResource(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource,
    692                           const D3D11DDIARG_CREATERESOURCE *pCreateResource)
    693 {
    694     pResource->pKMResource = (PVBOXDXKMRESOURCE)RTMemAllocZ(sizeof(VBOXDXKMRESOURCE));
    695     AssertReturnStmt(pResource->pKMResource, vboxDXDeviceSetError(pDevice, E_OUTOFMEMORY), false);
    696 
     690static HRESULT dxAllocate(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource, D3DKMT_HANDLE *phAllocation)
     691{
    697692    D3DDDI_ALLOCATIONINFO2 ddiAllocationInfo;
    698693    RT_ZERO(ddiAllocationInfo);
     
    716711    HRESULT hr = pDevice->pRTCallbacks->pfnAllocateCb(pDevice->hRTDevice.handle, &ddiAllocate);
    717712    LogFlowFunc((" pfnAllocateCb returned %d, hKMResource 0x%X, hAllocation 0x%X", hr, ddiAllocate.hKMResource, ddiAllocationInfo.hAllocation));
     713
     714    if (SUCCEEDED(hr))
     715        *phAllocation = ddiAllocationInfo.hAllocation;
     716
     717    return hr;
     718}
     719
     720
     721bool vboxDXCreateResource(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource,
     722                          const D3D11DDIARG_CREATERESOURCE *pCreateResource)
     723{
     724    pResource->pKMResource = (PVBOXDXKMRESOURCE)RTMemAllocZ(sizeof(VBOXDXKMRESOURCE));
     725    AssertReturnStmt(pResource->pKMResource, vboxDXDeviceSetError(pDevice, E_OUTOFMEMORY), false);
     726
     727    D3DKMT_HANDLE hAllocation = 0;
     728    HRESULT hr = dxAllocate(pDevice, pResource, &hAllocation);
     729    if (FAILED(hr))
     730    {
     731        /* Might be not enough memory due to temporary staging buffers. */
     732        vboxDXFlush(pDevice, true);
     733        hr = dxAllocate(pDevice, pResource, &hAllocation);
     734    }
    718735    AssertReturnStmt(SUCCEEDED(hr), RTMemFree(pResource->pKMResource); vboxDXDeviceSetError(pDevice, hr), false);
    719736
    720737    pResource->pKMResource->pResource = pResource;
    721     pResource->pKMResource->hAllocation = ddiAllocationInfo.hAllocation;
     738    pResource->pKMResource->hAllocation = hAllocation;
    722739    RTListAppend(&pDevice->listResources, &pResource->pKMResource->nodeResource);
    723740
     
    748765                memset(ddiLock.pData, 0, pResource->AllocationDesc.cbAllocation);
    749766
    750                 D3DKMT_HANDLE hAllocation = vboxDXGetAllocation(pResource);
     767                hAllocation = vboxDXGetAllocation(pResource);
    751768
    752769                D3DDDICB_UNLOCK ddiUnlock;
     
    787804    pResource->cSubresources = pDesc->surfaceInfo.numMipLevels * pDesc->surfaceInfo.arraySize;
    788805    pResource->uMap             = 0;
    789     pResource->pStagingResource = 0;
    790806    RTListInit(&pResource->listSRV);
    791807    RTListInit(&pResource->listRTV);
     
    800816
    801817
    802 static bool dxDestroyResource(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource)
    803 {
     818/* Destroy a resource created by the system (via DDI). Primary resources are freed immediately.
     819 * Other resources are moved to the deferred destruction queue (pDevice->listDestroyedResources).
     820 * The 'pResource' structure will be deleted by D3D runtime in any case.
     821 */
     822void vboxDXDestroyResource(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource)
     823{
     824    /* "the driver must process its deferred-destruction queue during calls to its Flush(D3D10) function"
     825     * "Primary destruction cannot be deferred by the Direct3D runtime, and the driver must call
     826     * the pfnDeallocateCb function appropriately within a call to the driver's DestroyResource(D3D10) function."
     827     */
     828
    804829    Assert(RTListIsEmpty(&pResource->listSRV));
    805830    Assert(RTListIsEmpty(&pResource->listRTV));
     
    807832    Assert(RTListIsEmpty(&pResource->listUAV));
    808833
    809     if (pResource->pStagingResource)
    810     {
    811         dxDestroyResource(pDevice, pResource->pStagingResource);
    812         RTMemFree(pResource->pStagingResource);
    813         pResource->pStagingResource = NULL;
    814     }
    815 
    816     D3DKMT_HANDLE const hAllocation = pResource->pKMResource->hAllocation;
    817     RTMemFree(pResource->pKMResource);
    818 
    819     if (!RT_BOOL(pResource->AllocationDesc.resourceInfo.MiscFlags & D3D10_DDI_RESOURCE_MISC_SHARED))
    820     {
     834    /* Remove from the list of active resources. */
     835    RTListNodeRemove(&pResource->pKMResource->nodeResource);
     836
     837    if (pResource->AllocationDesc.fPrimary)
     838    {
     839        /* Delete immediately. */
    821840        D3DDDICB_DEALLOCATE ddiDeallocate;
    822841        RT_ZERO(ddiDeallocate);
    823         ddiDeallocate.hResource      = NULL;
     842        //ddiDeallocate.hResource      = NULL;
    824843        ddiDeallocate.NumAllocations = 1;
    825         ddiDeallocate.HandleList     = &hAllocation;
     844        ddiDeallocate.HandleList     = &pResource->pKMResource->hAllocation;
    826845
    827846        HRESULT hr = pDevice->pRTCallbacks->pfnDeallocateCb(pDevice->hRTDevice.handle, &ddiDeallocate);
    828847        LogFlowFunc(("pfnDeallocateCb returned %d", hr));
    829         AssertReturnStmt(SUCCEEDED(hr), vboxDXDeviceSetError(pDevice, hr), false);
    830     }
    831 
    832     return true;
    833 }
    834 
    835 
    836 bool vboxDXDestroyResource(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource)
    837 {
    838     /* "the driver must process its deferred-destruction queue during calls to its Flush(D3D10) function"
    839      * "Primary destruction cannot be deferred by the Direct3D runtime, and the driver must call
    840      * the pfnDeallocateCb function appropriately within a call to the driver's DestroyResource(D3D10) function."
    841      */
    842 
    843     if (pResource->pStagingResource)
    844     {
    845         vboxDXDestroyResource(pDevice, pResource->pStagingResource);
    846         RTMemFree(pResource->pStagingResource);
    847         pResource->pStagingResource = NULL;
    848     }
    849 
    850     /* Remove from the list of active resources. */
    851     RTListNodeRemove(&pResource->pKMResource->nodeResource);
    852 
    853     if (pResource->AllocationDesc.fPrimary)
    854         return dxDestroyResource(pDevice, pResource);
    855 
    856     if (!RT_BOOL(pResource->AllocationDesc.resourceInfo.MiscFlags & D3D10_DDI_RESOURCE_MISC_SHARED))
    857     {
    858         /* Set the resource for deferred destruction. */
    859         pResource->pKMResource->pResource = NULL;
    860         RTListAppend(&pDevice->listDestroyedResources, &pResource->pKMResource->nodeResource);
     848        AssertStmt(SUCCEEDED(hr), vboxDXDeviceSetError(pDevice, hr));
     849
     850        RTMemFree(pResource->pKMResource);
    861851    }
    862852    else
    863853    {
    864         /* Opened shared resources must not be actually deleted. Just free the KM structure. */
    865         RTMemFree(pResource->pKMResource);
    866     }
    867 
    868     return true;
     854        if (!RT_BOOL(pResource->AllocationDesc.resourceInfo.MiscFlags & D3D10_DDI_RESOURCE_MISC_SHARED))
     855        {
     856            /* Set the resource for deferred destruction. */
     857            pResource->pKMResource->pResource = NULL;
     858            RTListAppend(&pDevice->listDestroyedResources, &pResource->pKMResource->nodeResource);
     859        }
     860        else
     861        {
     862            /* Opened shared resources must not be actually deleted. Just free the KM structure. */
     863            RTMemFree(pResource->pKMResource);
     864        }
     865    }
    869866}
    870867
     
    22332230
    22342231
    2235 static bool vboxDXCreateStagingBuffer(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource)
     2232static PVBOXDX_RESOURCE vboxDXCreateStagingBuffer(PVBOXDX_DEVICE pDevice, UINT cbAllocation)
    22362233{
    22372234    PVBOXDX_RESOURCE pStagingResource = (PVBOXDX_RESOURCE)RTMemAlloc(sizeof(VBOXDX_RESOURCE)
     
    22422239    D3D10DDI_MIPINFO mipInfo;
    22432240
    2244     /* Buffer is large enough to hold the entire resource. */
    2245     mipInfo.TexelWidth     = pResource->AllocationDesc.cbAllocation;
     2241    mipInfo.TexelWidth     = cbAllocation;
    22462242    mipInfo.TexelHeight    = 1;
    22472243    mipInfo.TexelDepth     = 1;
     
    22722268    {
    22732269        if (vboxDXCreateResource(pDevice, pStagingResource, &createResource))
    2274         {
    2275             pResource->pStagingResource = pStagingResource;
    2276             return true;
    2277         }
     2270            return pStagingResource;
    22782271    }
    22792272    RTMemFree(pStagingResource);
    2280     return false;
     2273    vboxDXDeviceSetError(pDevice, E_OUTOFMEMORY);
     2274    return NULL;
     2275}
     2276
     2277
     2278static HRESULT dxReclaimStagingAllocation(PVBOXDX_DEVICE pDevice, PVBOXDXKMRESOURCE pStagingKMResource)
     2279{
     2280    BOOL fDiscarded = FALSE;
     2281    D3DDDICB_RECLAIMALLOCATIONS ddiReclaimAllocations;
     2282    RT_ZERO(ddiReclaimAllocations);
     2283    ddiReclaimAllocations.pResources = NULL;
     2284    ddiReclaimAllocations.HandleList = &pStagingKMResource->hAllocation;
     2285    ddiReclaimAllocations.pDiscarded = &fDiscarded;
     2286    ddiReclaimAllocations.NumAllocations = 1;
     2287
     2288    HRESULT hr = pDevice->pRTCallbacks->pfnReclaimAllocationsCb(pDevice->hRTDevice.handle, &ddiReclaimAllocations);
     2289    LogFlowFunc(("pfnReclaimAllocationsCb returned %d, fDiscarded %d", hr, fDiscarded));
     2290    Assert(SUCCEEDED(hr));
     2291    return hr;
     2292}
     2293
     2294
     2295static HRESULT dxOfferStagingAllocation(PVBOXDX_DEVICE pDevice, PVBOXDXKMRESOURCE pStagingKMResource)
     2296{
     2297    D3DDDICB_OFFERALLOCATIONS ddiOfferAllocations;
     2298    RT_ZERO(ddiOfferAllocations);
     2299    ddiOfferAllocations.pResources = NULL;
     2300    ddiOfferAllocations.HandleList = &pStagingKMResource->hAllocation;
     2301    ddiOfferAllocations.NumAllocations = 1;
     2302    ddiOfferAllocations.Priority = D3DDDI_OFFER_PRIORITY_LOW;
     2303
     2304    HRESULT hr = pDevice->pRTCallbacks->pfnOfferAllocationsCb(pDevice->hRTDevice.handle, &ddiOfferAllocations);
     2305    LogFlowFunc(("pfnOfferAllocationsCb returned %d", hr));
     2306    Assert(SUCCEEDED(hr));
     2307    return hr;
    22812308}
    22822309
     
    22952322
    22962323    /* DEFAULT resources are updated via a staging buffer. */
    2297     if (!pDstResource->pStagingResource)
    2298     {
    2299         if (!vboxDXCreateStagingBuffer(pDevice, pDstResource))
    2300             return;
    2301     }
    2302 
     2324
     2325    /*
     2326     * A simple approach for now: allocate a staging buffer for each upload and delete the buffers after a flush.
     2327     */
     2328
     2329    /*
     2330     * Allocate a staging buffer big enough to hold the entire subresource.
     2331     */
     2332    uint32_t const cbStagingBuffer = vboxDXGetSubresourceSize(pDstResource, DstSubresource);
     2333    PVBOXDX_RESOURCE pStagingBuffer = vboxDXCreateStagingBuffer(pDevice, cbStagingBuffer);
     2334    if (!pStagingBuffer)
     2335        return;
     2336
     2337    /*
     2338     * Copy data to staging via map/unmap.
     2339     */
    23032340    SVGA3dBox destBox;
    23042341    if (pDstBox)
     
    23202357    vboxDXGetResourceBoxDimensions(pDstResource, DstSubresource, &destBox, &offPixel, &cbRow, &cRows, &Depth);
    23212358
    2322     uint32_t const offSubresource = vboxDXGetSubresourceOffset(pDstResource, DstSubresource);
    2323 
    23242359    UINT cbRowPitch;
    23252360    UINT cbDepthPitch;
    23262361    vboxDXGetSubresourcePitch(pDstResource, DstSubresource, &cbRowPitch, &cbDepthPitch);
    23272362
    2328     if (!vboxDXUpdateStagingBufferUP(pDevice, pDstResource->pStagingResource,
    2329                                      offSubresource + offPixel, cbRow, cRows, cbRowPitch, Depth, cbDepthPitch,
     2363    if (!vboxDXUpdateStagingBufferUP(pDevice, pStagingBuffer,
     2364                                     offPixel, cbRow, cRows, cbRowPitch, Depth, cbDepthPitch,
    23302365                                     pSysMemUP, RowPitch, DepthPitch))
    23312366        return;
    23322367
     2368    /*
     2369     * Copy from staging to destination.
     2370     */
    23332371    /* Inform the host that the staging buffer has been updated. Part occupied by the DstSubresource. */
    23342372    SVGA3dBox box;
    2335     box.x = offSubresource;
     2373    box.x = 0;
    23362374    box.y = 0;
    23372375    box.z = 0;
    2338     box.w = vboxDXGetSubresourceSize(pDstResource, DstSubresource);
     2376    box.w = cbStagingBuffer;
    23392377    box.h = 1;
    23402378    box.d = 1;
    2341     vgpu10UpdateSubResource(pDevice, vboxDXGetAllocation(pDstResource->pStagingResource), 0, &box);
     2379    vgpu10UpdateSubResource(pDevice, vboxDXGetAllocation(pStagingBuffer), 0, &box);
    23422380
    23432381    /* Issue SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER */
    2344     uint32 srcOffset = offSubresource + offPixel;
     2382    uint32 srcOffset = offPixel;
    23452383    uint32 srcPitch = cbRowPitch;
    23462384    uint32 srcSlicePitch = cbDepthPitch;
    2347     vgpu10TransferFromBuffer(pDevice, vboxDXGetAllocation(pDstResource->pStagingResource), srcOffset, srcPitch, srcSlicePitch,
     2385    vgpu10TransferFromBuffer(pDevice, vboxDXGetAllocation(pStagingBuffer), srcOffset, srcPitch, srcSlicePitch,
    23482386                             vboxDXGetAllocation(pDstResource), DstSubresource, destBox);
     2387
     2388    RTListPrepend(&pDevice->listStagingResources, &pStagingBuffer->pKMResource->nodeStaging);
    23492389}
    23502390
     
    31813221
    31823222
     3223static void dxDeallocateStagingResources(PVBOXDX_DEVICE pDevice)
     3224{
     3225    /* Move staging resources to the deferred destruction queue. */
     3226    PVBOXDXKMRESOURCE pKMResource, pNextKMResource;
     3227    RTListForEachSafe(&pDevice->listStagingResources, pKMResource, pNextKMResource, VBOXDXKMRESOURCE, nodeStaging)
     3228    {
     3229        RTListNodeRemove(&pKMResource->nodeStaging);
     3230
     3231        PVBOXDX_RESOURCE pStagingResource = pKMResource->pResource;
     3232        pKMResource->pResource = NULL;
     3233
     3234        Assert(pStagingResource->pKMResource == pKMResource);
     3235
     3236        /* Remove from the list of active resources. */
     3237        RTListNodeRemove(&pKMResource->nodeResource);
     3238        RTListAppend(&pDevice->listDestroyedResources, &pKMResource->nodeResource);
     3239
     3240        /* Staging resources are allocated by the driver. */
     3241        RTMemFree(pStagingResource);
     3242    }
     3243}
     3244
     3245
    31833246static void dxDestroyDeferredResources(PVBOXDX_DEVICE pDevice)
    31843247{
     
    31863249    RTListForEachSafe(&pDevice->listDestroyedResources, pKMResource, pNext, VBOXDXKMRESOURCE, nodeResource)
    31873250    {
    3188         D3DKMT_HANDLE const hAllocation = pKMResource->hAllocation;
    31893251        RTListNodeRemove(&pKMResource->nodeResource);
    3190         RTMemFree(pKMResource);
    31913252
    31923253        D3DDDICB_DEALLOCATE ddiDeallocate;
     
    31943255        //ddiDeallocate.hResource      = NULL;
    31953256        ddiDeallocate.NumAllocations = 1;
    3196         ddiDeallocate.HandleList     = &hAllocation;
    3197 
    3198         pDevice->pRTCallbacks->pfnDeallocateCb(pDevice->hRTDevice.handle, &ddiDeallocate);
     3257        ddiDeallocate.HandleList     = &pKMResource->hAllocation;
     3258
     3259        HRESULT hr = pDevice->pRTCallbacks->pfnDeallocateCb(pDevice->hRTDevice.handle, &ddiDeallocate);
     3260        LogFlowFunc(("pfnDeallocateCb returned %d", hr));
     3261        AssertStmt(SUCCEEDED(hr), vboxDXDeviceSetError(pDevice, hr));
     3262
     3263        RTMemFree(pKMResource);
    31993264    }
    32003265}
     
    32093274        AssertReturnStmt(SUCCEEDED(hr), vboxDXDeviceSetError(pDevice, hr), hr);
    32103275    }
     3276
     3277    /* Free the staging resources which used for uploads in this command buffer.
     3278     * They are moved to the deferred destruction queue.
     3279     */
     3280    dxDeallocateStagingResources(pDevice);
    32113281
    32123282    /* Process deferred-destruction queue. */
     
    33133383    RTListInit(&pDevice->listResources);
    33143384    RTListInit(&pDevice->listDestroyedResources);
     3385    RTListInit(&pDevice->listStagingResources);
    33153386    RTListInit(&pDevice->listShaders);
    33163387    RTListInit(&pDevice->listQueries);
     
    34153486void vboxDXDestroyDevice(PVBOXDX_DEVICE pDevice)
    34163487{
     3488    /* Flush will deallocate staging resources. */
    34173489    vboxDXFlush(pDevice, true);
    34183490
    34193491    PVBOXDXKMRESOURCE pKMResource, pNextKMResource;
    34203492    RTListForEachSafe(&pDevice->listResources, pKMResource, pNextKMResource, VBOXDXKMRESOURCE, nodeResource)
    3421         dxDestroyResource(pDevice, pKMResource->pResource);
     3493        vboxDXDestroyResource(pDevice, pKMResource->pResource);
    34223494
    34233495    dxDestroyDeferredResources(pDevice);
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/dx/VBoxDX.h

    r98103 r99855  
    182182    struct VBOXDX_RESOURCE     *pResource;                  /* The structure allocated by D3D runtime. */
    183183    D3DKMT_HANDLE               hAllocation;
     184    RTLISTNODE                  nodeStaging;                /* VBOXDX_DEVICE::listStagingResources if this resource is a staging buffer. */
    184185} VBOXDXKMRESOURCE, *PVBOXDXKMRESOURCE;
    185186
     
    198199        UINT                       uMap;
    199200    };
    200     struct VBOXDX_RESOURCE         *pStagingResource;
    201201
    202202    RTLISTANCHOR                   listSRV;                 /* Shader resource views created for this resource. */
     
    386386    RTLISTANCHOR                listResources;              /* All resources of this device, for cleanup. */
    387387    RTLISTANCHOR                listDestroyedResources;     /* DestroyResource adds to this list. Flush actually deleted them. */
     388    RTLISTANCHOR                listStagingResources;       /* List of staging resources for uploads. */
    388389
    389390    /* Shaders */
     
    436437bool vboxDXOpenResource(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource,
    437438                        const D3D10DDIARG_OPENRESOURCE *pOpenResource);
    438 bool vboxDXDestroyResource(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource);
     439void vboxDXDestroyResource(PVBOXDX_DEVICE pDevice, PVBOXDX_RESOURCE pResource);
    439440
    440441HRESULT vboxDXRotateResourceIdentities(PVBOXDX_DEVICE pDevice, UINT cResources, PVBOXDX_RESOURCE *papResources);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette