VirtualBox

Ignore:
Timestamp:
May 9, 2022 6:48:47 AM (3 years ago)
Author:
vboxsync
Message:

WDDM: Fill and DiscardContent paging operations; various fixes. bugref:9845

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/VBoxMPDX.cpp

    r94904 r94927  
    2727#include "SvgaHw.h"
    2828
     29#include <iprt/memobj.h>
    2930
    3031bool SvgaIsDXSupported(PVBOXMP_DEVEXT pDevExt)
     
    3637
    3738
    38 static NTSTATUS svgaCreateSurfaceForAllocation(PVBOXWDDM_EXT_GA pGaDevExt, PVBOXWDDM_ALLOCATION pAllocation)
    39 {
    40     VBOXWDDM_EXT_VMSVGA *pSvga = pGaDevExt->hw.pSvga;
     39static NTSTATUS svgaCreateSurfaceForAllocation(VBOXWDDM_EXT_VMSVGA *pSvga, PVBOXWDDM_ALLOCATION pAllocation)
     40{
    4141    NTSTATUS Status = SvgaSurfaceIdAlloc(pSvga, &pAllocation->dx.sid);
     42    Assert(NT_SUCCESS(Status));
    4243    if (NT_SUCCESS(Status))
    4344    {
     
    5859        }
    5960        else
    60             Status = STATUS_INSUFFICIENT_RESOURCES;
    61     }
     61            AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     62
     63        if (NT_SUCCESS(Status))
     64        {
     65            if (pAllocation->dx.SegmentId == 3)
     66            {
     67                pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_BIND_GB_SURFACE, sizeof(SVGA3dCmdBindGBSurface), SVGA3D_INVALID_ID);
     68                if (pvCmd)
     69                {
     70                    SVGA3dCmdBindGBSurface *pCmd = (SVGA3dCmdBindGBSurface *)pvCmd;
     71                    pCmd->sid = pAllocation->dx.sid;
     72                    pCmd->mobid = pAllocation->dx.mobid;
     73                    SvgaCmdBufCommit(pSvga, sizeof(SVGA3dCmdBindGBSurface));
     74                }
     75                else
     76                    AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     77            }
     78        }
     79    }
     80
     81    if (!NT_SUCCESS(Status))
     82        SvgaSurfaceIdFree(pSvga, pAllocation->dx.sid);
     83
    6284    return Status;
    6385}
    6486
    6587
     88static void svgaFreeGBMobForAllocation(VBOXWDDM_EXT_VMSVGA *pSvga, PVBOXWDDM_ALLOCATION pAllocation)
     89{
     90    AssertReturnVoid(pAllocation->dx.SegmentId == 3);
     91
     92    void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DESTROY_GB_MOB, sizeof(SVGA3dCmdDestroyGBMob), SVGA3D_INVALID_ID);
     93    if (pvCmd)
     94    {
     95        SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pvCmd;
     96        pCmd->mobid = VMSVGAMOB_ID(pAllocation->dx.gb.pMob);
     97        SvgaCmdBufCommit(pSvga, sizeof(SVGA3dCmdDestroyGBMob));
     98    }
     99
     100    if (pAllocation->dx.gb.pMob)
     101    {
     102        SvgaMobFree(pSvga, pAllocation->dx.gb.pMob);
     103        pAllocation->dx.gb.pMob = NULL;
     104    }
     105
     106    if (pAllocation->dx.gb.hMemObjGB != NIL_RTR0MEMOBJ)
     107    {
     108        RTR0MemObjFree(pAllocation->dx.gb.hMemObjGB, true);
     109        pAllocation->dx.gb.hMemObjGB = NIL_RTR0MEMOBJ;
     110    }
     111
     112    pAllocation->dx.mobid = SVGA3D_INVALID_ID;
     113}
     114
     115
     116static NTSTATUS svgaCreateGBMobForAllocation(VBOXWDDM_EXT_VMSVGA *pSvga, PVBOXWDDM_ALLOCATION pAllocation)
     117{
     118    AssertReturn(pAllocation->dx.SegmentId == 3, STATUS_INVALID_PARAMETER);
     119
     120    uint32_t const cbGB = RT_ALIGN_32(pAllocation->dx.desc.cbAllocation, PAGE_SIZE);
     121
     122    /* Allocate guest backing pages. */
     123    int rc = RTR0MemObjAllocPageTag(&pAllocation->dx.gb.hMemObjGB, cbGB, false /* executable R0 mapping */, "VMSVGAGB");
     124    AssertRCReturn(rc, STATUS_INSUFFICIENT_RESOURCES);
     125
     126    /* Allocate a new mob. */
     127    NTSTATUS Status = SvgaMobCreate(pSvga, &pAllocation->dx.gb.pMob, cbGB >> PAGE_SHIFT, 0);
     128    Assert(NT_SUCCESS(Status));
     129    if (NT_SUCCESS(Status))
     130    {
     131        Status = SvgaMobFillPageTableForMemObj(pSvga, pAllocation->dx.gb.pMob, pAllocation->dx.gb.hMemObjGB);
     132        Assert(NT_SUCCESS(Status));
     133        if (NT_SUCCESS(Status))
     134        {
     135            pAllocation->dx.mobid = VMSVGAMOB_ID(pAllocation->dx.gb.pMob);
     136
     137            void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DEFINE_GB_MOB64, sizeof(SVGA3dCmdDefineGBMob64), SVGA3D_INVALID_ID);
     138            if (pvCmd)
     139            {
     140                SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pvCmd;
     141                pCmd->mobid       = VMSVGAMOB_ID(pAllocation->dx.gb.pMob);
     142                pCmd->ptDepth     = pAllocation->dx.gb.pMob->enmMobFormat;
     143                pCmd->base        = pAllocation->dx.gb.pMob->base;
     144                pCmd->sizeInBytes = pAllocation->dx.gb.pMob->cbMob;
     145                SvgaCmdBufCommit(pSvga, sizeof(SVGA3dCmdDefineGBMob64));
     146            }
     147            else
     148                AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     149
     150            if (NT_SUCCESS(Status))
     151                return STATUS_SUCCESS;
     152        }
     153    }
     154
     155    svgaFreeGBMobForAllocation(pSvga, pAllocation);
     156    return Status;
     157}
     158
     159
    66160static NTSTATUS svgaCreateAllocationSurface(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation, DXGK_ALLOCATIONINFO *pAllocationInfo)
    67161{
    68     NTSTATUS Status = svgaCreateSurfaceForAllocation(pDevExt->pGa, pAllocation);
    69     AssertReturn(NT_SUCCESS(Status), Status);
     162    VBOXWDDM_EXT_VMSVGA *pSvga = pDevExt->pGa->hw.pSvga;
    70163
    71164    /* Fill data for WDDM. */
     
    87180//            pAllocationInfo->SupportedWriteSegmentSet    = 1; /* VRAM */
    88181//            pAllocationInfo->Flags.CpuVisible            = 1;
     182//
     183//            pAllocation->dx.SegmentId = 1;
    89184//        }
    90185//        else
     
    93188            pAllocationInfo->SupportedReadSegmentSet     = 4; /* Host */
    94189            pAllocationInfo->SupportedWriteSegmentSet    = 4; /* Host */
     190
     191            pAllocation->dx.SegmentId = 3;
    95192        }
    96193    }
     
    103200        pAllocationInfo->SupportedWriteSegmentSet    = 2; /* Aperture */
    104201        pAllocationInfo->Flags.CpuVisible            = 1;
     202
     203        pAllocation->dx.SegmentId = 2;
    105204    }
    106205    else if (pAllocation->dx.desc.surfaceInfo.surfaceFlags
     
    113212        pAllocationInfo->SupportedWriteSegmentSet    = 2; /* Aperture */
    114213        pAllocationInfo->Flags.CpuVisible            = 1;
     214
     215        pAllocation->dx.SegmentId = 2;
    115216    }
    116217    pAllocationInfo->EvictionSegmentSet              = 0;
     
    119220    pAllocationInfo->pAllocationUsageHint            = NULL;
    120221    pAllocationInfo->AllocationPriority              = D3DDDI_ALLOCATIONPRIORITY_NORMAL;
     222
     223    /* Allocations in the host VRAM still need guest backing. */
     224    NTSTATUS Status;
     225    if (pAllocation->dx.SegmentId == 3)
     226    {
     227        Status = svgaCreateGBMobForAllocation(pSvga, pAllocation);
     228        if (NT_SUCCESS(Status))
     229        {
     230            Status = svgaCreateSurfaceForAllocation(pSvga, pAllocation);
     231            if (!NT_SUCCESS(Status))
     232                svgaFreeGBMobForAllocation(pSvga, pAllocation);
     233        }
     234    }
     235    else
     236        Status = svgaCreateSurfaceForAllocation(pSvga, pAllocation);
     237
    121238    return Status;
    122239}
     
    144261
    145262
    146 static NTSTATUS svgaDestroyAllocationSurface(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
    147 {
    148     VBOXWDDM_EXT_VMSVGA *pSvga = pDevExt->pGa->hw.pSvga;
     263static NTSTATUS svgaDestroyAllocationSurface(VBOXWDDM_EXT_VMSVGA *pSvga, PVBOXWDDM_ALLOCATION pAllocation)
     264{
    149265    NTSTATUS Status = STATUS_SUCCESS;
    150266    if (pAllocation->dx.sid != SVGA3D_INVALID_ID)
    151267    {
    152         void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DESTROY_GB_SURFACE, sizeof(SVGA3dCmdDestroyGBSurface), SVGA3D_INVALID_ID);
     268        void *pvCmd;
     269        if (pAllocation->dx.SegmentId == 3)
     270        {
     271            pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_BIND_GB_SURFACE, sizeof(SVGA3dCmdBindGBSurface), SVGA3D_INVALID_ID);
     272            if (pvCmd)
     273            {
     274                SVGA3dCmdBindGBSurface *pCmd = (SVGA3dCmdBindGBSurface *)pvCmd;
     275                pCmd->sid = pAllocation->dx.sid;
     276                pCmd->mobid = SVGA3D_INVALID_ID;
     277                SvgaCmdBufCommit(pSvga, sizeof(SVGA3dCmdBindGBSurface));
     278            }
     279        }
     280
     281        pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DESTROY_GB_SURFACE, sizeof(SVGA3dCmdDestroyGBSurface), SVGA3D_INVALID_ID);
    153282        if (pvCmd)
    154283        {
     
    157286            SvgaCmdBufCommit(pSvga, sizeof(SVGA3dCmdDestroyGBSurface));
    158287        }
    159         else
    160             Status = STATUS_INSUFFICIENT_RESOURCES;
    161 
    162         if (NT_SUCCESS(Status))
    163             Status = SvgaSurfaceIdFree(pSvga, pAllocation->dx.sid);
     288
     289        Status = SvgaSurfaceIdFree(pSvga, pAllocation->dx.sid);
     290
     291        if (pAllocation->dx.SegmentId == 3)
     292            svgaFreeGBMobForAllocation(pSvga, pAllocation);
     293
     294        pAllocation->dx.sid = SVGA3D_INVALID_ID;
    164295    }
    165296    return Status;
     
    167298
    168299
    169 static NTSTATUS svgaDestroyAllocationShaders(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
    170 {
    171     VBOXWDDM_EXT_VMSVGA *pSvga = pDevExt->pGa->hw.pSvga;
     300static NTSTATUS svgaDestroyAllocationShaders(VBOXWDDM_EXT_VMSVGA *pSvga, PVBOXWDDM_ALLOCATION pAllocation)
     301{
     302    NTSTATUS Status = STATUS_SUCCESS;
    172303    if (pAllocation->dx.mobid != SVGA3D_INVALID_ID)
    173304    {
     
    180311        }
    181312        else
    182             AssertFailedReturn(STATUS_INSUFFICIENT_RESOURCES);
    183     }
    184     return STATUS_SUCCESS;
     313            AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     314
     315        pAllocation->dx.mobid = SVGA3D_INVALID_ID;
     316    }
     317    return Status;
    185318}
    186319
     
    207340    pAllocation->dx.sid = SVGA3D_INVALID_ID;
    208341    pAllocation->dx.mobid = SVGA3D_INVALID_ID;
     342    pAllocation->dx.SegmentId = 0;
     343    pAllocation->dx.pMDL = 0;
    209344
    210345    /* Legacy. Unused. */
     
    237372
    238373    if (pAllocation->dx.desc.enmAllocationType == VBOXDXALLOCATIONTYPE_SURFACE)
    239         Status = svgaDestroyAllocationSurface(pDevExt, pAllocation);
     374        Status = svgaDestroyAllocationSurface(pDevExt->pGa->hw.pSvga, pAllocation);
    240375    else if (pAllocation->dx.desc.enmAllocationType == VBOXDXALLOCATIONTYPE_SHADERS)
    241         Status = svgaDestroyAllocationShaders(pDevExt, pAllocation);
     376        Status = svgaDestroyAllocationShaders(pDevExt->pGa->hw.pSvga, pAllocation);
    242377    else
    243378        AssertFailedReturn(STATUS_INVALID_PARAMETER);
     
    309444                {
    310445                    /* DEFAULT resources only require the sid, because they exist outside the guest. */
    311                     if (pAllocation->dx.sid != SVGA3D_INVALID_ID)
    312                     {
    313                         *(uint32_t *)pPatchAddress = pAllocation->dx.sid;
    314                         continue;
    315                     }
     446                    Assert(pAllocation->dx.sid != SVGA3D_INVALID_ID);
     447                    Assert(pAllocation->dx.mobid != SVGA3D_INVALID_ID);
     448                    Assert(pAllocation->dx.SegmentId == 3);
     449
     450                    *(uint32_t *)pPatchAddress = pAllocation->dx.sid;
     451                    continue;
    316452                }
    317453                else
    318454                {
    319                     /* For Aperture segment, the surface need a mob too. */
     455                    /* For Aperture segment, the surface need a mob too, which must be created in BuildPagingBuffer. */
    320456                    if (   pAllocation->dx.sid != SVGA3D_INVALID_ID
    321457                        && pAllocation->dx.mobid != SVGA3D_INVALID_ID)
     
    640776
    641777
     778static NTSTATUS svgaPagingFill(PVBOXMP_DEVEXT pDevExt, DXGKARG_BUILDPAGINGBUFFER *pBuildPagingBuffer, uint32_t *pcbCommands)
     779{
     780    VBOXWDDM_EXT_VMSVGA *pSvga = pDevExt->pGa->hw.pSvga;
     781    RT_NOREF(pSvga);
     782
     783    PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
     784    AssertReturn(pAllocation, STATUS_INVALID_PARAMETER);
     785
     786    AssertReturn((pBuildPagingBuffer->Fill.FillSize & 3) == 0, STATUS_INVALID_PARAMETER);
     787    AssertReturn(   pAllocation->enmType != VBOXWDDM_ALLOC_TYPE_D3D
     788                 || pBuildPagingBuffer->Fill.Destination.SegmentId == pAllocation->dx.SegmentId, STATUS_INVALID_PARAMETER);
     789
     790    NTSTATUS Status = STATUS_SUCCESS;
     791    switch (pBuildPagingBuffer->Fill.Destination.SegmentId)
     792    {
     793        case 1: /* VRAM */
     794        {
     795            uint64_t const offVRAM = pBuildPagingBuffer->Fill.Destination.SegmentAddress.QuadPart;
     796            AssertReturn(   offVRAM < pDevExt->cbVRAMCpuVisible
     797                         && pBuildPagingBuffer->Fill.FillSize <= pDevExt->cbVRAMCpuVisible - offVRAM, STATUS_INVALID_PARAMETER);
     798            ASMMemFill32((uint8_t *)pDevExt->pvVisibleVram + offVRAM, pBuildPagingBuffer->Fill.FillSize, pBuildPagingBuffer->Fill.FillPattern);
     799            break;
     800        }
     801        case 2: /* Aperture */
     802        case 3: /* Host */
     803        {
     804            if (pAllocation->enmType != VBOXWDDM_ALLOC_TYPE_D3D)
     805                break;
     806
     807            void *pvDst;
     808            if (pBuildPagingBuffer->Fill.Destination.SegmentId == 3)
     809            {
     810                AssertReturn(pAllocation->dx.gb.hMemObjGB != NIL_RTR0MEMOBJ, STATUS_INVALID_PARAMETER);
     811                pvDst = RTR0MemObjAddress(pAllocation->dx.gb.hMemObjGB);
     812            }
     813            else
     814            {
     815                AssertReturn(pAllocation->dx.pMDL != NULL, STATUS_INVALID_PARAMETER);
     816                DEBUG_BREAKPOINT_TEST();
     817                pvDst = MmGetSystemAddressForMdlSafe(pAllocation->dx.pMDL, NormalPagePriority);
     818                AssertReturn(pvDst, STATUS_INSUFFICIENT_RESOURCES);
     819            }
     820
     821            /* Fill the guest backing pages. */
     822            uint32_t const cbFill = RT_MIN(pBuildPagingBuffer->Fill.FillSize, pAllocation->dx.desc.cbAllocation);
     823            ASMMemFill32(pvDst, cbFill, pBuildPagingBuffer->Fill.FillPattern);
     824
     825            /* Emit UPDATE_GB_SURFACE */
     826            uint8_t *pu8Cmd = (uint8_t *)pBuildPagingBuffer->pDmaBuffer;
     827            uint32_t cbRequired = sizeof(SVGA3dCmdHeader) + sizeof(SVGA3dCmdUpdateGBSurface);
     828            if (pBuildPagingBuffer->DmaSize < cbRequired)
     829            {
     830                Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     831                break;
     832            }
     833
     834            SVGA3dCmdHeader *pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     835            pHdr->id   = SVGA_3D_CMD_UPDATE_GB_SURFACE;
     836            pHdr->size = sizeof(SVGA3dCmdUpdateGBSurface);
     837            pu8Cmd += sizeof(*pHdr);
     838
     839            SVGA3dCmdUpdateGBSurface *pCmd = (SVGA3dCmdUpdateGBSurface *)pu8Cmd;
     840            pCmd->sid = pAllocation->dx.sid;
     841            pu8Cmd += sizeof(*pCmd);
     842
     843            *pcbCommands = (uintptr_t)pu8Cmd - (uintptr_t)pBuildPagingBuffer->pDmaBuffer;
     844            break;
     845        }
     846        default:
     847            AssertFailedReturn(STATUS_INVALID_PARAMETER);
     848    }
     849    return Status;
     850}
     851
     852
     853static NTSTATUS svgaPagingDiscardContent(PVBOXMP_DEVEXT pDevExt, DXGKARG_BUILDPAGINGBUFFER *pBuildPagingBuffer, uint32_t *pcbCommands)
     854{
     855    VBOXWDDM_EXT_VMSVGA *pSvga = pDevExt->pGa->hw.pSvga;
     856    RT_NOREF(pSvga);
     857
     858    PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->DiscardContent.hAllocation;
     859    AssertReturn(pAllocation, STATUS_INVALID_PARAMETER);
     860    AssertReturn(   pAllocation->enmType != VBOXWDDM_ALLOC_TYPE_D3D
     861                 || pBuildPagingBuffer->DiscardContent.SegmentId == pAllocation->dx.SegmentId, STATUS_INVALID_PARAMETER);
     862
     863    if (pAllocation->enmType != VBOXWDDM_ALLOC_TYPE_D3D)
     864        return STATUS_SUCCESS;
     865
     866    if (pAllocation->dx.desc.enmAllocationType == VBOXDXALLOCATIONTYPE_SURFACE)
     867    {
     868        /* Emit INVALIDATE_GB_SURFACE */
     869        uint8_t *pu8Cmd = (uint8_t *)pBuildPagingBuffer->pDmaBuffer;
     870        uint32_t cbRequired = sizeof(SVGA3dCmdHeader) + sizeof(SVGA3dCmdInvalidateGBSurface);
     871        if (pBuildPagingBuffer->DmaSize < cbRequired)
     872            return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     873
     874        SVGA3dCmdHeader *pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     875        pHdr->id   = SVGA_3D_CMD_INVALIDATE_GB_SURFACE;
     876        pHdr->size = sizeof(SVGA3dCmdInvalidateGBSurface);
     877        pu8Cmd += sizeof(*pHdr);
     878
     879        SVGA3dCmdUpdateGBSurface *pCmd = (SVGA3dCmdUpdateGBSurface *)pu8Cmd;
     880        pCmd->sid = pAllocation->dx.sid;
     881        pu8Cmd += sizeof(*pCmd);
     882
     883        *pcbCommands = (uintptr_t)pu8Cmd - (uintptr_t)pBuildPagingBuffer->pDmaBuffer;
     884    }
     885
     886    return STATUS_SUCCESS;
     887}
     888
     889
    642890static NTSTATUS svgaPagingMapApertureSegment(PVBOXMP_DEVEXT pDevExt, DXGKARG_BUILDPAGINGBUFFER *pBuildPagingBuffer, uint32_t *pcbCommands)
    643891{
     
    655903    if (pAllocation->dx.mobid != SVGA3D_INVALID_ID)
    656904    {
    657         AssertFailed();
     905        DEBUG_BREAKPOINT_TEST();
    658906        return STATUS_SUCCESS;
    659907    }
     
    8261074        case DXGK_OPERATION_FILL:
    8271075        {
    828             PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
    829             RT_NOREF(pAllocation);
    830             DEBUG_BREAKPOINT_TEST();
     1076            Status = svgaPagingFill(pDevExt, pBuildPagingBuffer, &cbCommands);
    8311077            break;
    8321078        }
    8331079        case DXGK_OPERATION_DISCARD_CONTENT:
    8341080        {
    835             DEBUG_BREAKPOINT_TEST();
     1081            Status = svgaPagingDiscardContent(pDevExt, pBuildPagingBuffer, &cbCommands);
    8361082            break;
    8371083        }
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