/* $Id: DevVGA-SVGA3d-dx-dx11.cpp $ */ /** @file * DevVMWare - VMWare SVGA device */ /* * Copyright (C) 2020-2023 Oracle and/or its affiliates. * * This file is part of VirtualBox base platform packages, as * available from https://www.virtualbox.org. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, in version 3 of the * License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * SPDX-License-Identifier: GPL-3.0-only */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #define LOG_GROUP LOG_GROUP_DEV_VMSVGA #include #include #include #include #include #include #include #include #include /* required by DevVGA.h */ #include /* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ #include "DevVGA.h" #include "DevVGA-SVGA.h" #include "DevVGA-SVGA3d.h" #include "DevVGA-SVGA3d-internal.h" #include "DevVGA-SVGA3d-dx-shader.h" /* d3d11_1.h has a structure field named 'Status' but Status is defined as int on Linux host */ #if defined(Status) #undef Status #endif #include #ifdef RT_OS_WINDOWS # define VBOX_D3D11_LIBRARY_NAME "d3d11" #else # define VBOX_D3D11_LIBRARY_NAME "VBoxDxVk" #endif /* One ID3D11Device object is used for all VMSVGA contexts. */ /** @todo This should be the only option because VGPU freely uses surfaces from different VMSVGA contexts * and synchronization of access to shared surfaces kills performance. */ #define DX_FORCE_SINGLE_DEVICE /* A single staging ID3D11Buffer is used for uploading data to other buffers. */ #define DX_COMMON_STAGING_BUFFER /* Always flush after submitting a draw call for debugging. */ //#define DX_FLUSH_AFTER_DRAW /* This is not available on non Windows hosts. */ #ifndef D3D_RELEASE # define D3D_RELEASE(a_Ptr) do { if ((a_Ptr)) (a_Ptr)->Release(); (a_Ptr) = NULL; } while (0) #endif /** Fake ID for the backend DX context. The context creates all shared textures. */ #define DX_CID_BACKEND UINT32_C(0xfffffffe) #define D3D_RELEASE_ARRAY(a_Count, a_papArray) do { \ for (uint32_t i = 0; i < (a_Count); ++i) \ D3D_RELEASE((a_papArray)[i]); \ } while (0) typedef struct D3D11BLITTER { ID3D11Device1 *pDevice; ID3D11DeviceContext1 *pImmediateContext; ID3D11VertexShader *pVertexShader; ID3D11PixelShader *pPixelShader; ID3D11SamplerState *pSamplerState; ID3D11RasterizerState1 *pRasterizerState; ID3D11BlendState1 *pBlendState; } D3D11BLITTER; typedef struct DXDEVICE { ID3D11Device1 *pDevice; /* Device. */ ID3D11DeviceContext1 *pImmediateContext; /* Corresponding context. */ IDXGIFactory *pDxgiFactory; /* DXGI Factory. */ D3D_FEATURE_LEVEL FeatureLevel; #ifdef DX_COMMON_STAGING_BUFFER /* Staging buffer for transfer to surface buffers. */ ID3D11Buffer *pStagingBuffer; /* The staging buffer resource. */ uint32_t cbStagingBuffer; /* Current size of the staging buffer resource. */ #endif D3D11BLITTER Blitter; /* Blits one texture to another. */ } DXDEVICE; /* Kind of a texture view. */ typedef enum VMSVGA3DBACKVIEWTYPE { VMSVGA3D_VIEWTYPE_NONE = 0, VMSVGA3D_VIEWTYPE_RENDERTARGET = 1, VMSVGA3D_VIEWTYPE_DEPTHSTENCIL = 2, VMSVGA3D_VIEWTYPE_SHADERRESOURCE = 3, VMSVGA3D_VIEWTYPE_UNORDEREDACCESS = 4 } VMSVGA3DBACKVIEWTYPE; /* Information about a texture view to track all created views:. * when a surface is invalidated, then all views must deleted; * when a view is deleted, then the view must be unlinked from the surface. */ typedef struct DXVIEWINFO { uint32_t sid; /* Surface which the view was created for. */ uint32_t cid; /* DX context which created the view. */ uint32_t viewId; /* View id assigned by the guest. */ VMSVGA3DBACKVIEWTYPE enmViewType; } DXVIEWINFO; /* Context Object Table element for a texture view. */ typedef struct DXVIEW { uint32_t cid; /* DX context which created the view. */ uint32_t sid; /* Surface which the view was created for. */ uint32_t viewId; /* View id assigned by the guest. */ VMSVGA3DBACKVIEWTYPE enmViewType; union { ID3D11View *pView; /* The view object. */ ID3D11RenderTargetView *pRenderTargetView; ID3D11DepthStencilView *pDepthStencilView; ID3D11ShaderResourceView *pShaderResourceView; ID3D11UnorderedAccessView *pUnorderedAccessView; } u; RTLISTNODE nodeSurfaceView; /* Views are linked to the surface. */ } DXVIEW; /* What kind of resource has been created for the VMSVGA3D surface. */ typedef enum VMSVGA3DBACKRESTYPE { VMSVGA3D_RESTYPE_NONE = 0, VMSVGA3D_RESTYPE_TEXTURE_1D = 1, VMSVGA3D_RESTYPE_TEXTURE_2D = 2, VMSVGA3D_RESTYPE_TEXTURE_CUBE = 3, VMSVGA3D_RESTYPE_TEXTURE_3D = 4, VMSVGA3D_RESTYPE_BUFFER = 5, } VMSVGA3DBACKRESTYPE; typedef struct VMSVGA3DBACKENDSURFACE { VMSVGA3DBACKRESTYPE enmResType; DXGI_FORMAT enmDxgiFormat; union { ID3D11Resource *pResource; ID3D11Texture1D *pTexture1D; ID3D11Texture2D *pTexture2D; ID3D11Texture3D *pTexture3D; ID3D11Buffer *pBuffer; } u; /* For updates from memory. */ union /** @todo One per format. */ { ID3D11Resource *pResource; ID3D11Texture1D *pTexture1D; ID3D11Texture2D *pTexture2D; ID3D11Texture3D *pTexture3D; #ifndef DX_COMMON_STAGING_BUFFER ID3D11Buffer *pBuffer; #endif } dynamic; /* For reading the texture content. */ union /** @todo One per format. */ { ID3D11Resource *pResource; ID3D11Texture1D *pTexture1D; ID3D11Texture2D *pTexture2D; ID3D11Texture3D *pTexture3D; #ifndef DX_COMMON_STAGING_BUFFER ID3D11Buffer *pBuffer; #endif } staging; /* Screen targets are created as shared surfaces. */ HANDLE SharedHandle; /* The shared handle of this structure. */ /* DX context which last rendered to the texture. * This is only for render targets and screen targets, which can be shared between contexts. * The backend context (cid == DX_CID_BACKEND) can also be a drawing context. */ uint32_t cidDrawing; /** AVL tree containing DXSHAREDTEXTURE structures. */ AVLU32TREE SharedTextureTree; /* Render target views, depth stencil views and shader resource views created for this texture or buffer. */ RTLISTANCHOR listView; /* DXVIEW */ } VMSVGA3DBACKENDSURFACE; /* "The only resources that can be shared are 2D non-mipmapped textures." */ typedef struct DXSHAREDTEXTURE { AVLU32NODECORE Core; /* Key is context id which opened this texture. */ ID3D11Texture2D *pTexture; /* The opened shared texture. */ uint32_t sid; /* Surface id. */ } DXSHAREDTEXTURE; typedef struct VMSVGAHWSCREEN { ID3D11Texture2D *pTexture; /* Shared texture for the screen content. Only used as CopyResource target. */ IDXGIResource *pDxgiResource; /* Interface of the texture. */ IDXGIKeyedMutex *pDXGIKeyedMutex; /* Synchronization interface for the render device. */ HANDLE SharedHandle; /* The shared handle of this structure. */ uint32_t sidScreenTarget; /* The source surface for this screen. */ } VMSVGAHWSCREEN; typedef struct DXELEMENTLAYOUT { ID3D11InputLayout *pElementLayout; uint32_t cElementDesc; D3D11_INPUT_ELEMENT_DESC aElementDesc[32]; } DXELEMENTLAYOUT; typedef struct DXSHADER { SVGA3dShaderType enmShaderType; union { ID3D11DeviceChild *pShader; /* All. */ ID3D11VertexShader *pVertexShader; /* SVGA3D_SHADERTYPE_VS */ ID3D11PixelShader *pPixelShader; /* SVGA3D_SHADERTYPE_PS */ ID3D11GeometryShader *pGeometryShader; /* SVGA3D_SHADERTYPE_GS */ ID3D11HullShader *pHullShader; /* SVGA3D_SHADERTYPE_HS */ ID3D11DomainShader *pDomainShader; /* SVGA3D_SHADERTYPE_DS */ ID3D11ComputeShader *pComputeShader; /* SVGA3D_SHADERTYPE_CS */ }; void *pvDXBC; uint32_t cbDXBC; uint32_t soid; /* Stream output declarations for geometry shaders. */ DXShaderInfo shaderInfo; } DXSHADER; typedef struct DXQUERY { union { ID3D11Query *pQuery; ID3D11Predicate *pPredicate; }; } DXQUERY; typedef struct DXSTREAMOUTPUT { UINT cDeclarationEntry; D3D11_SO_DECLARATION_ENTRY aDeclarationEntry[SVGA3D_MAX_STREAMOUT_DECLS]; } DXSTREAMOUTPUT; typedef struct DXBOUNDVERTEXBUFFER { ID3D11Buffer *pBuffer; uint32_t stride; uint32_t offset; } DXBOUNDVERTEXBUFFER; typedef struct DXBOUNDINDEXBUFFER { ID3D11Buffer *pBuffer; DXGI_FORMAT indexBufferFormat; uint32_t indexBufferOffset; } DXBOUNDINDEXBUFFER; typedef struct DXBOUNDRESOURCES /* Currently bound resources. Mirror SVGADXContextMobFormat structure. */ { struct { DXBOUNDVERTEXBUFFER vertexBuffers[SVGA3D_DX_MAX_VERTEXBUFFERS]; DXBOUNDINDEXBUFFER indexBuffer; } inputAssembly; struct { ID3D11Buffer *constantBuffers[SVGA3D_DX_MAX_CONSTBUFFERS]; } shaderState[SVGA3D_NUM_SHADERTYPE]; } DXBOUNDRESOURCES; typedef struct VMSVGA3DBACKENDDXCONTEXT { DXDEVICE dxDevice; /* DX device interfaces for this context operations. */ /* Arrays for Context-Object Tables. Number of entries depends on COTable size. */ uint32_t cBlendState; /* Number of entries in the papBlendState array. */ uint32_t cDepthStencilState; /* papDepthStencilState */ uint32_t cSamplerState; /* papSamplerState */ uint32_t cRasterizerState; /* papRasterizerState */ uint32_t cElementLayout; /* paElementLayout */ uint32_t cRenderTargetView; /* paRenderTargetView */ uint32_t cDepthStencilView; /* paDepthStencilView */ uint32_t cShaderResourceView; /* paShaderResourceView */ uint32_t cQuery; /* paQuery */ uint32_t cShader; /* paShader */ uint32_t cStreamOutput; /* paStreamOutput */ uint32_t cUnorderedAccessView; /* paUnorderedAccessView */ ID3D11BlendState1 **papBlendState; ID3D11DepthStencilState **papDepthStencilState; ID3D11SamplerState **papSamplerState; ID3D11RasterizerState1 **papRasterizerState; DXELEMENTLAYOUT *paElementLayout; DXVIEW *paRenderTargetView; DXVIEW *paDepthStencilView; DXVIEW *paShaderResourceView; DXQUERY *paQuery; DXSHADER *paShader; DXSTREAMOUTPUT *paStreamOutput; DXVIEW *paUnorderedAccessView; uint32_t cSOTarget; /* How many SO targets are currently set (SetSOTargets) */ DXBOUNDRESOURCES resources; } VMSVGA3DBACKENDDXCONTEXT; /* Shader disassembler function. Optional. */ typedef HRESULT FN_D3D_DISASSEMBLE(LPCVOID pSrcData, SIZE_T SrcDataSize, UINT Flags, LPCSTR szComments, ID3D10Blob **ppDisassembly); typedef FN_D3D_DISASSEMBLE *PFN_D3D_DISASSEMBLE; typedef struct VMSVGA3DBACKEND { RTLDRMOD hD3D11; PFN_D3D11_CREATE_DEVICE pfnD3D11CreateDevice; RTLDRMOD hD3DCompiler; PFN_D3D_DISASSEMBLE pfnD3DDisassemble; DXDEVICE dxDevice; /* Device for the VMSVGA3D context independent operation. */ DXBOUNDRESOURCES resources; /* What is currently applied to the pipeline. */ bool fSingleDevice; /* Whether to use one DX device for all guest contexts. */ /** @todo Here a set of functions which do different job in single and multiple device modes. */ } VMSVGA3DBACKEND; /* Static function prototypes. */ static int dxDeviceFlush(DXDEVICE *pDevice); static int dxDefineShaderResourceView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId, SVGACOTableDXSRViewEntry const *pEntry); static int dxDefineUnorderedAccessView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, SVGACOTableDXUAViewEntry const *pEntry); static int dxDefineRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGACOTableDXRTViewEntry const *pEntry); static int dxDefineDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, SVGACOTableDXDSViewEntry const *pEntry); static int dxSetRenderTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext); static int dxSetCSUnorderedAccessViews(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext); static DECLCALLBACK(void) vmsvga3dBackSurfaceDestroy(PVGASTATECC pThisCC, bool fClearCOTableEntry, PVMSVGA3DSURFACE pSurface); static int dxDestroyShader(DXSHADER *pDXShader); static int dxDestroyQuery(DXQUERY *pDXQuery); static int dxReadBuffer(DXDEVICE *pDevice, ID3D11Buffer *pBuffer, UINT Offset, UINT Bytes, void **ppvData, uint32_t *pcbData); static HRESULT BlitInit(D3D11BLITTER *pBlitter, ID3D11Device1 *pDevice, ID3D11DeviceContext1 *pImmediateContext); static void BlitRelease(D3D11BLITTER *pBlitter); /* This is not available with the DXVK headers for some reason. */ #ifndef RT_OS_WINDOWS typedef enum D3D11_TEXTURECUBE_FACE { D3D11_TEXTURECUBE_FACE_POSITIVE_X, D3D11_TEXTURECUBE_FACE_NEGATIVE_X, D3D11_TEXTURECUBE_FACE_POSITIVE_Y, D3D11_TEXTURECUBE_FACE_NEGATIVE_Y, D3D11_TEXTURECUBE_FACE_POSITIVE_Z, D3D11_TEXTURECUBE_FACE_NEGATIVE_Z } D3D11_TEXTURECUBE_FACE; #endif DECLINLINE(D3D11_TEXTURECUBE_FACE) vmsvga3dCubemapFaceFromIndex(uint32_t iFace) { D3D11_TEXTURECUBE_FACE Face; switch (iFace) { case 0: Face = D3D11_TEXTURECUBE_FACE_POSITIVE_X; break; case 1: Face = D3D11_TEXTURECUBE_FACE_NEGATIVE_X; break; case 2: Face = D3D11_TEXTURECUBE_FACE_POSITIVE_Y; break; case 3: Face = D3D11_TEXTURECUBE_FACE_NEGATIVE_Y; break; case 4: Face = D3D11_TEXTURECUBE_FACE_POSITIVE_Z; break; default: case 5: Face = D3D11_TEXTURECUBE_FACE_NEGATIVE_Z; break; } return Face; } /* This is to workaround issues with X8 formats, because they can't be used in some operations. */ #define DX_REPLACE_X8_WITH_A8 static DXGI_FORMAT vmsvgaDXSurfaceFormat2Dxgi(SVGA3dSurfaceFormat format) { /* Ensure that correct headers are used. * SVGA3D_AYUV was equal to 45, then replaced with SVGA3D_FORMAT_DEAD2 = 45, and redefined as SVGA3D_AYUV = 152. */ AssertCompile(SVGA3D_AYUV == 152); #define DXGI_FORMAT_ DXGI_FORMAT_UNKNOWN /** @todo More formats. */ switch (format) { #ifdef DX_REPLACE_X8_WITH_A8 case SVGA3D_X8R8G8B8: return DXGI_FORMAT_B8G8R8A8_UNORM; #else case SVGA3D_X8R8G8B8: return DXGI_FORMAT_B8G8R8X8_UNORM; #endif case SVGA3D_A8R8G8B8: return DXGI_FORMAT_B8G8R8A8_UNORM; case SVGA3D_R5G6B5: return DXGI_FORMAT_B5G6R5_UNORM; case SVGA3D_X1R5G5B5: return DXGI_FORMAT_B5G5R5A1_UNORM; case SVGA3D_A1R5G5B5: return DXGI_FORMAT_B5G5R5A1_UNORM; case SVGA3D_A4R4G4B4: break; // 11.1 return DXGI_FORMAT_B4G4R4A4_UNORM; case SVGA3D_Z_D32: break; case SVGA3D_Z_D16: return DXGI_FORMAT_D16_UNORM; case SVGA3D_Z_D24S8: return DXGI_FORMAT_D24_UNORM_S8_UINT; case SVGA3D_Z_D15S1: break; case SVGA3D_LUMINANCE8: return DXGI_FORMAT_; case SVGA3D_LUMINANCE4_ALPHA4: return DXGI_FORMAT_; case SVGA3D_LUMINANCE16: return DXGI_FORMAT_; case SVGA3D_LUMINANCE8_ALPHA8: return DXGI_FORMAT_; case SVGA3D_DXT1: return DXGI_FORMAT_; case SVGA3D_DXT2: return DXGI_FORMAT_; case SVGA3D_DXT3: return DXGI_FORMAT_; case SVGA3D_DXT4: return DXGI_FORMAT_; case SVGA3D_DXT5: return DXGI_FORMAT_; case SVGA3D_BUMPU8V8: return DXGI_FORMAT_; case SVGA3D_BUMPL6V5U5: return DXGI_FORMAT_; case SVGA3D_BUMPX8L8V8U8: return DXGI_FORMAT_; case SVGA3D_FORMAT_DEAD1: break; case SVGA3D_ARGB_S10E5: return DXGI_FORMAT_; case SVGA3D_ARGB_S23E8: return DXGI_FORMAT_; case SVGA3D_A2R10G10B10: return DXGI_FORMAT_; case SVGA3D_V8U8: return DXGI_FORMAT_; case SVGA3D_Q8W8V8U8: return DXGI_FORMAT_; case SVGA3D_CxV8U8: return DXGI_FORMAT_; case SVGA3D_X8L8V8U8: return DXGI_FORMAT_; case SVGA3D_A2W10V10U10: return DXGI_FORMAT_; case SVGA3D_ALPHA8: return DXGI_FORMAT_; case SVGA3D_R_S10E5: return DXGI_FORMAT_; case SVGA3D_R_S23E8: return DXGI_FORMAT_; case SVGA3D_RG_S10E5: return DXGI_FORMAT_; case SVGA3D_RG_S23E8: return DXGI_FORMAT_; case SVGA3D_BUFFER: return DXGI_FORMAT_; case SVGA3D_Z_D24X8: return DXGI_FORMAT_; case SVGA3D_V16U16: return DXGI_FORMAT_; case SVGA3D_G16R16: return DXGI_FORMAT_; case SVGA3D_A16B16G16R16: return DXGI_FORMAT_; case SVGA3D_UYVY: return DXGI_FORMAT_; case SVGA3D_YUY2: return DXGI_FORMAT_; case SVGA3D_NV12: return DXGI_FORMAT_; case SVGA3D_FORMAT_DEAD2: break; /* Old SVGA3D_AYUV */ case SVGA3D_R32G32B32A32_TYPELESS: return DXGI_FORMAT_R32G32B32A32_TYPELESS; case SVGA3D_R32G32B32A32_UINT: return DXGI_FORMAT_R32G32B32A32_UINT; case SVGA3D_R32G32B32A32_SINT: return DXGI_FORMAT_R32G32B32A32_SINT; case SVGA3D_R32G32B32_TYPELESS: return DXGI_FORMAT_R32G32B32_TYPELESS; case SVGA3D_R32G32B32_FLOAT: return DXGI_FORMAT_R32G32B32_FLOAT; case SVGA3D_R32G32B32_UINT: return DXGI_FORMAT_R32G32B32_UINT; case SVGA3D_R32G32B32_SINT: return DXGI_FORMAT_R32G32B32_SINT; case SVGA3D_R16G16B16A16_TYPELESS: return DXGI_FORMAT_R16G16B16A16_TYPELESS; case SVGA3D_R16G16B16A16_UINT: return DXGI_FORMAT_R16G16B16A16_UINT; case SVGA3D_R16G16B16A16_SNORM: return DXGI_FORMAT_R16G16B16A16_SNORM; case SVGA3D_R16G16B16A16_SINT: return DXGI_FORMAT_R16G16B16A16_SINT; case SVGA3D_R32G32_TYPELESS: return DXGI_FORMAT_R32G32_TYPELESS; case SVGA3D_R32G32_UINT: return DXGI_FORMAT_R32G32_UINT; case SVGA3D_R32G32_SINT: return DXGI_FORMAT_R32G32_SINT; case SVGA3D_R32G8X24_TYPELESS: return DXGI_FORMAT_R32G8X24_TYPELESS; case SVGA3D_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; case SVGA3D_R32_FLOAT_X8X24: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; case SVGA3D_X32_G8X24_UINT: return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT; case SVGA3D_R10G10B10A2_TYPELESS: return DXGI_FORMAT_R10G10B10A2_TYPELESS; case SVGA3D_R10G10B10A2_UINT: return DXGI_FORMAT_R10G10B10A2_UINT; case SVGA3D_R11G11B10_FLOAT: return DXGI_FORMAT_R11G11B10_FLOAT; case SVGA3D_R8G8B8A8_TYPELESS: return DXGI_FORMAT_R8G8B8A8_TYPELESS; case SVGA3D_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; case SVGA3D_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; case SVGA3D_R8G8B8A8_UINT: return DXGI_FORMAT_R8G8B8A8_UINT; case SVGA3D_R8G8B8A8_SINT: return DXGI_FORMAT_R8G8B8A8_SINT; case SVGA3D_R16G16_TYPELESS: return DXGI_FORMAT_R16G16_TYPELESS; case SVGA3D_R16G16_UINT: return DXGI_FORMAT_R16G16_UINT; case SVGA3D_R16G16_SINT: return DXGI_FORMAT_R16G16_SINT; case SVGA3D_R32_TYPELESS: return DXGI_FORMAT_R32_TYPELESS; case SVGA3D_D32_FLOAT: return DXGI_FORMAT_D32_FLOAT; case SVGA3D_R32_UINT: return DXGI_FORMAT_R32_UINT; case SVGA3D_R32_SINT: return DXGI_FORMAT_R32_SINT; case SVGA3D_R24G8_TYPELESS: return DXGI_FORMAT_R24G8_TYPELESS; case SVGA3D_D24_UNORM_S8_UINT: return DXGI_FORMAT_D24_UNORM_S8_UINT; case SVGA3D_R24_UNORM_X8: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; case SVGA3D_X24_G8_UINT: return DXGI_FORMAT_X24_TYPELESS_G8_UINT; case SVGA3D_R8G8_TYPELESS: return DXGI_FORMAT_R8G8_TYPELESS; case SVGA3D_R8G8_UNORM: return DXGI_FORMAT_R8G8_UNORM; case SVGA3D_R8G8_UINT: return DXGI_FORMAT_R8G8_UINT; case SVGA3D_R8G8_SINT: return DXGI_FORMAT_R8G8_SINT; case SVGA3D_R16_TYPELESS: return DXGI_FORMAT_R16_TYPELESS; case SVGA3D_R16_UNORM: return DXGI_FORMAT_R16_UNORM; case SVGA3D_R16_UINT: return DXGI_FORMAT_R16_UINT; case SVGA3D_R16_SNORM: return DXGI_FORMAT_R16_SNORM; case SVGA3D_R16_SINT: return DXGI_FORMAT_R16_SINT; case SVGA3D_R8_TYPELESS: return DXGI_FORMAT_R8_TYPELESS; case SVGA3D_R8_UNORM: return DXGI_FORMAT_R8_UNORM; case SVGA3D_R8_UINT: return DXGI_FORMAT_R8_UINT; case SVGA3D_R8_SNORM: return DXGI_FORMAT_R8_SNORM; case SVGA3D_R8_SINT: return DXGI_FORMAT_R8_SINT; case SVGA3D_P8: break; case SVGA3D_R9G9B9E5_SHAREDEXP: return DXGI_FORMAT_R9G9B9E5_SHAREDEXP; case SVGA3D_R8G8_B8G8_UNORM: return DXGI_FORMAT_R8G8_B8G8_UNORM; case SVGA3D_G8R8_G8B8_UNORM: return DXGI_FORMAT_G8R8_G8B8_UNORM; case SVGA3D_BC1_TYPELESS: return DXGI_FORMAT_BC1_TYPELESS; case SVGA3D_BC1_UNORM_SRGB: return DXGI_FORMAT_BC1_UNORM_SRGB; case SVGA3D_BC2_TYPELESS: return DXGI_FORMAT_BC2_TYPELESS; case SVGA3D_BC2_UNORM_SRGB: return DXGI_FORMAT_BC2_UNORM_SRGB; case SVGA3D_BC3_TYPELESS: return DXGI_FORMAT_BC3_TYPELESS; case SVGA3D_BC3_UNORM_SRGB: return DXGI_FORMAT_BC3_UNORM_SRGB; case SVGA3D_BC4_TYPELESS: return DXGI_FORMAT_BC4_TYPELESS; case SVGA3D_ATI1: break; case SVGA3D_BC4_SNORM: return DXGI_FORMAT_BC4_SNORM; case SVGA3D_BC5_TYPELESS: return DXGI_FORMAT_BC5_TYPELESS; case SVGA3D_ATI2: break; case SVGA3D_BC5_SNORM: return DXGI_FORMAT_BC5_SNORM; case SVGA3D_R10G10B10_XR_BIAS_A2_UNORM: return DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM; case SVGA3D_B8G8R8A8_TYPELESS: return DXGI_FORMAT_B8G8R8A8_TYPELESS; case SVGA3D_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; #ifdef DX_REPLACE_X8_WITH_A8 case SVGA3D_B8G8R8X8_TYPELESS: return DXGI_FORMAT_B8G8R8A8_TYPELESS; case SVGA3D_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; #else case SVGA3D_B8G8R8X8_TYPELESS: return DXGI_FORMAT_B8G8R8X8_TYPELESS; case SVGA3D_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; #endif case SVGA3D_Z_DF16: break; case SVGA3D_Z_DF24: break; case SVGA3D_Z_D24S8_INT: return DXGI_FORMAT_D24_UNORM_S8_UINT; case SVGA3D_YV12: break; case SVGA3D_R32G32B32A32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT; case SVGA3D_R16G16B16A16_FLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT; case SVGA3D_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; case SVGA3D_R32G32_FLOAT: return DXGI_FORMAT_R32G32_FLOAT; case SVGA3D_R10G10B10A2_UNORM: return DXGI_FORMAT_R10G10B10A2_UNORM; case SVGA3D_R8G8B8A8_SNORM: return DXGI_FORMAT_R8G8B8A8_SNORM; case SVGA3D_R16G16_FLOAT: return DXGI_FORMAT_R16G16_FLOAT; case SVGA3D_R16G16_UNORM: return DXGI_FORMAT_R16G16_UNORM; case SVGA3D_R16G16_SNORM: return DXGI_FORMAT_R16G16_SNORM; case SVGA3D_R32_FLOAT: return DXGI_FORMAT_R32_FLOAT; case SVGA3D_R8G8_SNORM: return DXGI_FORMAT_R8G8_SNORM; case SVGA3D_R16_FLOAT: return DXGI_FORMAT_R16_FLOAT; case SVGA3D_D16_UNORM: return DXGI_FORMAT_D16_UNORM; case SVGA3D_A8_UNORM: return DXGI_FORMAT_A8_UNORM; case SVGA3D_BC1_UNORM: return DXGI_FORMAT_BC1_UNORM; case SVGA3D_BC2_UNORM: return DXGI_FORMAT_BC2_UNORM; case SVGA3D_BC3_UNORM: return DXGI_FORMAT_BC3_UNORM; case SVGA3D_B5G6R5_UNORM: return DXGI_FORMAT_B5G6R5_UNORM; case SVGA3D_B5G5R5A1_UNORM: return DXGI_FORMAT_B5G5R5A1_UNORM; case SVGA3D_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM; #ifdef DX_REPLACE_X8_WITH_A8 case SVGA3D_B8G8R8X8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM; #else case SVGA3D_B8G8R8X8_UNORM: return DXGI_FORMAT_B8G8R8X8_UNORM; #endif case SVGA3D_BC4_UNORM: return DXGI_FORMAT_BC4_UNORM; case SVGA3D_BC5_UNORM: return DXGI_FORMAT_BC5_UNORM; case SVGA3D_B4G4R4A4_UNORM: return DXGI_FORMAT_; case SVGA3D_BC6H_TYPELESS: return DXGI_FORMAT_BC6H_TYPELESS; case SVGA3D_BC6H_UF16: return DXGI_FORMAT_BC6H_UF16; case SVGA3D_BC6H_SF16: return DXGI_FORMAT_BC6H_SF16; case SVGA3D_BC7_TYPELESS: return DXGI_FORMAT_BC7_TYPELESS; case SVGA3D_BC7_UNORM: return DXGI_FORMAT_BC7_UNORM; case SVGA3D_BC7_UNORM_SRGB: return DXGI_FORMAT_BC7_UNORM_SRGB; case SVGA3D_AYUV: return DXGI_FORMAT_; case SVGA3D_FORMAT_INVALID: case SVGA3D_FORMAT_MAX: break; } // AssertFailed(); return DXGI_FORMAT_UNKNOWN; #undef DXGI_FORMAT_ } static SVGA3dSurfaceFormat vmsvgaDXDevCapSurfaceFmt2Format(SVGA3dDevCapIndex enmDevCap) { switch (enmDevCap) { case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: return SVGA3D_X8R8G8B8; case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: return SVGA3D_A8R8G8B8; case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: return SVGA3D_A2R10G10B10; case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: return SVGA3D_X1R5G5B5; case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: return SVGA3D_A1R5G5B5; case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: return SVGA3D_A4R4G4B4; case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: return SVGA3D_R5G6B5; case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16: return SVGA3D_LUMINANCE16; case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8: return SVGA3D_LUMINANCE8_ALPHA8; case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8: return SVGA3D_ALPHA8; case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8: return SVGA3D_LUMINANCE8; case SVGA3D_DEVCAP_SURFACEFMT_Z_D16: return SVGA3D_Z_D16; case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8: return SVGA3D_Z_D24S8; case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8: return SVGA3D_Z_D24X8; case SVGA3D_DEVCAP_SURFACEFMT_DXT1: return SVGA3D_DXT1; case SVGA3D_DEVCAP_SURFACEFMT_DXT2: return SVGA3D_DXT2; case SVGA3D_DEVCAP_SURFACEFMT_DXT3: return SVGA3D_DXT3; case SVGA3D_DEVCAP_SURFACEFMT_DXT4: return SVGA3D_DXT4; case SVGA3D_DEVCAP_SURFACEFMT_DXT5: return SVGA3D_DXT5; case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8: return SVGA3D_BUMPX8L8V8U8; case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10: return SVGA3D_A2W10V10U10; case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8: return SVGA3D_BUMPU8V8; case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8: return SVGA3D_Q8W8V8U8; case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8: return SVGA3D_CxV8U8; case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5: return SVGA3D_R_S10E5; case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8: return SVGA3D_R_S23E8; case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5: return SVGA3D_RG_S10E5; case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8: return SVGA3D_RG_S23E8; case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5: return SVGA3D_ARGB_S10E5; case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8: return SVGA3D_ARGB_S23E8; case SVGA3D_DEVCAP_SURFACEFMT_V16U16: return SVGA3D_V16U16; case SVGA3D_DEVCAP_SURFACEFMT_G16R16: return SVGA3D_G16R16; case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16: return SVGA3D_A16B16G16R16; case SVGA3D_DEVCAP_SURFACEFMT_UYVY: return SVGA3D_UYVY; case SVGA3D_DEVCAP_SURFACEFMT_YUY2: return SVGA3D_YUY2; case SVGA3D_DEVCAP_SURFACEFMT_NV12: return SVGA3D_NV12; case SVGA3D_DEVCAP_DEAD10: return SVGA3D_FORMAT_DEAD2; /* SVGA3D_DEVCAP_SURFACEFMT_AYUV -> SVGA3D_AYUV */ case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16: return SVGA3D_Z_DF16; case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24: return SVGA3D_Z_DF24; case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: return SVGA3D_Z_D24S8_INT; case SVGA3D_DEVCAP_SURFACEFMT_ATI1: return SVGA3D_ATI1; case SVGA3D_DEVCAP_SURFACEFMT_ATI2: return SVGA3D_ATI2; case SVGA3D_DEVCAP_SURFACEFMT_YV12: return SVGA3D_YV12; default: AssertFailed(); break; } return SVGA3D_FORMAT_INVALID; } static SVGA3dSurfaceFormat vmsvgaDXDevCapDxfmt2Format(SVGA3dDevCapIndex enmDevCap) { switch (enmDevCap) { case SVGA3D_DEVCAP_DXFMT_X8R8G8B8: return SVGA3D_X8R8G8B8; case SVGA3D_DEVCAP_DXFMT_A8R8G8B8: return SVGA3D_A8R8G8B8; case SVGA3D_DEVCAP_DXFMT_R5G6B5: return SVGA3D_R5G6B5; case SVGA3D_DEVCAP_DXFMT_X1R5G5B5: return SVGA3D_X1R5G5B5; case SVGA3D_DEVCAP_DXFMT_A1R5G5B5: return SVGA3D_A1R5G5B5; case SVGA3D_DEVCAP_DXFMT_A4R4G4B4: return SVGA3D_A4R4G4B4; case SVGA3D_DEVCAP_DXFMT_Z_D32: return SVGA3D_Z_D32; case SVGA3D_DEVCAP_DXFMT_Z_D16: return SVGA3D_Z_D16; case SVGA3D_DEVCAP_DXFMT_Z_D24S8: return SVGA3D_Z_D24S8; case SVGA3D_DEVCAP_DXFMT_Z_D15S1: return SVGA3D_Z_D15S1; case SVGA3D_DEVCAP_DXFMT_LUMINANCE8: return SVGA3D_LUMINANCE8; case SVGA3D_DEVCAP_DXFMT_LUMINANCE4_ALPHA4: return SVGA3D_LUMINANCE4_ALPHA4; case SVGA3D_DEVCAP_DXFMT_LUMINANCE16: return SVGA3D_LUMINANCE16; case SVGA3D_DEVCAP_DXFMT_LUMINANCE8_ALPHA8: return SVGA3D_LUMINANCE8_ALPHA8; case SVGA3D_DEVCAP_DXFMT_DXT1: return SVGA3D_DXT1; case SVGA3D_DEVCAP_DXFMT_DXT2: return SVGA3D_DXT2; case SVGA3D_DEVCAP_DXFMT_DXT3: return SVGA3D_DXT3; case SVGA3D_DEVCAP_DXFMT_DXT4: return SVGA3D_DXT4; case SVGA3D_DEVCAP_DXFMT_DXT5: return SVGA3D_DXT5; case SVGA3D_DEVCAP_DXFMT_BUMPU8V8: return SVGA3D_BUMPU8V8; case SVGA3D_DEVCAP_DXFMT_BUMPL6V5U5: return SVGA3D_BUMPL6V5U5; case SVGA3D_DEVCAP_DXFMT_BUMPX8L8V8U8: return SVGA3D_BUMPX8L8V8U8; case SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD1: return SVGA3D_FORMAT_DEAD1; case SVGA3D_DEVCAP_DXFMT_ARGB_S10E5: return SVGA3D_ARGB_S10E5; case SVGA3D_DEVCAP_DXFMT_ARGB_S23E8: return SVGA3D_ARGB_S23E8; case SVGA3D_DEVCAP_DXFMT_A2R10G10B10: return SVGA3D_A2R10G10B10; case SVGA3D_DEVCAP_DXFMT_V8U8: return SVGA3D_V8U8; case SVGA3D_DEVCAP_DXFMT_Q8W8V8U8: return SVGA3D_Q8W8V8U8; case SVGA3D_DEVCAP_DXFMT_CxV8U8: return SVGA3D_CxV8U8; case SVGA3D_DEVCAP_DXFMT_X8L8V8U8: return SVGA3D_X8L8V8U8; case SVGA3D_DEVCAP_DXFMT_A2W10V10U10: return SVGA3D_A2W10V10U10; case SVGA3D_DEVCAP_DXFMT_ALPHA8: return SVGA3D_ALPHA8; case SVGA3D_DEVCAP_DXFMT_R_S10E5: return SVGA3D_R_S10E5; case SVGA3D_DEVCAP_DXFMT_R_S23E8: return SVGA3D_R_S23E8; case SVGA3D_DEVCAP_DXFMT_RG_S10E5: return SVGA3D_RG_S10E5; case SVGA3D_DEVCAP_DXFMT_RG_S23E8: return SVGA3D_RG_S23E8; case SVGA3D_DEVCAP_DXFMT_BUFFER: return SVGA3D_BUFFER; case SVGA3D_DEVCAP_DXFMT_Z_D24X8: return SVGA3D_Z_D24X8; case SVGA3D_DEVCAP_DXFMT_V16U16: return SVGA3D_V16U16; case SVGA3D_DEVCAP_DXFMT_G16R16: return SVGA3D_G16R16; case SVGA3D_DEVCAP_DXFMT_A16B16G16R16: return SVGA3D_A16B16G16R16; case SVGA3D_DEVCAP_DXFMT_UYVY: return SVGA3D_UYVY; case SVGA3D_DEVCAP_DXFMT_YUY2: return SVGA3D_YUY2; case SVGA3D_DEVCAP_DXFMT_NV12: return SVGA3D_NV12; case SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD2: return SVGA3D_FORMAT_DEAD2; /* SVGA3D_DEVCAP_DXFMT_AYUV -> SVGA3D_AYUV */ case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_TYPELESS: return SVGA3D_R32G32B32A32_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_UINT: return SVGA3D_R32G32B32A32_UINT; case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_SINT: return SVGA3D_R32G32B32A32_SINT; case SVGA3D_DEVCAP_DXFMT_R32G32B32_TYPELESS: return SVGA3D_R32G32B32_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R32G32B32_FLOAT: return SVGA3D_R32G32B32_FLOAT; case SVGA3D_DEVCAP_DXFMT_R32G32B32_UINT: return SVGA3D_R32G32B32_UINT; case SVGA3D_DEVCAP_DXFMT_R32G32B32_SINT: return SVGA3D_R32G32B32_SINT; case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_TYPELESS: return SVGA3D_R16G16B16A16_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UINT: return SVGA3D_R16G16B16A16_UINT; case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SNORM: return SVGA3D_R16G16B16A16_SNORM; case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SINT: return SVGA3D_R16G16B16A16_SINT; case SVGA3D_DEVCAP_DXFMT_R32G32_TYPELESS: return SVGA3D_R32G32_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R32G32_UINT: return SVGA3D_R32G32_UINT; case SVGA3D_DEVCAP_DXFMT_R32G32_SINT: return SVGA3D_R32G32_SINT; case SVGA3D_DEVCAP_DXFMT_R32G8X24_TYPELESS: return SVGA3D_R32G8X24_TYPELESS; case SVGA3D_DEVCAP_DXFMT_D32_FLOAT_S8X24_UINT: return SVGA3D_D32_FLOAT_S8X24_UINT; case SVGA3D_DEVCAP_DXFMT_R32_FLOAT_X8X24: return SVGA3D_R32_FLOAT_X8X24; case SVGA3D_DEVCAP_DXFMT_X32_G8X24_UINT: return SVGA3D_X32_G8X24_UINT; case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_TYPELESS: return SVGA3D_R10G10B10A2_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UINT: return SVGA3D_R10G10B10A2_UINT; case SVGA3D_DEVCAP_DXFMT_R11G11B10_FLOAT: return SVGA3D_R11G11B10_FLOAT; case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_TYPELESS: return SVGA3D_R8G8B8A8_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM: return SVGA3D_R8G8B8A8_UNORM; case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM_SRGB: return SVGA3D_R8G8B8A8_UNORM_SRGB; case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UINT: return SVGA3D_R8G8B8A8_UINT; case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SINT: return SVGA3D_R8G8B8A8_SINT; case SVGA3D_DEVCAP_DXFMT_R16G16_TYPELESS: return SVGA3D_R16G16_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R16G16_UINT: return SVGA3D_R16G16_UINT; case SVGA3D_DEVCAP_DXFMT_R16G16_SINT: return SVGA3D_R16G16_SINT; case SVGA3D_DEVCAP_DXFMT_R32_TYPELESS: return SVGA3D_R32_TYPELESS; case SVGA3D_DEVCAP_DXFMT_D32_FLOAT: return SVGA3D_D32_FLOAT; case SVGA3D_DEVCAP_DXFMT_R32_UINT: return SVGA3D_R32_UINT; case SVGA3D_DEVCAP_DXFMT_R32_SINT: return SVGA3D_R32_SINT; case SVGA3D_DEVCAP_DXFMT_R24G8_TYPELESS: return SVGA3D_R24G8_TYPELESS; case SVGA3D_DEVCAP_DXFMT_D24_UNORM_S8_UINT: return SVGA3D_D24_UNORM_S8_UINT; case SVGA3D_DEVCAP_DXFMT_R24_UNORM_X8: return SVGA3D_R24_UNORM_X8; case SVGA3D_DEVCAP_DXFMT_X24_G8_UINT: return SVGA3D_X24_G8_UINT; case SVGA3D_DEVCAP_DXFMT_R8G8_TYPELESS: return SVGA3D_R8G8_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R8G8_UNORM: return SVGA3D_R8G8_UNORM; case SVGA3D_DEVCAP_DXFMT_R8G8_UINT: return SVGA3D_R8G8_UINT; case SVGA3D_DEVCAP_DXFMT_R8G8_SINT: return SVGA3D_R8G8_SINT; case SVGA3D_DEVCAP_DXFMT_R16_TYPELESS: return SVGA3D_R16_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R16_UNORM: return SVGA3D_R16_UNORM; case SVGA3D_DEVCAP_DXFMT_R16_UINT: return SVGA3D_R16_UINT; case SVGA3D_DEVCAP_DXFMT_R16_SNORM: return SVGA3D_R16_SNORM; case SVGA3D_DEVCAP_DXFMT_R16_SINT: return SVGA3D_R16_SINT; case SVGA3D_DEVCAP_DXFMT_R8_TYPELESS: return SVGA3D_R8_TYPELESS; case SVGA3D_DEVCAP_DXFMT_R8_UNORM: return SVGA3D_R8_UNORM; case SVGA3D_DEVCAP_DXFMT_R8_UINT: return SVGA3D_R8_UINT; case SVGA3D_DEVCAP_DXFMT_R8_SNORM: return SVGA3D_R8_SNORM; case SVGA3D_DEVCAP_DXFMT_R8_SINT: return SVGA3D_R8_SINT; case SVGA3D_DEVCAP_DXFMT_P8: return SVGA3D_P8; case SVGA3D_DEVCAP_DXFMT_R9G9B9E5_SHAREDEXP: return SVGA3D_R9G9B9E5_SHAREDEXP; case SVGA3D_DEVCAP_DXFMT_R8G8_B8G8_UNORM: return SVGA3D_R8G8_B8G8_UNORM; case SVGA3D_DEVCAP_DXFMT_G8R8_G8B8_UNORM: return SVGA3D_G8R8_G8B8_UNORM; case SVGA3D_DEVCAP_DXFMT_BC1_TYPELESS: return SVGA3D_BC1_TYPELESS; case SVGA3D_DEVCAP_DXFMT_BC1_UNORM_SRGB: return SVGA3D_BC1_UNORM_SRGB; case SVGA3D_DEVCAP_DXFMT_BC2_TYPELESS: return SVGA3D_BC2_TYPELESS; case SVGA3D_DEVCAP_DXFMT_BC2_UNORM_SRGB: return SVGA3D_BC2_UNORM_SRGB; case SVGA3D_DEVCAP_DXFMT_BC3_TYPELESS: return SVGA3D_BC3_TYPELESS; case SVGA3D_DEVCAP_DXFMT_BC3_UNORM_SRGB: return SVGA3D_BC3_UNORM_SRGB; case SVGA3D_DEVCAP_DXFMT_BC4_TYPELESS: return SVGA3D_BC4_TYPELESS; case SVGA3D_DEVCAP_DXFMT_ATI1: return SVGA3D_ATI1; case SVGA3D_DEVCAP_DXFMT_BC4_SNORM: return SVGA3D_BC4_SNORM; case SVGA3D_DEVCAP_DXFMT_BC5_TYPELESS: return SVGA3D_BC5_TYPELESS; case SVGA3D_DEVCAP_DXFMT_ATI2: return SVGA3D_ATI2; case SVGA3D_DEVCAP_DXFMT_BC5_SNORM: return SVGA3D_BC5_SNORM; case SVGA3D_DEVCAP_DXFMT_R10G10B10_XR_BIAS_A2_UNORM: return SVGA3D_R10G10B10_XR_BIAS_A2_UNORM; case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_TYPELESS: return SVGA3D_B8G8R8A8_TYPELESS; case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM_SRGB: return SVGA3D_B8G8R8A8_UNORM_SRGB; case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_TYPELESS: return SVGA3D_B8G8R8X8_TYPELESS; case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM_SRGB: return SVGA3D_B8G8R8X8_UNORM_SRGB; case SVGA3D_DEVCAP_DXFMT_Z_DF16: return SVGA3D_Z_DF16; case SVGA3D_DEVCAP_DXFMT_Z_DF24: return SVGA3D_Z_DF24; case SVGA3D_DEVCAP_DXFMT_Z_D24S8_INT: return SVGA3D_Z_D24S8_INT; case SVGA3D_DEVCAP_DXFMT_YV12: return SVGA3D_YV12; case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_FLOAT: return SVGA3D_R32G32B32A32_FLOAT; case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_FLOAT: return SVGA3D_R16G16B16A16_FLOAT; case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UNORM: return SVGA3D_R16G16B16A16_UNORM; case SVGA3D_DEVCAP_DXFMT_R32G32_FLOAT: return SVGA3D_R32G32_FLOAT; case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UNORM: return SVGA3D_R10G10B10A2_UNORM; case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SNORM: return SVGA3D_R8G8B8A8_SNORM; case SVGA3D_DEVCAP_DXFMT_R16G16_FLOAT: return SVGA3D_R16G16_FLOAT; case SVGA3D_DEVCAP_DXFMT_R16G16_UNORM: return SVGA3D_R16G16_UNORM; case SVGA3D_DEVCAP_DXFMT_R16G16_SNORM: return SVGA3D_R16G16_SNORM; case SVGA3D_DEVCAP_DXFMT_R32_FLOAT: return SVGA3D_R32_FLOAT; case SVGA3D_DEVCAP_DXFMT_R8G8_SNORM: return SVGA3D_R8G8_SNORM; case SVGA3D_DEVCAP_DXFMT_R16_FLOAT: return SVGA3D_R16_FLOAT; case SVGA3D_DEVCAP_DXFMT_D16_UNORM: return SVGA3D_D16_UNORM; case SVGA3D_DEVCAP_DXFMT_A8_UNORM: return SVGA3D_A8_UNORM; case SVGA3D_DEVCAP_DXFMT_BC1_UNORM: return SVGA3D_BC1_UNORM; case SVGA3D_DEVCAP_DXFMT_BC2_UNORM: return SVGA3D_BC2_UNORM; case SVGA3D_DEVCAP_DXFMT_BC3_UNORM: return SVGA3D_BC3_UNORM; case SVGA3D_DEVCAP_DXFMT_B5G6R5_UNORM: return SVGA3D_B5G6R5_UNORM; case SVGA3D_DEVCAP_DXFMT_B5G5R5A1_UNORM: return SVGA3D_B5G5R5A1_UNORM; case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM: return SVGA3D_B8G8R8A8_UNORM; case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM: return SVGA3D_B8G8R8X8_UNORM; case SVGA3D_DEVCAP_DXFMT_BC4_UNORM: return SVGA3D_BC4_UNORM; case SVGA3D_DEVCAP_DXFMT_BC5_UNORM: return SVGA3D_BC5_UNORM; case SVGA3D_DEVCAP_DXFMT_BC6H_TYPELESS: return SVGA3D_BC6H_TYPELESS; case SVGA3D_DEVCAP_DXFMT_BC6H_UF16: return SVGA3D_BC6H_UF16; case SVGA3D_DEVCAP_DXFMT_BC6H_SF16: return SVGA3D_BC6H_SF16; case SVGA3D_DEVCAP_DXFMT_BC7_TYPELESS: return SVGA3D_BC7_TYPELESS; case SVGA3D_DEVCAP_DXFMT_BC7_UNORM: return SVGA3D_BC7_UNORM; case SVGA3D_DEVCAP_DXFMT_BC7_UNORM_SRGB: return SVGA3D_BC7_UNORM_SRGB; default: AssertFailed(); break; } return SVGA3D_FORMAT_INVALID; } static int vmsvgaDXCheckFormatSupportPreDX(PVMSVGA3DSTATE pState, SVGA3dSurfaceFormat enmFormat, uint32_t *pu32DevCap) { int rc = VINF_SUCCESS; *pu32DevCap = 0; DXGI_FORMAT const dxgiFormat = vmsvgaDXSurfaceFormat2Dxgi(enmFormat); if (dxgiFormat != DXGI_FORMAT_UNKNOWN) { RT_NOREF(pState); /** @todo Implement */ } else rc = VERR_NOT_SUPPORTED; return rc; } static int vmsvgaDXCheckFormatSupport(PVMSVGA3DSTATE pState, SVGA3dSurfaceFormat enmFormat, uint32_t *pu32DevCap) { int rc = VINF_SUCCESS; *pu32DevCap = 0; DXGI_FORMAT const dxgiFormat = vmsvgaDXSurfaceFormat2Dxgi(enmFormat); if (dxgiFormat != DXGI_FORMAT_UNKNOWN) { ID3D11Device *pDevice = pState->pBackend->dxDevice.pDevice; UINT FormatSupport = 0; HRESULT hr = pDevice->CheckFormatSupport(dxgiFormat, &FormatSupport); if (SUCCEEDED(hr)) { *pu32DevCap |= SVGA3D_DXFMT_SUPPORTED; if (FormatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) *pu32DevCap |= SVGA3D_DXFMT_SHADER_SAMPLE; if (FormatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET) *pu32DevCap |= SVGA3D_DXFMT_COLOR_RENDERTARGET; if (FormatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) *pu32DevCap |= SVGA3D_DXFMT_DEPTH_RENDERTARGET; if (FormatSupport & D3D11_FORMAT_SUPPORT_BLENDABLE) *pu32DevCap |= SVGA3D_DXFMT_BLENDABLE; if (FormatSupport & D3D11_FORMAT_SUPPORT_MIP) *pu32DevCap |= SVGA3D_DXFMT_MIPS; if (FormatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) *pu32DevCap |= SVGA3D_DXFMT_ARRAY; if (FormatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) *pu32DevCap |= SVGA3D_DXFMT_VOLUME; if (FormatSupport & D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER) *pu32DevCap |= SVGA3D_DXFMT_DX_VERTEX_BUFFER; UINT NumQualityLevels; hr = pDevice->CheckMultisampleQualityLevels(dxgiFormat, 2, &NumQualityLevels); if (SUCCEEDED(hr) && NumQualityLevels != 0) *pu32DevCap |= SVGA3D_DXFMT_MULTISAMPLE; } else { LogFunc(("CheckFormatSupport failed for 0x%08x, hr = 0x%08x\n", dxgiFormat, hr)); rc = VERR_NOT_SUPPORTED; } } else rc = VERR_NOT_SUPPORTED; return rc; } static int dxDeviceCreate(PVMSVGA3DBACKEND pBackend, DXDEVICE *pDXDevice) { int rc = VINF_SUCCESS; if (pBackend->fSingleDevice && pBackend->dxDevice.pDevice) { pDXDevice->pDevice = pBackend->dxDevice.pDevice; pDXDevice->pDevice->AddRef(); pDXDevice->pImmediateContext = pBackend->dxDevice.pImmediateContext; pDXDevice->pImmediateContext->AddRef(); pDXDevice->pDxgiFactory = pBackend->dxDevice.pDxgiFactory; pDXDevice->pDxgiFactory->AddRef(); pDXDevice->FeatureLevel = pBackend->dxDevice.FeatureLevel; #ifdef DX_COMMON_STAGING_BUFFER pDXDevice->pStagingBuffer = 0; pDXDevice->cbStagingBuffer = 0; #endif BlitInit(&pDXDevice->Blitter, pDXDevice->pDevice, pDXDevice->pImmediateContext); return rc; } IDXGIAdapter *pAdapter = NULL; /* Default adapter. */ static D3D_FEATURE_LEVEL const s_aFeatureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0 }; UINT Flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #ifdef DEBUG Flags |= D3D11_CREATE_DEVICE_DEBUG; #endif ID3D11Device *pDevice = 0; ID3D11DeviceContext *pImmediateContext = 0; HRESULT hr = pBackend->pfnD3D11CreateDevice(pAdapter, D3D_DRIVER_TYPE_HARDWARE, NULL, Flags, s_aFeatureLevels, RT_ELEMENTS(s_aFeatureLevels), D3D11_SDK_VERSION, &pDevice, &pDXDevice->FeatureLevel, &pImmediateContext); #ifdef DEBUG if (FAILED(hr)) { /* Device creation may fail because _DEBUG flag requires "D3D11 SDK Layers for Windows 10" ("Graphics Tools"): * Settings/System/Apps/Optional features/Add a feature/Graphics Tools * Retry without the flag. */ Flags &= ~D3D11_CREATE_DEVICE_DEBUG; hr = pBackend->pfnD3D11CreateDevice(pAdapter, D3D_DRIVER_TYPE_HARDWARE, NULL, Flags, s_aFeatureLevels, RT_ELEMENTS(s_aFeatureLevels), D3D11_SDK_VERSION, &pDevice, &pDXDevice->FeatureLevel, &pImmediateContext); } #endif if (SUCCEEDED(hr)) { LogRel(("VMSVGA: Feature level %#x\n", pDXDevice->FeatureLevel)); hr = pDevice->QueryInterface(__uuidof(ID3D11Device1), (void**)&pDXDevice->pDevice); AssertReturnStmt(SUCCEEDED(hr), D3D_RELEASE(pImmediateContext); D3D_RELEASE(pDevice), VERR_NOT_SUPPORTED); hr = pImmediateContext->QueryInterface(__uuidof(ID3D11DeviceContext1), (void**)&pDXDevice->pImmediateContext); AssertReturnStmt(SUCCEEDED(hr), D3D_RELEASE(pImmediateContext); D3D_RELEASE(pDXDevice->pDevice); D3D_RELEASE(pDevice), VERR_NOT_SUPPORTED); #ifdef DEBUG /* Break into debugger when DX runtime detects anything unusual. */ HRESULT hr2; ID3D11Debug *pDebug = 0; hr2 = pDXDevice->pDevice->QueryInterface(__uuidof(ID3D11Debug), (void**)&pDebug); if (SUCCEEDED(hr2)) { ID3D11InfoQueue *pInfoQueue = 0; hr2 = pDebug->QueryInterface(__uuidof(ID3D11InfoQueue), (void**)&pInfoQueue); if (SUCCEEDED(hr2)) { pInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); // pInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); // pInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, true); /* No breakpoints for the following messages. */ D3D11_MESSAGE_ID saIgnoredMessageIds[] = { /* Message ID: Caused by: */ D3D11_MESSAGE_ID_CREATEINPUTLAYOUT_TYPE_MISMATCH, /* Autogenerated input signatures. */ D3D11_MESSAGE_ID_LIVE_DEVICE, /* Live object report. Does not seem to prevent a breakpoint. */ (D3D11_MESSAGE_ID)3146081 /*DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET*/, /* U. */ D3D11_MESSAGE_ID_DEVICE_DRAW_SAMPLER_NOT_SET, /* U. */ D3D11_MESSAGE_ID_DEVICE_DRAW_SAMPLER_MISMATCH, /* U. */ D3D11_MESSAGE_ID_CREATEINPUTLAYOUT_EMPTY_LAYOUT, /* P. */ D3D11_MESSAGE_ID_DEVICE_SHADER_LINKAGE_REGISTERMASK, /* S. */ }; D3D11_INFO_QUEUE_FILTER filter; RT_ZERO(filter); filter.DenyList.NumIDs = RT_ELEMENTS(saIgnoredMessageIds); filter.DenyList.pIDList = saIgnoredMessageIds; pInfoQueue->AddStorageFilterEntries(&filter); D3D_RELEASE(pInfoQueue); } D3D_RELEASE(pDebug); } #endif IDXGIDevice *pDxgiDevice = 0; hr = pDXDevice->pDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDxgiDevice); if (SUCCEEDED(hr)) { IDXGIAdapter *pDxgiAdapter = 0; hr = pDxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&pDxgiAdapter); if (SUCCEEDED(hr)) { hr = pDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&pDXDevice->pDxgiFactory); D3D_RELEASE(pDxgiAdapter); } D3D_RELEASE(pDxgiDevice); } } if (SUCCEEDED(hr)) BlitInit(&pDXDevice->Blitter, pDXDevice->pDevice, pDXDevice->pImmediateContext); else rc = VERR_NOT_SUPPORTED; return rc; } static void dxDeviceDestroy(PVMSVGA3DBACKEND pBackend, DXDEVICE *pDevice) { RT_NOREF(pBackend); BlitRelease(&pDevice->Blitter); #ifdef DX_COMMON_STAGING_BUFFER D3D_RELEASE(pDevice->pStagingBuffer); #endif D3D_RELEASE(pDevice->pDxgiFactory); D3D_RELEASE(pDevice->pImmediateContext); #ifdef DEBUG HRESULT hr2; ID3D11Debug *pDebug = 0; hr2 = pDevice->pDevice->QueryInterface(__uuidof(ID3D11Debug), (void**)&pDebug); if (SUCCEEDED(hr2)) { /// @todo Use this to see whether all resources have been properly released. //DEBUG_BREAKPOINT_TEST(); //pDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL | (D3D11_RLDO_FLAGS)0x4 /*D3D11_RLDO_IGNORE_INTERNAL*/); D3D_RELEASE(pDebug); } #endif D3D_RELEASE(pDevice->pDevice); RT_ZERO(*pDevice); } static void dxViewAddToList(PVGASTATECC pThisCC, DXVIEW *pDXView) { LogFunc(("cid = %u, sid = %u, viewId = %u, type = %u\n", pDXView->cid, pDXView->sid, pDXView->viewId, pDXView->enmViewType)); Assert(pDXView->u.pView); /* Only already created views should be added. Guard against mis-use by callers. */ PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pDXView->sid, &pSurface); AssertRCReturnVoid(rc); RTListAppend(&pSurface->pBackendSurface->listView, &pDXView->nodeSurfaceView); } static void dxViewRemoveFromList(DXVIEW *pDXView) { LogFunc(("cid = %u, sid = %u, viewId = %u, type = %u\n", pDXView->cid, pDXView->sid, pDXView->viewId, pDXView->enmViewType)); /* pView can be NULL, if COT entry is already empty. */ if (pDXView->u.pView) { Assert(pDXView->nodeSurfaceView.pNext && pDXView->nodeSurfaceView.pPrev); RTListNodeRemove(&pDXView->nodeSurfaceView); } } static int dxViewDestroy(DXVIEW *pDXView) { LogFunc(("cid = %u, sid = %u, viewId = %u, type = %u\n", pDXView->cid, pDXView->sid, pDXView->viewId, pDXView->enmViewType)); if (pDXView->u.pView) { D3D_RELEASE(pDXView->u.pView); RTListNodeRemove(&pDXView->nodeSurfaceView); RT_ZERO(*pDXView); } return VINF_SUCCESS; } static int dxViewInit(DXVIEW *pDXView, PVMSVGA3DSURFACE pSurface, VMSVGA3DDXCONTEXT *pDXContext, uint32_t viewId, VMSVGA3DBACKVIEWTYPE enmViewType, ID3D11View *pView) { pDXView->cid = pDXContext->cid; pDXView->sid = pSurface->id; pDXView->viewId = viewId; pDXView->enmViewType = enmViewType; pDXView->u.pView = pView; RTListAppend(&pSurface->pBackendSurface->listView, &pDXView->nodeSurfaceView); LogFunc(("cid = %u, sid = %u, viewId = %u, type = %u\n", pDXView->cid, pDXView->sid, pDXView->viewId, pDXView->enmViewType)); DXVIEW *pIter, *pNext; RTListForEachSafe(&pSurface->pBackendSurface->listView, pIter, pNext, DXVIEW, nodeSurfaceView) { AssertPtr(pNext); LogFunc(("pIter=%p, pNext=%p\n", pIter, pNext)); } return VINF_SUCCESS; } DECLINLINE(bool) dxIsSurfaceShareable(PVMSVGA3DSURFACE pSurface) { /* It is not expected that volume textures will be shared between contexts. */ if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_VOLUME) return false; return (pSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) || (pSurface->f.surfaceFlags & SVGA3D_SURFACE_BIND_RENDER_TARGET); } static DXDEVICE *dxDeviceFromCid(uint32_t cid, PVMSVGA3DSTATE pState) { if (cid != DX_CID_BACKEND) { if (pState->pBackend->fSingleDevice) return &pState->pBackend->dxDevice; VMSVGA3DDXCONTEXT *pDXContext; int rc = vmsvga3dDXContextFromCid(pState, cid, &pDXContext); if (RT_SUCCESS(rc)) return &pDXContext->pBackendDXContext->dxDevice; } else return &pState->pBackend->dxDevice; AssertFailed(); return NULL; } static DXDEVICE *dxDeviceFromContext(PVMSVGA3DSTATE p3dState, VMSVGA3DDXCONTEXT *pDXContext) { if (pDXContext && !p3dState->pBackend->fSingleDevice) return &pDXContext->pBackendDXContext->dxDevice; return &p3dState->pBackend->dxDevice; } static int dxDeviceFlush(DXDEVICE *pDevice) { /** @todo Should the flush follow the query submission? */ pDevice->pImmediateContext->Flush(); ID3D11Query *pQuery = 0; D3D11_QUERY_DESC qd; RT_ZERO(qd); qd.Query = D3D11_QUERY_EVENT; HRESULT hr = pDevice->pDevice->CreateQuery(&qd, &pQuery); Assert(hr == S_OK); RT_NOREF(hr); pDevice->pImmediateContext->End(pQuery); BOOL queryData; while (pDevice->pImmediateContext->GetData(pQuery, &queryData, sizeof(queryData), 0) != S_OK) RTThreadYield(); D3D_RELEASE(pQuery); return VINF_SUCCESS; } static int dxContextWait(uint32_t cidDrawing, PVMSVGA3DSTATE pState) { if (pState->pBackend->fSingleDevice) return VINF_SUCCESS; /* Flush cidDrawing context and issue a query. */ DXDEVICE *pDXDevice = dxDeviceFromCid(cidDrawing, pState); if (pDXDevice) return dxDeviceFlush(pDXDevice); /* cidDrawing does not exist anymore. */ return VINF_SUCCESS; } static int dxSurfaceWait(PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, uint32_t cidRequesting) { if (pState->pBackend->fSingleDevice) return VINF_SUCCESS; VMSVGA3DBACKENDSURFACE *pBackendSurface = pSurface->pBackendSurface; if (!pBackendSurface) AssertFailedReturn(VERR_INVALID_STATE); int rc = VINF_SUCCESS; if (pBackendSurface->cidDrawing != SVGA_ID_INVALID) { if (pBackendSurface->cidDrawing != cidRequesting) { LogFunc(("sid = %u, assoc cid = %u, drawing cid = %u, req cid = %u\n", pSurface->id, pSurface->idAssociatedContext, pBackendSurface->cidDrawing, cidRequesting)); Assert(dxIsSurfaceShareable(pSurface)); rc = dxContextWait(pBackendSurface->cidDrawing, pState); pBackendSurface->cidDrawing = SVGA_ID_INVALID; } } return rc; } static ID3D11Resource *dxResource(PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, VMSVGA3DDXCONTEXT *pDXContext) { VMSVGA3DBACKENDSURFACE *pBackendSurface = pSurface->pBackendSurface; if (!pBackendSurface) AssertFailedReturn(NULL); ID3D11Resource *pResource; uint32_t const cidRequesting = pDXContext ? pDXContext->cid : DX_CID_BACKEND; if (cidRequesting == pSurface->idAssociatedContext || pState->pBackend->fSingleDevice) pResource = pBackendSurface->u.pResource; else { /* * Context, which as not created the surface, is requesting. */ AssertReturn(pDXContext, NULL); Assert(dxIsSurfaceShareable(pSurface)); Assert(pSurface->idAssociatedContext == DX_CID_BACKEND); DXSHAREDTEXTURE *pSharedTexture = (DXSHAREDTEXTURE *)RTAvlU32Get(&pBackendSurface->SharedTextureTree, pDXContext->cid); if (!pSharedTexture) { DXDEVICE *pDevice = dxDeviceFromContext(pState, pDXContext); AssertReturn(pDevice->pDevice, NULL); AssertReturn(pBackendSurface->SharedHandle, NULL); /* This context has not yet opened the texture. */ pSharedTexture = (DXSHAREDTEXTURE *)RTMemAllocZ(sizeof(DXSHAREDTEXTURE)); AssertReturn(pSharedTexture, NULL); pSharedTexture->Core.Key = pDXContext->cid; bool const fSuccess = RTAvlU32Insert(&pBackendSurface->SharedTextureTree, &pSharedTexture->Core); AssertReturn(fSuccess, NULL); HRESULT hr = pDevice->pDevice->OpenSharedResource(pBackendSurface->SharedHandle, __uuidof(ID3D11Texture2D), (void**)&pSharedTexture->pTexture); Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) pSharedTexture->sid = pSurface->id; else { RTAvlU32Remove(&pBackendSurface->SharedTextureTree, pDXContext->cid); RTMemFree(pSharedTexture); return NULL; } } pResource = pSharedTexture->pTexture; } /* Wait for drawing to finish. */ dxSurfaceWait(pState, pSurface, cidRequesting); return pResource; } static uint32_t dxGetRenderTargetViewSid(PVMSVGA3DDXCONTEXT pDXContext, uint32_t renderTargetViewId) { ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->cot.cRTView, SVGA_ID_INVALID); SVGACOTableDXRTViewEntry const *pRTViewEntry = &pDXContext->cot.paRTView[renderTargetViewId]; return pRTViewEntry->sid; } static SVGACOTableDXSRViewEntry const *dxGetShaderResourceViewEntry(PVMSVGA3DDXCONTEXT pDXContext, uint32_t shaderResourceViewId) { ASSERT_GUEST_RETURN(shaderResourceViewId < pDXContext->cot.cSRView, NULL); SVGACOTableDXSRViewEntry const *pSRViewEntry = &pDXContext->cot.paSRView[shaderResourceViewId]; return pSRViewEntry; } static SVGACOTableDXUAViewEntry const *dxGetUnorderedAccessViewEntry(PVMSVGA3DDXCONTEXT pDXContext, uint32_t uaViewId) { ASSERT_GUEST_RETURN(uaViewId < pDXContext->cot.cUAView, NULL); SVGACOTableDXUAViewEntry const *pUAViewEntry = &pDXContext->cot.paUAView[uaViewId]; return pUAViewEntry; } static SVGACOTableDXDSViewEntry const *dxGetDepthStencilViewEntry(PVMSVGA3DDXCONTEXT pDXContext, uint32_t depthStencilViewId) { ASSERT_GUEST_RETURN(depthStencilViewId < pDXContext->cot.cDSView, NULL); SVGACOTableDXDSViewEntry const *pDSViewEntry = &pDXContext->cot.paDSView[depthStencilViewId]; return pDSViewEntry; } static SVGACOTableDXRTViewEntry const *dxGetRenderTargetViewEntry(PVMSVGA3DDXCONTEXT pDXContext, uint32_t renderTargetViewId) { ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->cot.cRTView, NULL); SVGACOTableDXRTViewEntry const *pRTViewEntry = &pDXContext->cot.paRTView[renderTargetViewId]; return pRTViewEntry; } static int dxTrackRenderTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); for (unsigned long i = 0; i < RT_ELEMENTS(pDXContext->svgaDXContext.renderState.renderTargetViewIds); ++i) { uint32_t const renderTargetViewId = pDXContext->svgaDXContext.renderState.renderTargetViewIds[i]; if (renderTargetViewId == SVGA_ID_INVALID) continue; uint32_t const sid = dxGetRenderTargetViewSid(pDXContext, renderTargetViewId); LogFunc(("[%u] sid = %u, drawing cid = %u\n", i, sid, pDXContext->cid)); PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); if (RT_SUCCESS(rc)) { AssertContinue(pSurface->pBackendSurface); pSurface->pBackendSurface->cidDrawing = pDXContext->cid; } } return VINF_SUCCESS; } static int dxDefineStreamOutput(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid, SVGACOTableDXStreamOutputEntry const *pEntry, DXSHADER *pDXShader) { PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; /* Make D3D11_SO_DECLARATION_ENTRY array from SVGA3dStreamOutputDeclarationEntry. */ SVGA3dStreamOutputDeclarationEntry const *paDecls; PVMSVGAMOB pMob = NULL; if (pEntry->usesMob) { pMob = vmsvgaR3MobGet(pSvgaR3State, pEntry->mobid); ASSERT_GUEST_RETURN(pMob, VERR_INVALID_PARAMETER); /* Create a memory pointer for the MOB, which is accessible by host. */ int rc = vmsvgaR3MobBackingStoreCreate(pSvgaR3State, pMob, vmsvgaR3MobSize(pMob)); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); /* Get pointer to the shader bytecode. This will also verify the offset. */ paDecls = (SVGA3dStreamOutputDeclarationEntry const *)vmsvgaR3MobBackingStorePtr(pMob, pEntry->offsetInBytes); AssertReturnStmt(paDecls, vmsvgaR3MobBackingStoreDelete(pSvgaR3State, pMob), VERR_INTERNAL_ERROR); } else paDecls = &pEntry->decl[0]; pDXStreamOutput->cDeclarationEntry = pEntry->numOutputStreamEntries; for (uint32_t i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) { D3D11_SO_DECLARATION_ENTRY *pDst = &pDXStreamOutput->aDeclarationEntry[i]; SVGA3dStreamOutputDeclarationEntry const *pSrc = &paDecls[i]; uint32_t const registerMask = pSrc->registerMask & 0xF; unsigned const iFirstBit = ASMBitFirstSetU32(registerMask); unsigned const iLastBit = ASMBitLastSetU32(registerMask); pDst->Stream = pSrc->stream; pDst->SemanticName = NULL; /* Semantic name and index will be taken from the shader output declaration. */ pDst->SemanticIndex = 0; pDst->StartComponent = iFirstBit > 0 ? iFirstBit - 1 : 0; pDst->ComponentCount = iFirstBit > 0 ? iLastBit - (iFirstBit - 1) : 0; pDst->OutputSlot = pSrc->outputSlot; } uint32_t MaxSemanticIndex = 0; for (uint32_t i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) { D3D11_SO_DECLARATION_ENTRY *pDeclarationEntry = &pDXStreamOutput->aDeclarationEntry[i]; SVGA3dStreamOutputDeclarationEntry const *decl = &paDecls[i]; /* Find the corresponding register and mask in the GS shader output. */ int idxFound = -1; for (uint32_t iOutputEntry = 0; iOutputEntry < pDXShader->shaderInfo.cOutputSignature; ++iOutputEntry) { SVGA3dDXSignatureEntry const *pOutputEntry = &pDXShader->shaderInfo.aOutputSignature[iOutputEntry]; if ( pOutputEntry->registerIndex == decl->registerIndex && (decl->registerMask & ~pOutputEntry->mask) == 0) /* SO decl mask is a subset of shader output mask. */ { idxFound = iOutputEntry; break; } } if (idxFound >= 0) { DXShaderAttributeSemantic const *pOutputSemantic = &pDXShader->shaderInfo.aOutputSemantic[idxFound]; pDeclarationEntry->SemanticName = pOutputSemantic->pcszSemanticName; pDeclarationEntry->SemanticIndex = pOutputSemantic->SemanticIndex; MaxSemanticIndex = RT_MAX(MaxSemanticIndex, pOutputSemantic->SemanticIndex); } else AssertFailed(); } /* A geometry shader may return components of the same register as different attributes: * * Output signature * Name Index Mask Register * ATTRIB 2 xy 2 * ATTRIB 3 z 2 * * For ATTRIB 3 the stream output declaration expects StartComponent = 0 and ComponentCount = 1 * (not StartComponent = 2 and ComponentCount = 1): * * Stream output declaration * SemanticName SemanticIndex StartComponent ComponentCount * ATTRIB 2 0 2 * ATTRIB 3 0 1 * * Stream output declaration can have multiple entries for the same attribute. * In this case StartComponent is the offset within the attribute. * * Output signature * Name Index Mask Register * ATTRIB 0 xyzw 0 * * Stream output declaration * SemanticName SemanticIndex StartComponent ComponentCount * ATTRIB 0 0 1 * ATTRIB 0 1 1 * * StartComponent has been computed as the component offset in a register: * 'StartComponent = iFirstBit > 0 ? iFirstBit - 1 : 0;'. * * StartComponent must be the offset in an attribute. */ for (uint32_t SemanticIndex = 0; SemanticIndex <= MaxSemanticIndex; ++SemanticIndex) { /* Find minimum StartComponent value for this attribute. */ uint32_t MinStartComponent = UINT32_MAX; for (uint32_t i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) { D3D11_SO_DECLARATION_ENTRY *pDeclarationEntry = &pDXStreamOutput->aDeclarationEntry[i]; if (pDeclarationEntry->SemanticIndex == SemanticIndex) MinStartComponent = RT_MIN(MinStartComponent, pDeclarationEntry->StartComponent); } AssertContinue(MinStartComponent != UINT32_MAX); /* Adjust the StartComponent to start from 0 for this attribute. */ for (uint32_t i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) { D3D11_SO_DECLARATION_ENTRY *pDeclarationEntry = &pDXStreamOutput->aDeclarationEntry[i]; if (pDeclarationEntry->SemanticIndex == SemanticIndex) pDeclarationEntry->StartComponent -= MinStartComponent; } } if (pMob) vmsvgaR3MobBackingStoreDelete(pSvgaR3State, pMob); return VINF_SUCCESS; } static void dxDestroyStreamOutput(DXSTREAMOUTPUT *pDXStreamOutput) { RT_ZERO(*pDXStreamOutput); } static D3D11_BLEND dxBlendFactorAlpha(uint8_t svgaBlend) { /* "Blend options that end in _COLOR are not allowed." but the guest sometimes sends them. */ switch (svgaBlend) { case SVGA3D_BLENDOP_ZERO: return D3D11_BLEND_ZERO; case SVGA3D_BLENDOP_ONE: return D3D11_BLEND_ONE; case SVGA3D_BLENDOP_SRCCOLOR: return D3D11_BLEND_SRC_ALPHA; case SVGA3D_BLENDOP_INVSRCCOLOR: return D3D11_BLEND_INV_SRC_ALPHA; case SVGA3D_BLENDOP_SRCALPHA: return D3D11_BLEND_SRC_ALPHA; case SVGA3D_BLENDOP_INVSRCALPHA: return D3D11_BLEND_INV_SRC_ALPHA; case SVGA3D_BLENDOP_DESTALPHA: return D3D11_BLEND_DEST_ALPHA; case SVGA3D_BLENDOP_INVDESTALPHA: return D3D11_BLEND_INV_DEST_ALPHA; case SVGA3D_BLENDOP_DESTCOLOR: return D3D11_BLEND_DEST_ALPHA; case SVGA3D_BLENDOP_INVDESTCOLOR: return D3D11_BLEND_INV_DEST_ALPHA; case SVGA3D_BLENDOP_SRCALPHASAT: return D3D11_BLEND_SRC_ALPHA_SAT; case SVGA3D_BLENDOP_BLENDFACTOR: return D3D11_BLEND_BLEND_FACTOR; case SVGA3D_BLENDOP_INVBLENDFACTOR: return D3D11_BLEND_INV_BLEND_FACTOR; case SVGA3D_BLENDOP_SRC1COLOR: return D3D11_BLEND_SRC1_ALPHA; case SVGA3D_BLENDOP_INVSRC1COLOR: return D3D11_BLEND_INV_SRC1_ALPHA; case SVGA3D_BLENDOP_SRC1ALPHA: return D3D11_BLEND_SRC1_ALPHA; case SVGA3D_BLENDOP_INVSRC1ALPHA: return D3D11_BLEND_INV_SRC1_ALPHA; case SVGA3D_BLENDOP_BLENDFACTORALPHA: return D3D11_BLEND_BLEND_FACTOR; case SVGA3D_BLENDOP_INVBLENDFACTORALPHA: return D3D11_BLEND_INV_BLEND_FACTOR; default: break; } return D3D11_BLEND_ZERO; } static D3D11_BLEND dxBlendFactorColor(uint8_t svgaBlend) { switch (svgaBlend) { case SVGA3D_BLENDOP_ZERO: return D3D11_BLEND_ZERO; case SVGA3D_BLENDOP_ONE: return D3D11_BLEND_ONE; case SVGA3D_BLENDOP_SRCCOLOR: return D3D11_BLEND_SRC_COLOR; case SVGA3D_BLENDOP_INVSRCCOLOR: return D3D11_BLEND_INV_SRC_COLOR; case SVGA3D_BLENDOP_SRCALPHA: return D3D11_BLEND_SRC_ALPHA; case SVGA3D_BLENDOP_INVSRCALPHA: return D3D11_BLEND_INV_SRC_ALPHA; case SVGA3D_BLENDOP_DESTALPHA: return D3D11_BLEND_DEST_ALPHA; case SVGA3D_BLENDOP_INVDESTALPHA: return D3D11_BLEND_INV_DEST_ALPHA; case SVGA3D_BLENDOP_DESTCOLOR: return D3D11_BLEND_DEST_COLOR; case SVGA3D_BLENDOP_INVDESTCOLOR: return D3D11_BLEND_INV_DEST_COLOR; case SVGA3D_BLENDOP_SRCALPHASAT: return D3D11_BLEND_SRC_ALPHA_SAT; case SVGA3D_BLENDOP_BLENDFACTOR: return D3D11_BLEND_BLEND_FACTOR; case SVGA3D_BLENDOP_INVBLENDFACTOR: return D3D11_BLEND_INV_BLEND_FACTOR; case SVGA3D_BLENDOP_SRC1COLOR: return D3D11_BLEND_SRC1_COLOR; case SVGA3D_BLENDOP_INVSRC1COLOR: return D3D11_BLEND_INV_SRC1_COLOR; case SVGA3D_BLENDOP_SRC1ALPHA: return D3D11_BLEND_SRC1_ALPHA; case SVGA3D_BLENDOP_INVSRC1ALPHA: return D3D11_BLEND_INV_SRC1_ALPHA; case SVGA3D_BLENDOP_BLENDFACTORALPHA: return D3D11_BLEND_BLEND_FACTOR; case SVGA3D_BLENDOP_INVBLENDFACTORALPHA: return D3D11_BLEND_INV_BLEND_FACTOR; default: break; } return D3D11_BLEND_ZERO; } static D3D11_BLEND_OP dxBlendOp(uint8_t svgaBlendEq) { return (D3D11_BLEND_OP)svgaBlendEq; } static D3D11_LOGIC_OP dxLogicOp(uint8_t svgaLogicEq) { return (D3D11_LOGIC_OP)svgaLogicEq; } /** @todo AssertCompile for types like D3D11_COMPARISON_FUNC and SVGA3dComparisonFunc */ static HRESULT dxBlendStateCreate(DXDEVICE *pDevice, SVGACOTableDXBlendStateEntry const *pEntry, ID3D11BlendState1 **pp) { D3D11_BLEND_DESC1 BlendDesc; BlendDesc.AlphaToCoverageEnable = RT_BOOL(pEntry->alphaToCoverageEnable); BlendDesc.IndependentBlendEnable = RT_BOOL(pEntry->independentBlendEnable); for (int i = 0; i < SVGA3D_MAX_RENDER_TARGETS; ++i) { BlendDesc.RenderTarget[i].BlendEnable = RT_BOOL(pEntry->perRT[i].blendEnable); BlendDesc.RenderTarget[i].LogicOpEnable = RT_BOOL(pEntry->perRT[i].logicOpEnable); BlendDesc.RenderTarget[i].SrcBlend = dxBlendFactorColor(pEntry->perRT[i].srcBlend); BlendDesc.RenderTarget[i].DestBlend = dxBlendFactorColor(pEntry->perRT[i].destBlend); BlendDesc.RenderTarget[i].BlendOp = dxBlendOp (pEntry->perRT[i].blendOp); BlendDesc.RenderTarget[i].SrcBlendAlpha = dxBlendFactorAlpha(pEntry->perRT[i].srcBlendAlpha); BlendDesc.RenderTarget[i].DestBlendAlpha = dxBlendFactorAlpha(pEntry->perRT[i].destBlendAlpha); BlendDesc.RenderTarget[i].BlendOpAlpha = dxBlendOp (pEntry->perRT[i].blendOpAlpha); BlendDesc.RenderTarget[i].LogicOp = dxLogicOp (pEntry->perRT[i].logicOp); BlendDesc.RenderTarget[i].RenderTargetWriteMask = pEntry->perRT[i].renderTargetWriteMask; } HRESULT hr = pDevice->pDevice->CreateBlendState1(&BlendDesc, pp); Assert(SUCCEEDED(hr)); return hr; } static HRESULT dxDepthStencilStateCreate(DXDEVICE *pDevice, SVGACOTableDXDepthStencilEntry const *pEntry, ID3D11DepthStencilState **pp) { D3D11_DEPTH_STENCIL_DESC desc; desc.DepthEnable = pEntry->depthEnable; desc.DepthWriteMask = (D3D11_DEPTH_WRITE_MASK)pEntry->depthWriteMask; desc.DepthFunc = (D3D11_COMPARISON_FUNC)pEntry->depthFunc; desc.StencilEnable = pEntry->stencilEnable; desc.StencilReadMask = pEntry->stencilReadMask; desc.StencilWriteMask = pEntry->stencilWriteMask; desc.FrontFace.StencilFailOp = (D3D11_STENCIL_OP)pEntry->frontStencilFailOp; desc.FrontFace.StencilDepthFailOp = (D3D11_STENCIL_OP)pEntry->frontStencilDepthFailOp; desc.FrontFace.StencilPassOp = (D3D11_STENCIL_OP)pEntry->frontStencilPassOp; desc.FrontFace.StencilFunc = (D3D11_COMPARISON_FUNC)pEntry->frontStencilFunc; desc.BackFace.StencilFailOp = (D3D11_STENCIL_OP)pEntry->backStencilFailOp; desc.BackFace.StencilDepthFailOp = (D3D11_STENCIL_OP)pEntry->backStencilDepthFailOp; desc.BackFace.StencilPassOp = (D3D11_STENCIL_OP)pEntry->backStencilPassOp; desc.BackFace.StencilFunc = (D3D11_COMPARISON_FUNC)pEntry->backStencilFunc; /** @todo frontEnable, backEnable */ HRESULT hr = pDevice->pDevice->CreateDepthStencilState(&desc, pp); Assert(SUCCEEDED(hr)); return hr; } static HRESULT dxSamplerStateCreate(DXDEVICE *pDevice, SVGACOTableDXSamplerEntry const *pEntry, ID3D11SamplerState **pp) { D3D11_SAMPLER_DESC desc; /* Guest sometimes sends inconsistent (from D3D11 point of view) set of filter flags. */ if (pEntry->filter & SVGA3D_FILTER_ANISOTROPIC) desc.Filter = (pEntry->filter & SVGA3D_FILTER_COMPARE) ? D3D11_FILTER_COMPARISON_ANISOTROPIC : D3D11_FILTER_ANISOTROPIC; else desc.Filter = (D3D11_FILTER)pEntry->filter; desc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)pEntry->addressU; desc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)pEntry->addressV; desc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)pEntry->addressW; desc.MipLODBias = pEntry->mipLODBias; desc.MaxAnisotropy = RT_CLAMP(pEntry->maxAnisotropy, 1, 16); /* "Valid values are between 1 and 16" */ desc.ComparisonFunc = (D3D11_COMPARISON_FUNC)pEntry->comparisonFunc; desc.BorderColor[0] = pEntry->borderColor.value[0]; desc.BorderColor[1] = pEntry->borderColor.value[1]; desc.BorderColor[2] = pEntry->borderColor.value[2]; desc.BorderColor[3] = pEntry->borderColor.value[3]; desc.MinLOD = pEntry->minLOD; desc.MaxLOD = pEntry->maxLOD; HRESULT hr = pDevice->pDevice->CreateSamplerState(&desc, pp); Assert(SUCCEEDED(hr)); return hr; } static D3D11_FILL_MODE dxFillMode(uint8_t svgaFillMode) { if (svgaFillMode == SVGA3D_FILLMODE_POINT) return D3D11_FILL_WIREFRAME; return (D3D11_FILL_MODE)svgaFillMode; } static D3D11_CULL_MODE dxCullMode(uint8_t svgaCullMode) { return (D3D11_CULL_MODE)svgaCullMode; } static HRESULT dxRasterizerStateCreate(DXDEVICE *pDevice, SVGACOTableDXRasterizerStateEntry const *pEntry, ID3D11RasterizerState1 **pp) { D3D11_RASTERIZER_DESC1 desc; desc.FillMode = dxFillMode(pEntry->fillMode); desc.CullMode = dxCullMode(pEntry->cullMode); desc.FrontCounterClockwise = pEntry->frontCounterClockwise; /** @todo provokingVertexLast */ desc.DepthBias = pEntry->depthBias; desc.DepthBiasClamp = pEntry->depthBiasClamp; desc.SlopeScaledDepthBias = pEntry->slopeScaledDepthBias; desc.DepthClipEnable = pEntry->depthClipEnable; desc.ScissorEnable = pEntry->scissorEnable; desc.MultisampleEnable = pEntry->multisampleEnable; desc.AntialiasedLineEnable = pEntry->antialiasedLineEnable; desc.ForcedSampleCount = pEntry->forcedSampleCount; /** @todo lineWidth lineStippleEnable lineStippleFactor lineStipplePattern */ HRESULT hr = pDevice->pDevice->CreateRasterizerState1(&desc, pp); Assert(SUCCEEDED(hr)); return hr; } static HRESULT dxRenderTargetViewCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableDXRTViewEntry const *pEntry, VMSVGA3DSURFACE *pSurface, ID3D11RenderTargetView **pp) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); ID3D11Resource *pResource = dxResource(pThisCC->svga.p3dState, pSurface, pDXContext); D3D11_RENDER_TARGET_VIEW_DESC desc; RT_ZERO(desc); desc.Format = vmsvgaDXSurfaceFormat2Dxgi(pEntry->format); AssertReturn(desc.Format != DXGI_FORMAT_UNKNOWN || pEntry->format == SVGA3D_BUFFER, E_FAIL); switch (pEntry->resourceDimension) { case SVGA3D_RESOURCE_BUFFER: desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER; desc.Buffer.FirstElement = pEntry->desc.buffer.firstElement; desc.Buffer.NumElements = pEntry->desc.buffer.numElements; break; case SVGA3D_RESOURCE_TEXTURE1D: if (pSurface->surfaceDesc.numArrayElements <= 1) { desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D; desc.Texture1D.MipSlice = pEntry->desc.tex.mipSlice; } else { desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY; desc.Texture1DArray.MipSlice = pEntry->desc.tex.mipSlice; desc.Texture1DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; desc.Texture1DArray.ArraySize = pEntry->desc.tex.arraySize; } break; case SVGA3D_RESOURCE_TEXTURE2D: if (pSurface->surfaceDesc.numArrayElements <= 1) { desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; desc.Texture2D.MipSlice = pEntry->desc.tex.mipSlice; } else { desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; desc.Texture2DArray.MipSlice = pEntry->desc.tex.mipSlice; desc.Texture2DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; desc.Texture2DArray.ArraySize = pEntry->desc.tex.arraySize; } break; case SVGA3D_RESOURCE_TEXTURE3D: desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; desc.Texture3D.MipSlice = pEntry->desc.tex3D.mipSlice; desc.Texture3D.FirstWSlice = pEntry->desc.tex3D.firstW; desc.Texture3D.WSize = pEntry->desc.tex3D.wSize; break; case SVGA3D_RESOURCE_TEXTURECUBE: desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; desc.Texture2DArray.MipSlice = pEntry->desc.tex.mipSlice; desc.Texture2DArray.FirstArraySlice = 0; desc.Texture2DArray.ArraySize = 6; break; case SVGA3D_RESOURCE_BUFFEREX: AssertFailed(); /** @todo test. Probably not applicable to a render target view. */ desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER; desc.Buffer.FirstElement = pEntry->desc.buffer.firstElement; desc.Buffer.NumElements = pEntry->desc.buffer.numElements; break; default: ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); } HRESULT hr = pDevice->pDevice->CreateRenderTargetView(pResource, &desc, pp); Assert(SUCCEEDED(hr)); return hr; } static HRESULT dxShaderResourceViewCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableDXSRViewEntry const *pEntry, VMSVGA3DSURFACE *pSurface, ID3D11ShaderResourceView **pp) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); ID3D11Resource *pResource = dxResource(pThisCC->svga.p3dState, pSurface, pDXContext); D3D11_SHADER_RESOURCE_VIEW_DESC desc; RT_ZERO(desc); desc.Format = vmsvgaDXSurfaceFormat2Dxgi(pEntry->format); AssertReturn(desc.Format != DXGI_FORMAT_UNKNOWN || pEntry->format == SVGA3D_BUFFER, E_FAIL); switch (pEntry->resourceDimension) { case SVGA3D_RESOURCE_BUFFER: desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; desc.Buffer.FirstElement = pEntry->desc.buffer.firstElement; desc.Buffer.NumElements = pEntry->desc.buffer.numElements; break; case SVGA3D_RESOURCE_TEXTURE1D: if (pSurface->surfaceDesc.numArrayElements <= 1) { desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; desc.Texture1D.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; desc.Texture1D.MipLevels = pEntry->desc.tex.mipLevels; } else { desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; desc.Texture1DArray.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; desc.Texture1DArray.MipLevels = pEntry->desc.tex.mipLevels; desc.Texture1DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; desc.Texture1DArray.ArraySize = pEntry->desc.tex.arraySize; } break; case SVGA3D_RESOURCE_TEXTURE2D: if (pSurface->surfaceDesc.numArrayElements <= 1) { desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; desc.Texture2D.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; desc.Texture2D.MipLevels = pEntry->desc.tex.mipLevels; } else { desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; desc.Texture2DArray.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; desc.Texture2DArray.MipLevels = pEntry->desc.tex.mipLevels; desc.Texture2DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; desc.Texture2DArray.ArraySize = pEntry->desc.tex.arraySize; } break; case SVGA3D_RESOURCE_TEXTURE3D: desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; desc.Texture3D.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; desc.Texture3D.MipLevels = pEntry->desc.tex.mipLevels; break; case SVGA3D_RESOURCE_TEXTURECUBE: if (pSurface->surfaceDesc.numArrayElements <= 6) { desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; desc.TextureCube.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; desc.TextureCube.MipLevels = pEntry->desc.tex.mipLevels; } else { desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY; desc.TextureCubeArray.MostDetailedMip = pEntry->desc.tex.mostDetailedMip; desc.TextureCubeArray.MipLevels = pEntry->desc.tex.mipLevels; desc.TextureCubeArray.First2DArrayFace = pEntry->desc.tex.firstArraySlice; desc.TextureCubeArray.NumCubes = pEntry->desc.tex.arraySize / 6; } break; case SVGA3D_RESOURCE_BUFFEREX: AssertFailed(); /** @todo test. */ desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; desc.BufferEx.FirstElement = pEntry->desc.bufferex.firstElement; desc.BufferEx.NumElements = pEntry->desc.bufferex.numElements; desc.BufferEx.Flags = pEntry->desc.bufferex.flags; break; default: ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); } HRESULT hr = pDevice->pDevice->CreateShaderResourceView(pResource, &desc, pp); Assert(SUCCEEDED(hr)); return hr; } static HRESULT dxUnorderedAccessViewCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableDXUAViewEntry const *pEntry, VMSVGA3DSURFACE *pSurface, ID3D11UnorderedAccessView **pp) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); ID3D11Resource *pResource = dxResource(pThisCC->svga.p3dState, pSurface, pDXContext); D3D11_UNORDERED_ACCESS_VIEW_DESC desc; RT_ZERO(desc); desc.Format = vmsvgaDXSurfaceFormat2Dxgi(pEntry->format); AssertReturn(desc.Format != DXGI_FORMAT_UNKNOWN || pEntry->format == SVGA3D_BUFFER, E_FAIL); switch (pEntry->resourceDimension) { case SVGA3D_RESOURCE_BUFFER: desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; desc.Buffer.FirstElement = pEntry->desc.buffer.firstElement; desc.Buffer.NumElements = pEntry->desc.buffer.numElements; desc.Buffer.Flags = pEntry->desc.buffer.flags; break; case SVGA3D_RESOURCE_TEXTURE1D: if (pSurface->surfaceDesc.numArrayElements <= 1) { desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D; desc.Texture1D.MipSlice = pEntry->desc.tex.mipSlice; } else { desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1DARRAY; desc.Texture1DArray.MipSlice = pEntry->desc.tex.mipSlice; desc.Texture1DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; desc.Texture1DArray.ArraySize = pEntry->desc.tex.arraySize; } break; case SVGA3D_RESOURCE_TEXTURE2D: if (pSurface->surfaceDesc.numArrayElements <= 1) { desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; desc.Texture2D.MipSlice = pEntry->desc.tex.mipSlice; } else { desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; desc.Texture2DArray.MipSlice = pEntry->desc.tex.mipSlice; desc.Texture2DArray.FirstArraySlice = pEntry->desc.tex.firstArraySlice; desc.Texture2DArray.ArraySize = pEntry->desc.tex.arraySize; } break; case SVGA3D_RESOURCE_TEXTURE3D: desc.Texture3D.MipSlice = pEntry->desc.tex3D.mipSlice; desc.Texture3D.FirstWSlice = pEntry->desc.tex3D.firstW; desc.Texture3D.WSize = pEntry->desc.tex3D.wSize; break; default: ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); } HRESULT hr = pDevice->pDevice->CreateUnorderedAccessView(pResource, &desc, pp); Assert(SUCCEEDED(hr)); return hr; } static HRESULT dxDepthStencilViewCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableDXDSViewEntry const *pEntry, VMSVGA3DSURFACE *pSurface, ID3D11DepthStencilView **pp) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); ID3D11Resource *pResource = dxResource(pThisCC->svga.p3dState, pSurface, pDXContext); D3D11_DEPTH_STENCIL_VIEW_DESC desc; RT_ZERO(desc); desc.Format = vmsvgaDXSurfaceFormat2Dxgi(pEntry->format); AssertReturn(desc.Format != DXGI_FORMAT_UNKNOWN || pEntry->format == SVGA3D_BUFFER, E_FAIL); desc.Flags = pEntry->flags; switch (pEntry->resourceDimension) { case SVGA3D_RESOURCE_TEXTURE1D: if (pSurface->surfaceDesc.numArrayElements <= 1) { desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D; desc.Texture1D.MipSlice = pEntry->mipSlice; } else { desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY; desc.Texture1DArray.MipSlice = pEntry->mipSlice; desc.Texture1DArray.FirstArraySlice = pEntry->firstArraySlice; desc.Texture1DArray.ArraySize = pEntry->arraySize; } break; case SVGA3D_RESOURCE_TEXTURE2D: if (pSurface->surfaceDesc.numArrayElements <= 1) { desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; desc.Texture2D.MipSlice = pEntry->mipSlice; } else { desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; desc.Texture2DArray.MipSlice = pEntry->mipSlice; desc.Texture2DArray.FirstArraySlice = pEntry->firstArraySlice; desc.Texture2DArray.ArraySize = pEntry->arraySize; } break; default: ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); } HRESULT hr = pDevice->pDevice->CreateDepthStencilView(pResource, &desc, pp); Assert(SUCCEEDED(hr)); return hr; } static HRESULT dxShaderCreate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, DXSHADER *pDXShader) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); HRESULT hr = S_OK; switch (pDXShader->enmShaderType) { case SVGA3D_SHADERTYPE_VS: hr = pDevice->pDevice->CreateVertexShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pVertexShader); Assert(SUCCEEDED(hr)); break; case SVGA3D_SHADERTYPE_PS: hr = pDevice->pDevice->CreatePixelShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pPixelShader); Assert(SUCCEEDED(hr)); break; case SVGA3D_SHADERTYPE_GS: { SVGA3dStreamOutputId const soid = pDXContext->svgaDXContext.streamOut.soid; if (soid == SVGA_ID_INVALID) { hr = pDevice->pDevice->CreateGeometryShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pGeometryShader); Assert(SUCCEEDED(hr)); } else { ASSERT_GUEST_RETURN(soid < pDXContext->pBackendDXContext->cStreamOutput, E_INVALIDARG); SVGACOTableDXStreamOutputEntry const *pEntry = &pDXContext->cot.paStreamOutput[soid]; DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; hr = pDevice->pDevice->CreateGeometryShaderWithStreamOutput(pDXShader->pvDXBC, pDXShader->cbDXBC, pDXStreamOutput->aDeclarationEntry, pDXStreamOutput->cDeclarationEntry, pEntry->numOutputStreamStrides ? pEntry->streamOutputStrideInBytes : NULL, pEntry->numOutputStreamStrides, pEntry->rasterizedStream, /*pClassLinkage=*/ NULL, &pDXShader->pGeometryShader); AssertBreak(SUCCEEDED(hr)); pDXShader->soid = soid; } break; } case SVGA3D_SHADERTYPE_HS: hr = pDevice->pDevice->CreateHullShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pHullShader); Assert(SUCCEEDED(hr)); break; case SVGA3D_SHADERTYPE_DS: hr = pDevice->pDevice->CreateDomainShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pDomainShader); Assert(SUCCEEDED(hr)); break; case SVGA3D_SHADERTYPE_CS: hr = pDevice->pDevice->CreateComputeShader(pDXShader->pvDXBC, pDXShader->cbDXBC, NULL, &pDXShader->pComputeShader); Assert(SUCCEEDED(hr)); break; default: ASSERT_GUEST_FAILED_RETURN(E_INVALIDARG); } return hr; } static void dxShaderSet(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderType type, DXSHADER *pDXShader) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); switch (type) { case SVGA3D_SHADERTYPE_VS: pDevice->pImmediateContext->VSSetShader(pDXShader ? pDXShader->pVertexShader : NULL, NULL, 0); break; case SVGA3D_SHADERTYPE_PS: pDevice->pImmediateContext->PSSetShader(pDXShader ? pDXShader->pPixelShader : NULL, NULL, 0); break; case SVGA3D_SHADERTYPE_GS: { Assert(!pDXShader || (pDXShader->soid == pDXContext->svgaDXContext.streamOut.soid)); pDevice->pImmediateContext->GSSetShader(pDXShader ? pDXShader->pGeometryShader : NULL, NULL, 0); } break; case SVGA3D_SHADERTYPE_HS: pDevice->pImmediateContext->HSSetShader(pDXShader ? pDXShader->pHullShader : NULL, NULL, 0); break; case SVGA3D_SHADERTYPE_DS: pDevice->pImmediateContext->DSSetShader(pDXShader ? pDXShader->pDomainShader : NULL, NULL, 0); break; case SVGA3D_SHADERTYPE_CS: pDevice->pImmediateContext->CSSetShader(pDXShader ? pDXShader->pComputeShader : NULL, NULL, 0); break; default: ASSERT_GUEST_FAILED_RETURN_VOID(); } } static void dxConstantBufferSet(DXDEVICE *pDevice, uint32_t slot, SVGA3dShaderType type, ID3D11Buffer *pConstantBuffer) { switch (type) { case SVGA3D_SHADERTYPE_VS: pDevice->pImmediateContext->VSSetConstantBuffers(slot, 1, &pConstantBuffer); break; case SVGA3D_SHADERTYPE_PS: pDevice->pImmediateContext->PSSetConstantBuffers(slot, 1, &pConstantBuffer); break; case SVGA3D_SHADERTYPE_GS: pDevice->pImmediateContext->GSSetConstantBuffers(slot, 1, &pConstantBuffer); break; case SVGA3D_SHADERTYPE_HS: pDevice->pImmediateContext->HSSetConstantBuffers(slot, 1, &pConstantBuffer); break; case SVGA3D_SHADERTYPE_DS: pDevice->pImmediateContext->DSSetConstantBuffers(slot, 1, &pConstantBuffer); break; case SVGA3D_SHADERTYPE_CS: pDevice->pImmediateContext->CSSetConstantBuffers(slot, 1, &pConstantBuffer); break; default: ASSERT_GUEST_FAILED_RETURN_VOID(); } } static void dxSamplerSet(DXDEVICE *pDevice, SVGA3dShaderType type, uint32_t startSampler, uint32_t cSampler, ID3D11SamplerState * const *papSampler) { switch (type) { case SVGA3D_SHADERTYPE_VS: pDevice->pImmediateContext->VSSetSamplers(startSampler, cSampler, papSampler); break; case SVGA3D_SHADERTYPE_PS: pDevice->pImmediateContext->PSSetSamplers(startSampler, cSampler, papSampler); break; case SVGA3D_SHADERTYPE_GS: pDevice->pImmediateContext->GSSetSamplers(startSampler, cSampler, papSampler); break; case SVGA3D_SHADERTYPE_HS: pDevice->pImmediateContext->HSSetSamplers(startSampler, cSampler, papSampler); break; case SVGA3D_SHADERTYPE_DS: pDevice->pImmediateContext->DSSetSamplers(startSampler, cSampler, papSampler); break; case SVGA3D_SHADERTYPE_CS: pDevice->pImmediateContext->CSSetSamplers(startSampler, cSampler, papSampler); break; default: ASSERT_GUEST_FAILED_RETURN_VOID(); } } static void dxShaderResourceViewSet(DXDEVICE *pDevice, SVGA3dShaderType type, uint32_t startView, uint32_t cShaderResourceView, ID3D11ShaderResourceView * const *papShaderResourceView) { switch (type) { case SVGA3D_SHADERTYPE_VS: pDevice->pImmediateContext->VSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); break; case SVGA3D_SHADERTYPE_PS: pDevice->pImmediateContext->PSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); break; case SVGA3D_SHADERTYPE_GS: pDevice->pImmediateContext->GSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); break; case SVGA3D_SHADERTYPE_HS: pDevice->pImmediateContext->HSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); break; case SVGA3D_SHADERTYPE_DS: pDevice->pImmediateContext->DSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); break; case SVGA3D_SHADERTYPE_CS: pDevice->pImmediateContext->CSSetShaderResources(startView, cShaderResourceView, papShaderResourceView); break; default: ASSERT_GUEST_FAILED_RETURN_VOID(); } } static void dxCSUnorderedAccessViewSet(DXDEVICE *pDevice, uint32_t startView, uint32_t cView, ID3D11UnorderedAccessView * const *papUnorderedAccessView, UINT *pUAVInitialCounts) { pDevice->pImmediateContext->CSSetUnorderedAccessViews(startView, cView, papUnorderedAccessView, pUAVInitialCounts); } static int dxBackendSurfaceAlloc(PVMSVGA3DBACKENDSURFACE *ppBackendSurface) { PVMSVGA3DBACKENDSURFACE pBackendSurface = (PVMSVGA3DBACKENDSURFACE)RTMemAllocZ(sizeof(VMSVGA3DBACKENDSURFACE)); AssertPtrReturn(pBackendSurface, VERR_NO_MEMORY); pBackendSurface->cidDrawing = SVGA_ID_INVALID; RTListInit(&pBackendSurface->listView); *ppBackendSurface = pBackendSurface; return VINF_SUCCESS; } static HRESULT dxInitSharedHandle(PVMSVGA3DBACKEND pBackend, PVMSVGA3DBACKENDSURFACE pBackendSurface) { if (pBackend->fSingleDevice) return S_OK; /* Get the shared handle. */ IDXGIResource *pDxgiResource = NULL; HRESULT hr = pBackendSurface->u.pResource->QueryInterface(__uuidof(IDXGIResource), (void**)&pDxgiResource); Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { hr = pDxgiResource->GetSharedHandle(&pBackendSurface->SharedHandle); Assert(SUCCEEDED(hr)); D3D_RELEASE(pDxgiResource); } return hr; } static UINT dxBindFlags(SVGA3dSurfaceAllFlags surfaceFlags) { /* Catch unimplemented flags. */ Assert(!RT_BOOL(surfaceFlags & (SVGA3D_SURFACE_BIND_LOGICOPS | SVGA3D_SURFACE_BIND_RAW_VIEWS))); UINT BindFlags = 0; if (surfaceFlags & (SVGA3D_SURFACE_BIND_VERTEX_BUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER)) BindFlags |= D3D11_BIND_VERTEX_BUFFER; if (surfaceFlags & (SVGA3D_SURFACE_BIND_INDEX_BUFFER | SVGA3D_SURFACE_HINT_INDEXBUFFER)) BindFlags |= D3D11_BIND_INDEX_BUFFER; if (surfaceFlags & SVGA3D_SURFACE_BIND_CONSTANT_BUFFER) BindFlags |= D3D11_BIND_CONSTANT_BUFFER; if (surfaceFlags & SVGA3D_SURFACE_BIND_SHADER_RESOURCE) BindFlags |= D3D11_BIND_SHADER_RESOURCE; if (surfaceFlags & SVGA3D_SURFACE_BIND_RENDER_TARGET) BindFlags |= D3D11_BIND_RENDER_TARGET; if (surfaceFlags & SVGA3D_SURFACE_BIND_DEPTH_STENCIL) BindFlags |= D3D11_BIND_DEPTH_STENCIL; if (surfaceFlags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) BindFlags |= D3D11_BIND_STREAM_OUTPUT; if (surfaceFlags & SVGA3D_SURFACE_BIND_UAVIEW) BindFlags |= D3D11_BIND_UNORDERED_ACCESS; return BindFlags; } static DXDEVICE *dxSurfaceDevice(PVMSVGA3DSTATE p3dState, PVMSVGA3DSURFACE pSurface, PVMSVGA3DDXCONTEXT pDXContext, UINT *pMiscFlags) { if (p3dState->pBackend->fSingleDevice) { *pMiscFlags = 0; return &p3dState->pBackend->dxDevice; } if (!pDXContext || dxIsSurfaceShareable(pSurface)) { *pMiscFlags = D3D11_RESOURCE_MISC_SHARED; return &p3dState->pBackend->dxDevice; } *pMiscFlags = 0; return &pDXContext->pBackendDXContext->dxDevice; } static DXGI_FORMAT dxGetDxgiTypelessFormat(DXGI_FORMAT dxgiFormat) { switch (dxgiFormat) { case DXGI_FORMAT_R32G32B32A32_FLOAT: case DXGI_FORMAT_R32G32B32A32_UINT: case DXGI_FORMAT_R32G32B32A32_SINT: return DXGI_FORMAT_R32G32B32A32_TYPELESS; /* 1 */ case DXGI_FORMAT_R32G32B32_FLOAT: case DXGI_FORMAT_R32G32B32_UINT: case DXGI_FORMAT_R32G32B32_SINT: return DXGI_FORMAT_R32G32B32_TYPELESS; /* 5 */ case DXGI_FORMAT_R16G16B16A16_FLOAT: case DXGI_FORMAT_R16G16B16A16_UNORM: case DXGI_FORMAT_R16G16B16A16_UINT: case DXGI_FORMAT_R16G16B16A16_SNORM: case DXGI_FORMAT_R16G16B16A16_SINT: return DXGI_FORMAT_R16G16B16A16_TYPELESS; /* 9 */ case DXGI_FORMAT_R32G32_FLOAT: case DXGI_FORMAT_R32G32_UINT: case DXGI_FORMAT_R32G32_SINT: return DXGI_FORMAT_R32G32_TYPELESS; /* 15 */ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS; /* 19 */ case DXGI_FORMAT_R10G10B10A2_UNORM: case DXGI_FORMAT_R10G10B10A2_UINT: return DXGI_FORMAT_R10G10B10A2_TYPELESS; /* 23 */ case DXGI_FORMAT_R8G8B8A8_UNORM: case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: case DXGI_FORMAT_R8G8B8A8_UINT: case DXGI_FORMAT_R8G8B8A8_SNORM: case DXGI_FORMAT_R8G8B8A8_SINT: return DXGI_FORMAT_R8G8B8A8_TYPELESS; /* 27 */ case DXGI_FORMAT_R16G16_FLOAT: case DXGI_FORMAT_R16G16_UNORM: case DXGI_FORMAT_R16G16_UINT: case DXGI_FORMAT_R16G16_SNORM: case DXGI_FORMAT_R16G16_SINT: return DXGI_FORMAT_R16G16_TYPELESS; /* 33 */ case DXGI_FORMAT_D32_FLOAT: case DXGI_FORMAT_R32_FLOAT: case DXGI_FORMAT_R32_UINT: case DXGI_FORMAT_R32_SINT: return DXGI_FORMAT_R32_TYPELESS; /* 39 */ case DXGI_FORMAT_D24_UNORM_S8_UINT: case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: case DXGI_FORMAT_X24_TYPELESS_G8_UINT: return DXGI_FORMAT_R24G8_TYPELESS; /* 44 */ case DXGI_FORMAT_R8G8_UNORM: case DXGI_FORMAT_R8G8_UINT: case DXGI_FORMAT_R8G8_SNORM: case DXGI_FORMAT_R8G8_SINT: return DXGI_FORMAT_R8G8_TYPELESS; /* 48*/ case DXGI_FORMAT_R16_FLOAT: case DXGI_FORMAT_D16_UNORM: case DXGI_FORMAT_R16_UNORM: case DXGI_FORMAT_R16_UINT: case DXGI_FORMAT_R16_SNORM: case DXGI_FORMAT_R16_SINT: return DXGI_FORMAT_R16_TYPELESS; /* 53 */ case DXGI_FORMAT_R8_UNORM: case DXGI_FORMAT_R8_UINT: case DXGI_FORMAT_R8_SNORM: case DXGI_FORMAT_R8_SINT: return DXGI_FORMAT_R8_TYPELESS; /* 60*/ case DXGI_FORMAT_BC1_UNORM: case DXGI_FORMAT_BC1_UNORM_SRGB: return DXGI_FORMAT_BC1_TYPELESS; /* 70 */ case DXGI_FORMAT_BC2_UNORM: case DXGI_FORMAT_BC2_UNORM_SRGB: return DXGI_FORMAT_BC2_TYPELESS; /* 73 */ case DXGI_FORMAT_BC3_UNORM: case DXGI_FORMAT_BC3_UNORM_SRGB: return DXGI_FORMAT_BC3_TYPELESS; /* 76 */ case DXGI_FORMAT_BC4_UNORM: case DXGI_FORMAT_BC4_SNORM: return DXGI_FORMAT_BC4_TYPELESS; /* 79 */ case DXGI_FORMAT_BC5_UNORM: case DXGI_FORMAT_BC5_SNORM: return DXGI_FORMAT_BC5_TYPELESS; /* 82 */ case DXGI_FORMAT_B8G8R8A8_UNORM: case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_TYPELESS; /* 90 */ case DXGI_FORMAT_B8G8R8X8_UNORM: case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_TYPELESS; /* 92 */ case DXGI_FORMAT_BC6H_UF16: case DXGI_FORMAT_BC6H_SF16: return DXGI_FORMAT_BC6H_TYPELESS; /* 94 */ case DXGI_FORMAT_BC7_UNORM: case DXGI_FORMAT_BC7_UNORM_SRGB: return DXGI_FORMAT_BC7_TYPELESS; /* 97 */ default: break; } return dxgiFormat; } static bool dxIsDepthStencilFormat(DXGI_FORMAT dxgiFormat) { switch (dxgiFormat) { case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: case DXGI_FORMAT_D32_FLOAT: case DXGI_FORMAT_D24_UNORM_S8_UINT: case DXGI_FORMAT_D16_UNORM: return true; default: break; } return false; } static int vmsvga3dBackSurfaceCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface) { PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState; AssertReturn(p3dState, VERR_INVALID_STATE); PVMSVGA3DBACKEND pBackend = p3dState->pBackend; AssertReturn(pBackend, VERR_INVALID_STATE); UINT MiscFlags; DXDEVICE *pDXDevice = dxSurfaceDevice(p3dState, pSurface, pDXContext, &MiscFlags); AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); if (pSurface->pBackendSurface != NULL) { AssertFailed(); /** @todo Should the function not be used like that? */ vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); } PVMSVGA3DBACKENDSURFACE pBackendSurface; int rc = dxBackendSurfaceAlloc(&pBackendSurface); AssertRCReturn(rc, rc); uint32_t const cWidth = pSurface->paMipmapLevels[0].cBlocksX * pSurface->cxBlock; uint32_t const cHeight = pSurface->paMipmapLevels[0].cBlocksY * pSurface->cyBlock; uint32_t const cDepth = pSurface->paMipmapLevels[0].mipmapSize.depth; uint32_t const numMipLevels = pSurface->cLevels; DXGI_FORMAT dxgiFormat = vmsvgaDXSurfaceFormat2Dxgi(pSurface->format); AssertReturn(dxgiFormat != DXGI_FORMAT_UNKNOWN, E_FAIL); /* Create typeless textures, unless it is a depth/stencil resource, * because D3D11_BIND_DEPTH_STENCIL requires a depth/stencil format. * Always use typeless format for staging/dynamic resources. */ DXGI_FORMAT const dxgiFormatTypeless = dxGetDxgiTypelessFormat(dxgiFormat); if (!dxIsDepthStencilFormat(dxgiFormat)) dxgiFormat = dxgiFormatTypeless; /* Format for staging resource is always the typeless one. */ DXGI_FORMAT const dxgiFormatStaging = dxgiFormatTypeless; DXGI_FORMAT dxgiFormatDynamic; /* Some drivers do not allow to use depth typeless formats for dynamic resources. * Create a placeholder texture (it does not work with CopySubresource). */ /** @todo Implement upload from such textures. */ if (dxgiFormatTypeless == DXGI_FORMAT_R24G8_TYPELESS) dxgiFormatDynamic = DXGI_FORMAT_R32_UINT; else if (dxgiFormatTypeless == DXGI_FORMAT_R32G8X24_TYPELESS) dxgiFormatDynamic = DXGI_FORMAT_R32G32_UINT; else dxgiFormatDynamic = dxgiFormatTypeless; /* * Create D3D11 texture object. */ D3D11_SUBRESOURCE_DATA *paInitialData = NULL; if (pSurface->paMipmapLevels[0].pSurfaceData) { /* Can happen for a non GBO surface or if GBO texture was updated prior to creation of the hardware resource. */ uint32_t const cSubresource = numMipLevels * pSurface->surfaceDesc.numArrayElements; paInitialData = (D3D11_SUBRESOURCE_DATA *)RTMemAlloc(cSubresource * sizeof(D3D11_SUBRESOURCE_DATA)); AssertPtrReturn(paInitialData, VERR_NO_MEMORY); for (uint32_t i = 0; i < cSubresource; ++i) { PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i]; D3D11_SUBRESOURCE_DATA *p = &paInitialData[i]; p->pSysMem = pMipmapLevel->pSurfaceData; p->SysMemPitch = pMipmapLevel->cbSurfacePitch; p->SysMemSlicePitch = pMipmapLevel->cbSurfacePlane; } } HRESULT hr = S_OK; if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_CUBEMAP) { Assert(pSurface->cFaces == 6); Assert(cWidth == cHeight); Assert(cDepth == 1); //DEBUG_BREAKPOINT_TEST(); D3D11_TEXTURE2D_DESC td; RT_ZERO(td); td.Width = cWidth; td.Height = cHeight; td.MipLevels = numMipLevels; td.ArraySize = pSurface->surfaceDesc.numArrayElements; /* This is 6 * numCubes */ td.Format = dxgiFormat; td.SampleDesc.Count = 1; td.SampleDesc.Quality = 0; td.Usage = D3D11_USAGE_DEFAULT; td.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); td.CPUAccessFlags = 0; /** @todo */ td.MiscFlags = MiscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE; /** @todo */ if ( numMipLevels > 1 && (td.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) == (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) td.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; /* Required for GenMips. */ hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->u.pTexture2D); Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { /* Map-able texture. */ td.Format = dxgiFormatDynamic; td.MipLevels = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ td.ArraySize = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ td.Usage = D3D11_USAGE_DYNAMIC; td.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; td.MiscFlags = 0; hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->dynamic.pTexture2D); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) { /* Staging texture. */ td.Format = dxgiFormatStaging; td.Usage = D3D11_USAGE_STAGING; td.BindFlags = 0; /* No flags allowed. */ td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; td.MiscFlags = 0; hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->staging.pTexture2D); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) hr = dxInitSharedHandle(pBackend, pBackendSurface); if (SUCCEEDED(hr)) { pBackendSurface->enmResType = VMSVGA3D_RESTYPE_TEXTURE_CUBE; } } else if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_1D) { /* * 1D texture. */ Assert(pSurface->cFaces == 1); D3D11_TEXTURE1D_DESC td; RT_ZERO(td); td.Width = cWidth; td.MipLevels = numMipLevels; td.ArraySize = pSurface->surfaceDesc.numArrayElements; td.Format = dxgiFormat; td.Usage = D3D11_USAGE_DEFAULT; td.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); td.CPUAccessFlags = 0; td.MiscFlags = MiscFlags; /** @todo */ if ( numMipLevels > 1 && (td.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) == (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) td.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; /* Required for GenMips. */ hr = pDXDevice->pDevice->CreateTexture1D(&td, paInitialData, &pBackendSurface->u.pTexture1D); Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { /* Map-able texture. */ td.Format = dxgiFormatDynamic; td.MipLevels = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ td.ArraySize = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ td.Usage = D3D11_USAGE_DYNAMIC; td.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; td.MiscFlags = 0; hr = pDXDevice->pDevice->CreateTexture1D(&td, paInitialData, &pBackendSurface->dynamic.pTexture1D); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) { /* Staging texture. */ td.Format = dxgiFormatStaging; td.Usage = D3D11_USAGE_STAGING; td.BindFlags = 0; /* No flags allowed. */ td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; td.MiscFlags = 0; hr = pDXDevice->pDevice->CreateTexture1D(&td, paInitialData, &pBackendSurface->staging.pTexture1D); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) hr = dxInitSharedHandle(pBackend, pBackendSurface); if (SUCCEEDED(hr)) { pBackendSurface->enmResType = VMSVGA3D_RESTYPE_TEXTURE_1D; } } else { if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_VOLUME) { /* * Volume texture. */ Assert(pSurface->cFaces == 1); Assert(pSurface->surfaceDesc.numArrayElements == 1); D3D11_TEXTURE3D_DESC td; RT_ZERO(td); td.Width = cWidth; td.Height = cHeight; td.Depth = cDepth; td.MipLevels = numMipLevels; td.Format = dxgiFormat; td.Usage = D3D11_USAGE_DEFAULT; td.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); td.CPUAccessFlags = 0; /** @todo */ td.MiscFlags = MiscFlags; /** @todo */ if ( numMipLevels > 1 && (td.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) == (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) td.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; /* Required for GenMips. */ hr = pDXDevice->pDevice->CreateTexture3D(&td, paInitialData, &pBackendSurface->u.pTexture3D); Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { /* Map-able texture. */ td.Format = dxgiFormatDynamic; td.MipLevels = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ td.Usage = D3D11_USAGE_DYNAMIC; td.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; td.MiscFlags = 0; hr = pDXDevice->pDevice->CreateTexture3D(&td, paInitialData, &pBackendSurface->dynamic.pTexture3D); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) { /* Staging texture. */ td.Format = dxgiFormatStaging; td.Usage = D3D11_USAGE_STAGING; td.BindFlags = 0; /* No flags allowed. */ td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; td.MiscFlags = 0; hr = pDXDevice->pDevice->CreateTexture3D(&td, paInitialData, &pBackendSurface->staging.pTexture3D); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) hr = dxInitSharedHandle(pBackend, pBackendSurface); if (SUCCEEDED(hr)) { pBackendSurface->enmResType = VMSVGA3D_RESTYPE_TEXTURE_3D; } } else { /* * 2D texture. */ Assert(cDepth == 1); Assert(pSurface->cFaces == 1); D3D11_TEXTURE2D_DESC td; RT_ZERO(td); td.Width = cWidth; td.Height = cHeight; td.MipLevels = numMipLevels; td.ArraySize = pSurface->surfaceDesc.numArrayElements; td.Format = dxgiFormat; td.SampleDesc.Count = 1; td.SampleDesc.Quality = 0; td.Usage = D3D11_USAGE_DEFAULT; td.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); td.CPUAccessFlags = 0; /** @todo */ td.MiscFlags = MiscFlags; /** @todo */ if ( numMipLevels > 1 && (td.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) == (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) td.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; /* Required for GenMips. */ hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->u.pTexture2D); Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { /* Map-able texture. */ td.Format = dxgiFormatDynamic; td.MipLevels = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ td.ArraySize = 1; /* Must be for D3D11_USAGE_DYNAMIC. */ td.Usage = D3D11_USAGE_DYNAMIC; td.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; td.MiscFlags = 0; hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->dynamic.pTexture2D); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) { /* Staging texture. */ td.Format = dxgiFormatStaging; td.Usage = D3D11_USAGE_STAGING; td.BindFlags = 0; /* No flags allowed. */ td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; td.MiscFlags = 0; hr = pDXDevice->pDevice->CreateTexture2D(&td, paInitialData, &pBackendSurface->staging.pTexture2D); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) hr = dxInitSharedHandle(pBackend, pBackendSurface); if (SUCCEEDED(hr)) { pBackendSurface->enmResType = VMSVGA3D_RESTYPE_TEXTURE_2D; } } } if (hr == DXGI_ERROR_DEVICE_REMOVED) { DEBUG_BREAKPOINT_TEST(); hr = pDXDevice->pDevice->GetDeviceRemovedReason(); } Assert(hr == S_OK); RTMemFree(paInitialData); if (pSurface->autogenFilter != SVGA3D_TEX_FILTER_NONE) { } if (SUCCEEDED(hr)) { /* * Success. */ LogFunc(("sid = %u\n", pSurface->id)); pBackendSurface->enmDxgiFormat = dxgiFormat; pSurface->pBackendSurface = pBackendSurface; if (p3dState->pBackend->fSingleDevice || RT_BOOL(MiscFlags & D3D11_RESOURCE_MISC_SHARED)) pSurface->idAssociatedContext = DX_CID_BACKEND; else pSurface->idAssociatedContext = pDXContext->cid; return VINF_SUCCESS; } D3D_RELEASE(pBackendSurface->staging.pResource); D3D_RELEASE(pBackendSurface->dynamic.pResource); D3D_RELEASE(pBackendSurface->u.pResource); RTMemFree(pBackendSurface); return VERR_NO_MEMORY; } static int vmsvga3dBackSurfaceCreateBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /* Buffers should be created as such. */ AssertReturn(RT_BOOL(pSurface->f.surfaceFlags & ( SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_BIND_VERTEX_BUFFER | SVGA3D_SURFACE_BIND_INDEX_BUFFER )), VERR_INVALID_PARAMETER); if (pSurface->pBackendSurface != NULL) { AssertFailed(); /** @todo Should the function not be used like that? */ vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); } PVMSVGA3DMIPMAPLEVEL pMipLevel; int rc = vmsvga3dMipmapLevel(pSurface, 0, 0, &pMipLevel); AssertRCReturn(rc, rc); PVMSVGA3DBACKENDSURFACE pBackendSurface; rc = dxBackendSurfaceAlloc(&pBackendSurface); AssertRCReturn(rc, rc); LogFunc(("sid = %u, size = %u\n", pSurface->id, pMipLevel->cbSurface)); /* Upload the current data, if any. */ D3D11_SUBRESOURCE_DATA *pInitialData = NULL; D3D11_SUBRESOURCE_DATA initialData; if (pMipLevel->pSurfaceData) { initialData.pSysMem = pMipLevel->pSurfaceData; initialData.SysMemPitch = pMipLevel->cbSurface; initialData.SysMemSlicePitch = pMipLevel->cbSurface; pInitialData = &initialData; } D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = pMipLevel->cbSurface; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->u.pBuffer); Assert(SUCCEEDED(hr)); #ifndef DX_COMMON_STAGING_BUFFER if (SUCCEEDED(hr)) { /* Map-able Buffer. */ bd.Usage = D3D11_USAGE_DYNAMIC; bd.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->dynamic.pBuffer); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) { /* Staging texture. */ bd.Usage = D3D11_USAGE_STAGING; bd.BindFlags = 0; /* No flags allowed. */ bd.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->staging.pBuffer); Assert(SUCCEEDED(hr)); } #endif if (SUCCEEDED(hr)) { /* * Success. */ pBackendSurface->enmResType = VMSVGA3D_RESTYPE_BUFFER; pBackendSurface->enmDxgiFormat = DXGI_FORMAT_UNKNOWN; pSurface->pBackendSurface = pBackendSurface; pSurface->idAssociatedContext = pDXContext->cid; return VINF_SUCCESS; } /* Failure. */ D3D_RELEASE(pBackendSurface->u.pBuffer); #ifndef DX_COMMON_STAGING_BUFFER D3D_RELEASE(pBackendSurface->dynamic.pBuffer); D3D_RELEASE(pBackendSurface->staging.pBuffer); #endif RTMemFree(pBackendSurface); return VERR_NO_MEMORY; } static int vmsvga3dBackSurfaceCreateSoBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /* Buffers should be created as such. */ AssertReturn(RT_BOOL(pSurface->f.surfaceFlags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT), VERR_INVALID_PARAMETER); if (pSurface->pBackendSurface != NULL) { AssertFailed(); /** @todo Should the function not be used like that? */ vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); } PVMSVGA3DBACKENDSURFACE pBackendSurface; int rc = dxBackendSurfaceAlloc(&pBackendSurface); AssertRCReturn(rc, rc); D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = pSurface->paMipmapLevels[0].cbSurface; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); bd.CPUAccessFlags = 0; /// @todo ? D3D11_CPU_ACCESS_READ; bd.MiscFlags = 0; bd.StructureByteStride = 0; HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, 0, &pBackendSurface->u.pBuffer); #ifndef DX_COMMON_STAGING_BUFFER if (SUCCEEDED(hr)) { /* Map-able Buffer. */ bd.Usage = D3D11_USAGE_DYNAMIC; bd.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; hr = pDevice->pDevice->CreateBuffer(&bd, 0, &pBackendSurface->dynamic.pBuffer); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) { /* Staging texture. */ bd.Usage = D3D11_USAGE_STAGING; bd.BindFlags = 0; /* No flags allowed. */ bd.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; hr = pDevice->pDevice->CreateBuffer(&bd, 0, &pBackendSurface->staging.pBuffer); Assert(SUCCEEDED(hr)); } #endif if (SUCCEEDED(hr)) { /* * Success. */ pBackendSurface->enmResType = VMSVGA3D_RESTYPE_BUFFER; pBackendSurface->enmDxgiFormat = DXGI_FORMAT_UNKNOWN; pSurface->pBackendSurface = pBackendSurface; pSurface->idAssociatedContext = pDXContext->cid; return VINF_SUCCESS; } /* Failure. */ D3D_RELEASE(pBackendSurface->u.pBuffer); #ifndef DX_COMMON_STAGING_BUFFER D3D_RELEASE(pBackendSurface->dynamic.pBuffer); D3D_RELEASE(pBackendSurface->staging.pBuffer); #endif RTMemFree(pBackendSurface); return VERR_NO_MEMORY; } #if 0 static int vmsvga3dBackSurfaceCreateConstantBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface, uint32_t offsetInBytes, uint32_t sizeInBytes) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /* Buffers should be created as such. */ AssertReturn(RT_BOOL(pSurface->f.surfaceFlags & ( SVGA3D_SURFACE_BIND_CONSTANT_BUFFER)), VERR_INVALID_PARAMETER); if (pSurface->pBackendSurface != NULL) { AssertFailed(); /** @todo Should the function not be used like that? */ vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); } PVMSVGA3DMIPMAPLEVEL pMipLevel; int rc = vmsvga3dMipmapLevel(pSurface, 0, 0, &pMipLevel); AssertRCReturn(rc, rc); ASSERT_GUEST_RETURN( offsetInBytes < pMipLevel->cbSurface && sizeInBytes <= pMipLevel->cbSurface - offsetInBytes, VERR_INVALID_PARAMETER); PVMSVGA3DBACKENDSURFACE pBackendSurface; rc = dxBackendSurfaceAlloc(&pBackendSurface); AssertRCReturn(rc, rc); /* Upload the current data, if any. */ D3D11_SUBRESOURCE_DATA *pInitialData = NULL; D3D11_SUBRESOURCE_DATA initialData; if (pMipLevel->pSurfaceData) { initialData.pSysMem = (uint8_t *)pMipLevel->pSurfaceData + offsetInBytes; initialData.SysMemPitch = pMipLevel->cbSurface; initialData.SysMemSlicePitch = pMipLevel->cbSurface; pInitialData = &initialData; // Log(("%.*Rhxd\n", sizeInBytes, initialData.pSysMem)); } D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = sizeInBytes; bd.Usage = D3D11_USAGE_DYNAMIC; bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; bd.MiscFlags = 0; bd.StructureByteStride = 0; HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->u.pBuffer); if (SUCCEEDED(hr)) { /* * Success. */ pBackendSurface->enmResType = VMSVGA3D_RESTYPE_BUFFER; pBackendSurface->enmDxgiFormat = DXGI_FORMAT_UNKNOWN; pSurface->pBackendSurface = pBackendSurface; pSurface->idAssociatedContext = pDXContext->cid; return VINF_SUCCESS; } /* Failure. */ D3D_RELEASE(pBackendSurface->u.pBuffer); RTMemFree(pBackendSurface); return VERR_NO_MEMORY; } #endif static int vmsvga3dBackSurfaceCreateResource(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PVMSVGA3DSURFACE pSurface) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); if (pSurface->pBackendSurface != NULL) { AssertFailed(); /** @todo Should the function not be used like that? */ vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); } PVMSVGA3DMIPMAPLEVEL pMipLevel; int rc = vmsvga3dMipmapLevel(pSurface, 0, 0, &pMipLevel); AssertRCReturn(rc, rc); PVMSVGA3DBACKENDSURFACE pBackendSurface; rc = dxBackendSurfaceAlloc(&pBackendSurface); AssertRCReturn(rc, rc); HRESULT hr; /* * Figure out the type of the surface. */ if (pSurface->format == SVGA3D_BUFFER) { /* Upload the current data, if any. */ D3D11_SUBRESOURCE_DATA *pInitialData = NULL; D3D11_SUBRESOURCE_DATA initialData; if (pMipLevel->pSurfaceData) { initialData.pSysMem = pMipLevel->pSurfaceData; initialData.SysMemPitch = pMipLevel->cbSurface; initialData.SysMemSlicePitch = pMipLevel->cbSurface; pInitialData = &initialData; } D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = pMipLevel->cbSurface; if (pSurface->f.surfaceFlags & (SVGA3D_SURFACE_STAGING_UPLOAD | SVGA3D_SURFACE_STAGING_DOWNLOAD)) bd.Usage = D3D11_USAGE_STAGING; else if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_DYNAMIC) bd.Usage = D3D11_USAGE_DYNAMIC; else if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_STATIC) bd.Usage = pInitialData ? D3D11_USAGE_IMMUTABLE : D3D11_USAGE_DEFAULT; /* Guest will update later. */ else if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_INDIRECT_UPDATE) bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = dxBindFlags(pSurface->f.surfaceFlags); if (bd.Usage == D3D11_USAGE_STAGING) bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; else if (bd.Usage == D3D11_USAGE_DYNAMIC) bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_DRAWINDIRECT_ARGS) bd.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_BIND_RAW_VIEWS) bd.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_BUFFER_STRUCTURED) bd.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_RESOURCE_CLAMP) bd.MiscFlags |= D3D11_RESOURCE_MISC_RESOURCE_CLAMP; if (bd.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) { SVGAOTableSurfaceEntry entrySurface; rc = vmsvgaR3OTableReadSurface(pThisCC->svga.pSvgaR3State, pSurface->id, &entrySurface); AssertRCReturn(rc, rc); bd.StructureByteStride = entrySurface.bufferByteStride; } hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->u.pBuffer); Assert(SUCCEEDED(hr)); #ifndef DX_COMMON_STAGING_BUFFER if (SUCCEEDED(hr)) { /* Map-able Buffer. */ bd.Usage = D3D11_USAGE_DYNAMIC; bd.BindFlags = D3D11_BIND_SHADER_RESOURCE; /* Have to specify a supported flag, otherwise E_INVALIDARG will be returned. */ bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->dynamic.pBuffer); Assert(SUCCEEDED(hr)); } if (SUCCEEDED(hr)) { /* Staging texture. */ bd.Usage = D3D11_USAGE_STAGING; bd.BindFlags = 0; /* No flags allowed. */ bd.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBackendSurface->staging.pBuffer); Assert(SUCCEEDED(hr)); } #endif if (SUCCEEDED(hr)) { pBackendSurface->enmResType = VMSVGA3D_RESTYPE_BUFFER; pBackendSurface->enmDxgiFormat = DXGI_FORMAT_UNKNOWN; } } else { /** @todo Texture. Currently vmsvga3dBackSurfaceCreateTexture is called for textures. */ AssertFailed(); hr = E_FAIL; } if (SUCCEEDED(hr)) { /* * Success. */ pSurface->pBackendSurface = pBackendSurface; pSurface->idAssociatedContext = pDXContext->cid; return VINF_SUCCESS; } /* Failure. */ D3D_RELEASE(pBackendSurface->u.pResource); D3D_RELEASE(pBackendSurface->dynamic.pResource); D3D_RELEASE(pBackendSurface->staging.pResource); RTMemFree(pBackendSurface); return VERR_NO_MEMORY; } #ifdef DX_COMMON_STAGING_BUFFER static int dxStagingBufferRealloc(DXDEVICE *pDXDevice, uint32_t cbRequiredSize) { AssertReturn(cbRequiredSize < SVGA3D_MAX_SURFACE_MEM_SIZE, VERR_INVALID_PARAMETER); if (RT_LIKELY(cbRequiredSize <= pDXDevice->cbStagingBuffer)) return VINF_SUCCESS; D3D_RELEASE(pDXDevice->pStagingBuffer); uint32_t const cbAlloc = RT_ALIGN_32(cbRequiredSize, _64K); D3D11_SUBRESOURCE_DATA *pInitialData = NULL; D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = cbAlloc; bd.Usage = D3D11_USAGE_STAGING; //bd.BindFlags = 0; /* No bind flags are allowed for staging resources. */ bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; int rc = VINF_SUCCESS; ID3D11Buffer *pBuffer; HRESULT hr = pDXDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBuffer); if (SUCCEEDED(hr)) { pDXDevice->pStagingBuffer = pBuffer; pDXDevice->cbStagingBuffer = cbAlloc; } else { pDXDevice->cbStagingBuffer = 0; rc = VERR_NO_MEMORY; } return rc; } #endif static DECLCALLBACK(int) vmsvga3dBackInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) { RT_NOREF(pDevIns, pThis); int rc; #ifdef RT_OS_LINUX /** @todo Remove, this is currently needed for loading the X11 library in order to call XInitThreads(). */ rc = glLdrInit(pDevIns); if (RT_FAILURE(rc)) { LogRel(("VMSVGA3d: Error loading OpenGL library and resolving necessary functions: %Rrc\n", rc)); return rc; } #endif PVMSVGA3DBACKEND pBackend = (PVMSVGA3DBACKEND)RTMemAllocZ(sizeof(VMSVGA3DBACKEND)); AssertReturn(pBackend, VERR_NO_MEMORY); pThisCC->svga.p3dState->pBackend = pBackend; rc = RTLdrLoadSystem(VBOX_D3D11_LIBRARY_NAME, /* fNoUnload = */ true, &pBackend->hD3D11); AssertRC(rc); if (RT_SUCCESS(rc)) { rc = RTLdrGetSymbol(pBackend->hD3D11, "D3D11CreateDevice", (void **)&pBackend->pfnD3D11CreateDevice); AssertRC(rc); } if (RT_SUCCESS(rc)) { /* Failure to load the shader disassembler is ignored. */ int rc2 = RTLdrLoadSystem("D3DCompiler_47", /* fNoUnload = */ true, &pBackend->hD3DCompiler); if (RT_SUCCESS(rc2)) rc2 = RTLdrGetSymbol(pBackend->hD3DCompiler, "D3DDisassemble", (void **)&pBackend->pfnD3DDisassemble); Log6Func(("Load D3DDisassemble: %Rrc\n", rc2)); } #if !defined(RT_OS_WINDOWS) || defined(DX_FORCE_SINGLE_DEVICE) pBackend->fSingleDevice = true; #endif LogRelMax(1, ("VMSVGA: Single DX device mode: %s\n", pBackend->fSingleDevice ? "enabled" : "disabled")); //DEBUG_BREAKPOINT_TEST(); return rc; } static DECLCALLBACK(int) vmsvga3dBackPowerOn(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC) { RT_NOREF(pDevIns, pThis); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); PVMSVGA3DBACKEND pBackend = pState->pBackend; AssertReturn(pBackend, VERR_INVALID_STATE); int rc = dxDeviceCreate(pBackend, &pBackend->dxDevice); if (RT_SUCCESS(rc)) { IDXGIAdapter *pAdapter = NULL; HRESULT hr = pBackend->dxDevice.pDxgiFactory->EnumAdapters(0, &pAdapter); if (SUCCEEDED(hr)) { DXGI_ADAPTER_DESC desc; hr = pAdapter->GetDesc(&desc); if (SUCCEEDED(hr)) { char sz[RT_ELEMENTS(desc.Description)]; for (unsigned i = 0; i < RT_ELEMENTS(desc.Description); ++i) sz[i] = (char)desc.Description[i]; LogRelMax(1, ("VMSVGA: Adapter [%s]\n", sz)); } pAdapter->Release(); } } return rc; } static DECLCALLBACK(int) vmsvga3dBackReset(PVGASTATECC pThisCC) { RT_NOREF(pThisCC); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackTerminate(PVGASTATECC pThisCC) { PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); if (pState->pBackend) dxDeviceDestroy(pState->pBackend, &pState->pBackend->dxDevice); return VINF_SUCCESS; } /** @todo Such structures must be in VBoxVideo3D.h */ typedef struct VBOX3DNOTIFYDEFINESCREEN { VBOX3DNOTIFY Core; uint32_t cWidth; uint32_t cHeight; int32_t xRoot; int32_t yRoot; uint32_t fPrimary; uint32_t cDpi; } VBOX3DNOTIFYDEFINESCREEN; static int vmsvga3dDrvNotifyDefineScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) { VBOX3DNOTIFYDEFINESCREEN n; n.Core.enmNotification = VBOX3D_NOTIFY_TYPE_HW_SCREEN_CREATED; n.Core.iDisplay = pScreen->idScreen; n.Core.u32Reserved = 0; n.Core.cbData = sizeof(n) - RT_UOFFSETOF(VBOX3DNOTIFY, au8Data); RT_ZERO(n.Core.au8Data); n.cWidth = pScreen->cWidth; n.cHeight = pScreen->cHeight; n.xRoot = pScreen->xOrigin; n.yRoot = pScreen->yOrigin; n.fPrimary = RT_BOOL(pScreen->fuScreen & SVGA_SCREEN_IS_PRIMARY); n.cDpi = pScreen->cDpi; return pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, &n.Core); } static int vmsvga3dDrvNotifyDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) { VBOX3DNOTIFY n; n.enmNotification = VBOX3D_NOTIFY_TYPE_HW_SCREEN_DESTROYED; n.iDisplay = pScreen->idScreen; n.u32Reserved = 0; n.cbData = sizeof(n) - RT_UOFFSETOF(VBOX3DNOTIFY, au8Data); RT_ZERO(n.au8Data); return pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, &n); } static int vmsvga3dDrvNotifyBindSurface(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, HANDLE hSharedSurface) { VBOX3DNOTIFY n; n.enmNotification = VBOX3D_NOTIFY_TYPE_HW_SCREEN_BIND_SURFACE; n.iDisplay = pScreen->idScreen; n.u32Reserved = 0; n.cbData = sizeof(n) - RT_UOFFSETOF(VBOX3DNOTIFY, au8Data); *(uint64_t *)&n.au8Data[0] = (uint64_t)hSharedSurface; return pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, &n); } typedef struct VBOX3DNOTIFYUPDATE { VBOX3DNOTIFY Core; uint32_t x; uint32_t y; uint32_t w; uint32_t h; } VBOX3DNOTIFYUPDATE; static int vmsvga3dDrvNotifyUpdate(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, uint32_t x, uint32_t y, uint32_t w, uint32_t h) { VBOX3DNOTIFYUPDATE n; n.Core.enmNotification = VBOX3D_NOTIFY_TYPE_HW_SCREEN_UPDATE_END; n.Core.iDisplay = pScreen->idScreen; n.Core.u32Reserved = 0; n.Core.cbData = sizeof(n) - RT_UOFFSETOF(VBOX3DNOTIFY, au8Data); RT_ZERO(n.Core.au8Data); n.x = x; n.y = y; n.w = w; n.h = h; return pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, &n.Core); } static int vmsvga3dHwScreenCreate(PVMSVGA3DSTATE pState, uint32_t cWidth, uint32_t cHeight, VMSVGAHWSCREEN *p) { PVMSVGA3DBACKEND pBackend = pState->pBackend; DXDEVICE *pDXDevice = &pBackend->dxDevice; AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); D3D11_TEXTURE2D_DESC td; RT_ZERO(td); td.Width = cWidth; td.Height = cHeight; td.MipLevels = 1; td.ArraySize = 1; td.Format = DXGI_FORMAT_B8G8R8A8_UNORM; td.SampleDesc.Count = 1; td.SampleDesc.Quality = 0; td.Usage = D3D11_USAGE_DEFAULT; td.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; td.CPUAccessFlags = 0; td.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; HRESULT hr = pDXDevice->pDevice->CreateTexture2D(&td, 0, &p->pTexture); if (SUCCEEDED(hr)) { /* Get the shared handle. */ hr = p->pTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&p->pDxgiResource); if (SUCCEEDED(hr)) { hr = p->pDxgiResource->GetSharedHandle(&p->SharedHandle); if (SUCCEEDED(hr)) hr = p->pTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&p->pDXGIKeyedMutex); } } if (SUCCEEDED(hr)) return VINF_SUCCESS; AssertFailed(); return VERR_NOT_SUPPORTED; } static void vmsvga3dHwScreenDestroy(PVMSVGA3DSTATE pState, VMSVGAHWSCREEN *p) { RT_NOREF(pState); D3D_RELEASE(p->pDXGIKeyedMutex); D3D_RELEASE(p->pDxgiResource); D3D_RELEASE(p->pTexture); p->SharedHandle = 0; p->sidScreenTarget = SVGA_ID_INVALID; } static DECLCALLBACK(int) vmsvga3dBackDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) { RT_NOREF(pThis, pThisCC, pScreen); LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: screen %u\n", pScreen->idScreen)); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); PVMSVGA3DBACKEND pBackend = pState->pBackend; AssertReturn(pBackend, VERR_INVALID_STATE); Assert(pScreen->pHwScreen == NULL); VMSVGAHWSCREEN *p = (VMSVGAHWSCREEN *)RTMemAllocZ(sizeof(VMSVGAHWSCREEN)); AssertPtrReturn(p, VERR_NO_MEMORY); p->sidScreenTarget = SVGA_ID_INVALID; int rc = vmsvga3dDrvNotifyDefineScreen(pThisCC, pScreen); if (RT_SUCCESS(rc)) { /* The frontend supports the screen. Create the actual resource. */ rc = vmsvga3dHwScreenCreate(pState, pScreen->cWidth, pScreen->cHeight, p); if (RT_SUCCESS(rc)) LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: created\n")); } if (RT_SUCCESS(rc)) { LogRel(("VMSVGA: Using HW accelerated screen %u\n", pScreen->idScreen)); pScreen->pHwScreen = p; } else { LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: %Rrc\n", rc)); vmsvga3dHwScreenDestroy(pState, p); RTMemFree(p); } return rc; } static DECLCALLBACK(int) vmsvga3dBackDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen) { PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); vmsvga3dDrvNotifyDestroyScreen(pThisCC, pScreen); if (pScreen->pHwScreen) { vmsvga3dHwScreenDestroy(pState, pScreen->pHwScreen); RTMemFree(pScreen->pHwScreen); pScreen->pHwScreen = NULL; } return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSurfaceBlitToScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage, SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects) { RT_NOREF(pThisCC, pScreen, destRect, srcImage, srcRect, cRects, paRects); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); PVMSVGA3DBACKEND pBackend = pState->pBackend; AssertReturn(pBackend, VERR_INVALID_STATE); VMSVGAHWSCREEN *p = pScreen->pHwScreen; AssertReturn(p, VERR_NOT_SUPPORTED); PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pState, srcImage.sid, &pSurface); AssertRCReturn(rc, rc); /** @todo Implement. */ AssertFailed(); return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackSurfaceMap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, SVGA3dBox const *pBox, VMSVGA3D_SURFACE_MAP enmMapType, VMSVGA3D_MAPPED_SURFACE *pMap) { PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); PVMSVGA3DBACKEND pBackend = pState->pBackend; AssertReturn(pBackend, VERR_INVALID_STATE); PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pState, pImage->sid, &pSurface); AssertRCReturn(rc, rc); PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; AssertPtrReturn(pBackendSurface, VERR_INVALID_STATE); PVMSVGA3DMIPMAPLEVEL pMipLevel; rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); /* A surface is always mapped by the DX context which has created the surface. */ DXDEVICE *pDevice = dxDeviceFromCid(pSurface->idAssociatedContext, pState); AssertReturn(pDevice && pDevice->pDevice, VERR_INVALID_STATE); SVGA3dBox clipBox; if (pBox) { clipBox = *pBox; vmsvgaR3ClipBox(&pMipLevel->mipmapSize, &clipBox); ASSERT_GUEST_RETURN(clipBox.w && clipBox.h && clipBox.d, VERR_INVALID_PARAMETER); } else { clipBox.x = 0; clipBox.y = 0; clipBox.z = 0; clipBox.w = pMipLevel->mipmapSize.width; clipBox.h = pMipLevel->mipmapSize.height; clipBox.d = pMipLevel->mipmapSize.depth; } D3D11_MAP d3d11MapType; switch (enmMapType) { case VMSVGA3D_SURFACE_MAP_READ: d3d11MapType = D3D11_MAP_READ; break; case VMSVGA3D_SURFACE_MAP_WRITE: d3d11MapType = D3D11_MAP_WRITE; break; case VMSVGA3D_SURFACE_MAP_READ_WRITE: d3d11MapType = D3D11_MAP_READ_WRITE; break; case VMSVGA3D_SURFACE_MAP_WRITE_DISCARD: d3d11MapType = D3D11_MAP_WRITE_DISCARD; break; default: AssertFailed(); return VERR_INVALID_PARAMETER; } D3D11_MAPPED_SUBRESOURCE mappedResource; RT_ZERO(mappedResource); if ( pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_1D || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_CUBE || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) { dxSurfaceWait(pState, pSurface, pSurface->idAssociatedContext); ID3D11Resource *pMappedResource; if (enmMapType == VMSVGA3D_SURFACE_MAP_READ) { pMappedResource = pBackendSurface->staging.pResource; /* Copy the texture content to the staging texture. * The requested miplevel of the texture is copied to the miplevel 0 of the staging texture, * because the staging (and dynamic) structures do not have miplevels. * Always copy entire miplevel so all Dst are zero and pSrcBox is NULL, as D3D11 requires. */ ID3D11Resource *pDstResource = pMappedResource; UINT DstSubresource = 0; UINT DstX = 0; UINT DstY = 0; UINT DstZ = 0; ID3D11Resource *pSrcResource = pBackendSurface->u.pResource; UINT SrcSubresource = D3D11CalcSubresource(pImage->mipmap, pImage->face, pSurface->cLevels); D3D11_BOX *pSrcBox = NULL; //D3D11_BOX SrcBox; //SrcBox.left = 0; //SrcBox.top = 0; //SrcBox.front = 0; //SrcBox.right = pMipLevel->mipmapSize.width; //SrcBox.bottom = pMipLevel->mipmapSize.height; //SrcBox.back = pMipLevel->mipmapSize.depth; pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox); } else if (enmMapType == VMSVGA3D_SURFACE_MAP_WRITE) pMappedResource = pBackendSurface->staging.pResource; else pMappedResource = pBackendSurface->dynamic.pResource; UINT const Subresource = 0; /* Dynamic or staging textures have one subresource. */ HRESULT hr = pDevice->pImmediateContext->Map(pMappedResource, Subresource, d3d11MapType, /* MapFlags = */ 0, &mappedResource); if (SUCCEEDED(hr)) vmsvga3dSurfaceMapInit(pMap, enmMapType, &clipBox, pSurface, mappedResource.pData, mappedResource.RowPitch, mappedResource.DepthPitch); else AssertFailedStmt(rc = VERR_NOT_SUPPORTED); } else if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_BUFFER) { #ifdef DX_COMMON_STAGING_BUFFER /* Map the staging buffer. */ rc = dxStagingBufferRealloc(pDevice, pMipLevel->cbSurface); if (RT_SUCCESS(rc)) { /* The staging buffer does not allow D3D11_MAP_WRITE_DISCARD, so replace it. */ if (d3d11MapType == D3D11_MAP_WRITE_DISCARD) d3d11MapType = D3D11_MAP_WRITE; if (enmMapType == VMSVGA3D_SURFACE_MAP_READ) { /* Copy from the buffer to the staging buffer. */ ID3D11Resource *pDstResource = pDevice->pStagingBuffer; UINT DstSubresource = 0; UINT DstX = clipBox.x; UINT DstY = clipBox.y; UINT DstZ = clipBox.z; ID3D11Resource *pSrcResource = pBackendSurface->u.pResource; UINT SrcSubresource = 0; D3D11_BOX SrcBox; SrcBox.left = clipBox.x; SrcBox.top = clipBox.y; SrcBox.front = clipBox.z; SrcBox.right = clipBox.w; SrcBox.bottom = clipBox.h; SrcBox.back = clipBox.d; pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, &SrcBox); } UINT const Subresource = 0; /* Buffers have only one subresource. */ HRESULT hr = pDevice->pImmediateContext->Map(pDevice->pStagingBuffer, Subresource, d3d11MapType, /* MapFlags = */ 0, &mappedResource); if (SUCCEEDED(hr)) vmsvga3dSurfaceMapInit(pMap, enmMapType, &clipBox, pSurface, mappedResource.pData, mappedResource.RowPitch, mappedResource.DepthPitch); else AssertFailedStmt(rc = VERR_NOT_SUPPORTED); } #else ID3D11Resource *pMappedResource; if (enmMapType == VMSVGA3D_SURFACE_MAP_READ) { pMappedResource = pBackendSurface->staging.pResource; /* Copy the resource content to the staging resource. */ ID3D11Resource *pDstResource = pMappedResource; UINT DstSubresource = 0; UINT DstX = clipBox.x; UINT DstY = clipBox.y; UINT DstZ = clipBox.z; ID3D11Resource *pSrcResource = pBackendSurface->u.pResource; UINT SrcSubresource = 0; D3D11_BOX SrcBox; SrcBox.left = clipBox.x; SrcBox.top = clipBox.y; SrcBox.front = clipBox.z; SrcBox.right = clipBox.w; SrcBox.bottom = clipBox.h; SrcBox.back = clipBox.d; pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, &SrcBox); } else if (enmMapType == VMSVGA3D_SURFACE_MAP_WRITE) pMappedResource = pBackendSurface->staging.pResource; else pMappedResource = pBackendSurface->dynamic.pResource; UINT const Subresource = 0; /* Dynamic or staging textures have one subresource. */ HRESULT hr = pDevice->pImmediateContext->Map(pMappedResource, Subresource, d3d11MapType, /* MapFlags = */ 0, &mappedResource); if (SUCCEEDED(hr)) vmsvga3dSurfaceMapInit(pMap, enmMapType, &clipBox, pSurface, mappedResource.pData, mappedResource.RowPitch, mappedResource.DepthPitch); else AssertFailedStmt(rc = VERR_NOT_SUPPORTED); #endif } else { // UINT D3D11CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT MipLevels); /** @todo Implement. */ AssertFailed(); rc = VERR_NOT_IMPLEMENTED; } return rc; } static DECLCALLBACK(int) vmsvga3dBackSurfaceUnmap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, VMSVGA3D_MAPPED_SURFACE *pMap, bool fWritten) { PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); PVMSVGA3DBACKEND pBackend = pState->pBackend; AssertReturn(pBackend, VERR_INVALID_STATE); PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pState, pImage->sid, &pSurface); AssertRCReturn(rc, rc); /* The called should not use the function for system memory surfaces. */ PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; AssertReturn(pBackendSurface, VERR_INVALID_PARAMETER); PVMSVGA3DMIPMAPLEVEL pMipLevel; rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); /* A surface is always mapped by the DX context which has created the surface. */ DXDEVICE *pDevice = dxDeviceFromCid(pSurface->idAssociatedContext, pState); AssertReturn(pDevice && pDevice->pDevice, VERR_INVALID_STATE); if ( pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_1D || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_CUBE || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) { ID3D11Resource *pMappedResource; if (pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ) pMappedResource = pBackendSurface->staging.pResource; else if (pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE) pMappedResource = pBackendSurface->staging.pResource; else pMappedResource = pBackendSurface->dynamic.pResource; UINT const Subresource = 0; /* Staging or dynamic textures have one subresource. */ pDevice->pImmediateContext->Unmap(pMappedResource, Subresource); if ( fWritten && ( pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ_WRITE || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD)) { /* If entire resource must be copied then use pSrcBox = NULL and dst point (0,0,0) * Because DX11 insists on this for some resource types, for example DEPTH_STENCIL resources. */ uint32_t const cWidth0 = pSurface->paMipmapLevels[0].mipmapSize.width; uint32_t const cHeight0 = pSurface->paMipmapLevels[0].mipmapSize.height; uint32_t const cDepth0 = pSurface->paMipmapLevels[0].mipmapSize.depth; /** @todo Entire subresource is always mapped. So find a way to copy it back, important for DEPTH_STENCIL mipmaps. */ bool const fEntireResource = pMap->box.x == 0 && pMap->box.y == 0 && pMap->box.z == 0 && pMap->box.w == cWidth0 && pMap->box.h == cHeight0 && pMap->box.d == cDepth0; ID3D11Resource *pDstResource = pBackendSurface->u.pResource; UINT DstSubresource = D3D11CalcSubresource(pImage->mipmap, pImage->face, pSurface->cLevels); UINT DstX = (pMap->box.x / pSurface->cxBlock) * pSurface->cxBlock; UINT DstY = (pMap->box.y / pSurface->cyBlock) * pSurface->cyBlock; UINT DstZ = pMap->box.z; ID3D11Resource *pSrcResource = pMappedResource; UINT SrcSubresource = Subresource; D3D11_BOX *pSrcBox; D3D11_BOX SrcBox; if (fEntireResource) pSrcBox = NULL; else { uint32_t const cxBlocks = (pMap->box.w + pSurface->cxBlock - 1) / pSurface->cxBlock; uint32_t const cyBlocks = (pMap->box.h + pSurface->cyBlock - 1) / pSurface->cyBlock; SrcBox.left = DstX; SrcBox.top = DstY; SrcBox.front = DstZ; SrcBox.right = DstX + cxBlocks * pSurface->cxBlock; SrcBox.bottom = DstY + cyBlocks * pSurface->cyBlock; SrcBox.back = DstZ + pMap->box.d; pSrcBox = &SrcBox; } pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox); pBackendSurface->cidDrawing = pSurface->idAssociatedContext; } } else if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_BUFFER) { Log4(("Unmap buffer sid = %u:\n%.*Rhxd\n", pSurface->id, pMap->cbRow, pMap->pvData)); #ifdef DX_COMMON_STAGING_BUFFER /* Unmap the staging buffer. */ UINT const Subresource = 0; /* Buffers have only one subresource. */ pDevice->pImmediateContext->Unmap(pDevice->pStagingBuffer, Subresource); /* Copy from the staging buffer to the actual buffer */ if ( fWritten && ( pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ_WRITE || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD)) { ID3D11Resource *pDstResource = pBackendSurface->u.pResource; UINT DstSubresource = 0; UINT DstX = (pMap->box.x / pSurface->cxBlock) * pSurface->cxBlock; UINT DstY = (pMap->box.y / pSurface->cyBlock) * pSurface->cyBlock; UINT DstZ = pMap->box.z; ID3D11Resource *pSrcResource = pDevice->pStagingBuffer; UINT SrcSubresource = 0; D3D11_BOX SrcBox; uint32_t const cxBlocks = (pMap->box.w + pSurface->cxBlock - 1) / pSurface->cxBlock; uint32_t const cyBlocks = (pMap->box.h + pSurface->cyBlock - 1) / pSurface->cyBlock; SrcBox.left = DstX; SrcBox.top = DstY; SrcBox.front = DstZ; SrcBox.right = DstX + cxBlocks * pSurface->cxBlock; SrcBox.bottom = DstY + cyBlocks * pSurface->cyBlock; SrcBox.back = DstZ + pMap->box.d; pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, &SrcBox); } #else ID3D11Resource *pMappedResource; if (pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ) pMappedResource = pBackendSurface->staging.pResource; else if (pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE) pMappedResource = pBackendSurface->staging.pResource; else pMappedResource = pBackendSurface->dynamic.pResource; UINT const Subresource = 0; /* Staging or dynamic textures have one subresource. */ pDevice->pImmediateContext->Unmap(pMappedResource, Subresource); if ( fWritten && ( pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ_WRITE || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD)) { ID3D11Resource *pDstResource = pBackendSurface->u.pResource; UINT DstSubresource = 0; UINT DstX = pMap->box.x; UINT DstY = pMap->box.y; UINT DstZ = pMap->box.z; ID3D11Resource *pSrcResource = pMappedResource; UINT SrcSubresource = 0; D3D11_BOX SrcBox; SrcBox.left = DstX; SrcBox.top = DstY; SrcBox.front = DstZ; SrcBox.right = DstX + pMap->box.w; SrcBox.bottom = DstY + pMap->box.h; SrcBox.back = DstZ + pMap->box.d; pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, &SrcBox); pBackendSurface->cidDrawing = pSurface->idAssociatedContext; } #endif } else { AssertFailed(); rc = VERR_NOT_IMPLEMENTED; } return rc; } static DECLCALLBACK(int) vmsvga3dScreenTargetBind(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, uint32_t sid) { int rc = VINF_SUCCESS; PVMSVGA3DSURFACE pSurface; if (sid != SVGA_ID_INVALID) { /* Create the surface if does not yet exist. */ PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface); AssertRCReturn(rc, rc); if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)) { /* Create the actual texture. */ rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, NULL, pSurface); AssertRCReturn(rc, rc); } } else pSurface = NULL; /* Notify the HW accelerated screen if it is used. */ VMSVGAHWSCREEN *pHwScreen = pScreen->pHwScreen; if (!pHwScreen) return VINF_SUCCESS; /* Same surface -> do nothing. */ if (pHwScreen->sidScreenTarget == sid) return VINF_SUCCESS; if (sid != SVGA_ID_INVALID) { AssertReturn( pSurface->pBackendSurface && pSurface->pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D && RT_BOOL(pSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET), VERR_INVALID_PARAMETER); HANDLE const hSharedSurface = pHwScreen->SharedHandle; rc = vmsvga3dDrvNotifyBindSurface(pThisCC, pScreen, hSharedSurface); } if (RT_SUCCESS(rc)) { pHwScreen->sidScreenTarget = sid; } return rc; } static DECLCALLBACK(int) vmsvga3dScreenTargetUpdate(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, SVGA3dRect const *pRect) { VMSVGAHWSCREEN *pHwScreen = pScreen->pHwScreen; AssertReturn(pHwScreen, VERR_NOT_SUPPORTED); if (pHwScreen->sidScreenTarget == SVGA_ID_INVALID) return VINF_SUCCESS; /* No surface bound. */ PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); PVMSVGA3DBACKEND pBackend = pState->pBackend; AssertReturn(pBackend, VERR_INVALID_STATE); PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pState, pHwScreen->sidScreenTarget, &pSurface); AssertRCReturn(rc, rc); PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; AssertReturn( pBackendSurface && pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D && RT_BOOL(pSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET), VERR_INVALID_PARAMETER); SVGA3dRect boundRect; boundRect.x = 0; boundRect.y = 0; boundRect.w = pSurface->paMipmapLevels[0].mipmapSize.width; boundRect.h = pSurface->paMipmapLevels[0].mipmapSize.height; SVGA3dRect clipRect = *pRect; vmsvgaR3Clip3dRect(&boundRect, &clipRect); ASSERT_GUEST_RETURN(clipRect.w && clipRect.h, VERR_INVALID_PARAMETER); /* Wait for the surface to finish drawing. */ dxSurfaceWait(pState, pSurface, DX_CID_BACKEND); /* Copy the screen texture to the shared surface. */ DWORD result = pHwScreen->pDXGIKeyedMutex->AcquireSync(0, 10000); if (result == S_OK) { pBackend->dxDevice.pImmediateContext->CopyResource(pHwScreen->pTexture, pBackendSurface->u.pTexture2D); dxDeviceFlush(&pBackend->dxDevice); result = pHwScreen->pDXGIKeyedMutex->ReleaseSync(1); } else AssertFailed(); rc = vmsvga3dDrvNotifyUpdate(pThisCC, pScreen, pRect->x, pRect->y, pRect->w, pRect->h); return rc; } /* * * 3D interface. * */ static DECLCALLBACK(int) vmsvga3dBackQueryCaps(PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val) { PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); int rc = VINF_SUCCESS; *pu32Val = 0; if (idx3dCaps > SVGA3D_DEVCAP_MAX) { LogRelMax(16, ("VMSVGA: unsupported SVGA3D_DEVCAP %d\n", idx3dCaps)); return VERR_NOT_SUPPORTED; } D3D_FEATURE_LEVEL const FeatureLevel = pState->pBackend->dxDevice.FeatureLevel; /* Most values are taken from: * https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-intro * * Shader values are from * https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-models */ switch (idx3dCaps) { case SVGA3D_DEVCAP_3D: *pu32Val = 1; break; case SVGA3D_DEVCAP_MAX_LIGHTS: *pu32Val = SVGA3D_NUM_LIGHTS; /* VGPU9. Not applicable to DX11. */ break; case SVGA3D_DEVCAP_MAX_TEXTURES: *pu32Val = SVGA3D_NUM_TEXTURE_UNITS; /* VGPU9. Not applicable to DX11. */ break; case SVGA3D_DEVCAP_MAX_CLIP_PLANES: *pu32Val = SVGA3D_NUM_CLIPPLANES; break; case SVGA3D_DEVCAP_VERTEX_SHADER_VERSION: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = SVGA3DVSVERSION_40; else *pu32Val = SVGA3DVSVERSION_30; break; case SVGA3D_DEVCAP_VERTEX_SHADER: *pu32Val = 1; break; case SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = SVGA3DPSVERSION_40; else *pu32Val = SVGA3DPSVERSION_30; break; case SVGA3D_DEVCAP_FRAGMENT_SHADER: *pu32Val = 1; break; case SVGA3D_DEVCAP_MAX_RENDER_TARGETS: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = 8; else *pu32Val = 4; break; case SVGA3D_DEVCAP_S23E8_TEXTURES: case SVGA3D_DEVCAP_S10E5_TEXTURES: /* Must be obsolete by now; surface format caps specify the same thing. */ break; case SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND: /* Obsolete */ break; /* * 2. The BUFFER_FORMAT capabilities are deprecated, and they always * return TRUE. Even on physical hardware that does not support * these formats natively, the SVGA3D device will provide an emulation * which should be invisible to the guest OS. */ case SVGA3D_DEVCAP_D16_BUFFER_FORMAT: case SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT: case SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT: *pu32Val = 1; break; case SVGA3D_DEVCAP_QUERY_TYPES: /* Obsolete */ break; case SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING: /* Obsolete */ break; case SVGA3D_DEVCAP_MAX_POINT_SIZE: AssertCompile(sizeof(uint32_t) == sizeof(float)); *(float *)pu32Val = 256.0f; /* VGPU9. Not applicable to DX11. */ break; case SVGA3D_DEVCAP_MAX_SHADER_TEXTURES: /* Obsolete */ break; case SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH: case SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT: if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0) *pu32Val = 16384; else if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = 8192; else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_3) *pu32Val = 4096; else *pu32Val = 2048; break; case SVGA3D_DEVCAP_MAX_VOLUME_EXTENT: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = 2048; else *pu32Val = 256; break; case SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT: if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0) *pu32Val = 16384; else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_3) *pu32Val = 8192; else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_2) *pu32Val = 2048; else *pu32Val = 128; break; case SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO: /* Obsolete */ break; case SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY: if (FeatureLevel >= D3D_FEATURE_LEVEL_9_2) *pu32Val = D3D11_REQ_MAXANISOTROPY; else *pu32Val = 2; // D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; break; case SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = UINT32_MAX; else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_2) *pu32Val = 1048575; // D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; else *pu32Val = 65535; // D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; break; case SVGA3D_DEVCAP_MAX_VERTEX_INDEX: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = UINT32_MAX; else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_2) *pu32Val = 1048575; else *pu32Val = 65534; break; case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = UINT32_MAX; else *pu32Val = 512; break; case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = UINT32_MAX; else *pu32Val = 512; break; case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = 4096; else *pu32Val = 32; break; case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = 4096; else *pu32Val = 32; break; case SVGA3D_DEVCAP_TEXTURE_OPS: /* Obsolete */ break; case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8: case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8: case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10: case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5: case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5: case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4: case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5: case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16: case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8: case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8: case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8: case SVGA3D_DEVCAP_SURFACEFMT_Z_D16: case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8: case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8: case SVGA3D_DEVCAP_SURFACEFMT_DXT1: case SVGA3D_DEVCAP_SURFACEFMT_DXT2: case SVGA3D_DEVCAP_SURFACEFMT_DXT3: case SVGA3D_DEVCAP_SURFACEFMT_DXT4: case SVGA3D_DEVCAP_SURFACEFMT_DXT5: case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8: case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10: case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8: case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8: case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8: case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5: case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8: case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5: case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8: case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5: case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8: case SVGA3D_DEVCAP_SURFACEFMT_V16U16: case SVGA3D_DEVCAP_SURFACEFMT_G16R16: case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16: case SVGA3D_DEVCAP_SURFACEFMT_UYVY: case SVGA3D_DEVCAP_SURFACEFMT_YUY2: case SVGA3D_DEVCAP_SURFACEFMT_NV12: case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */ case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16: case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24: case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: case SVGA3D_DEVCAP_SURFACEFMT_ATI1: case SVGA3D_DEVCAP_SURFACEFMT_ATI2: case SVGA3D_DEVCAP_SURFACEFMT_YV12: { SVGA3dSurfaceFormat const enmFormat = vmsvgaDXDevCapSurfaceFmt2Format(idx3dCaps); rc = vmsvgaDXCheckFormatSupportPreDX(pState, enmFormat, pu32Val); break; } case SVGA3D_DEVCAP_MISSING62: /* Unused */ break; case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES: /* Obsolete */ break; case SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS: if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) *pu32Val = 8; else if (FeatureLevel >= D3D_FEATURE_LEVEL_9_3) *pu32Val = 4; // D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT else *pu32Val = 1; // D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT break; case SVGA3D_DEVCAP_DEAD4: /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */ case SVGA3D_DEVCAP_DEAD5: /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */ *pu32Val = (1 << (2-1)) | (1 << (4-1)) | (1 << (8-1)); /* 2x, 4x, 8x */ break; case SVGA3D_DEVCAP_DEAD7: /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */ /* Obsolete */ break; case SVGA3D_DEVCAP_DEAD6: /* SVGA3D_DEVCAP_SUPERSAMPLE */ /* Obsolete */ break; case SVGA3D_DEVCAP_AUTOGENMIPMAPS: *pu32Val = 1; break; case SVGA3D_DEVCAP_MAX_CONTEXT_IDS: *pu32Val = SVGA3D_MAX_CONTEXT_IDS; break; case SVGA3D_DEVCAP_MAX_SURFACE_IDS: *pu32Val = SVGA3D_MAX_SURFACE_IDS; break; case SVGA3D_DEVCAP_DEAD1: /* Obsolete */ break; case SVGA3D_DEVCAP_DEAD8: /* SVGA3D_DEVCAP_VIDEO_DECODE */ /* Obsolete */ break; case SVGA3D_DEVCAP_DEAD9: /* SVGA3D_DEVCAP_VIDEO_PROCESS */ /* Obsolete */ break; case SVGA3D_DEVCAP_LINE_AA: *pu32Val = 1; break; case SVGA3D_DEVCAP_LINE_STIPPLE: *pu32Val = 0; /* DX11 does not seem to support this directly. */ break; case SVGA3D_DEVCAP_MAX_LINE_WIDTH: AssertCompile(sizeof(uint32_t) == sizeof(float)); *(float *)pu32Val = 1.0f; break; case SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH: AssertCompile(sizeof(uint32_t) == sizeof(float)); *(float *)pu32Val = 1.0f; break; case SVGA3D_DEVCAP_DEAD3: /* Old SVGA3D_DEVCAP_LOGICOPS */ /* Deprecated. */ AssertCompile(SVGA3D_DEVCAP_DEAD3 == 92); /* Newer SVGA headers redefine this. */ break; case SVGA3D_DEVCAP_TS_COLOR_KEY: *pu32Val = 0; /* DX11 does not seem to support this directly. */ break; case SVGA3D_DEVCAP_DEAD2: break; case SVGA3D_DEVCAP_DXCONTEXT: *pu32Val = 1; break; case SVGA3D_DEVCAP_DEAD11: /* SVGA3D_DEVCAP_MAX_TEXTURE_ARRAY_SIZE */ *pu32Val = D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; break; case SVGA3D_DEVCAP_DX_MAX_VERTEXBUFFERS: *pu32Val = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; break; case SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS: *pu32Val = D3D11_COMMONSHADER_CONSTANT_BUFFER_HW_SLOT_COUNT; break; case SVGA3D_DEVCAP_DX_PROVOKING_VERTEX: *pu32Val = 0; /* boolean */ break; case SVGA3D_DEVCAP_DXFMT_X8R8G8B8: case SVGA3D_DEVCAP_DXFMT_A8R8G8B8: case SVGA3D_DEVCAP_DXFMT_R5G6B5: case SVGA3D_DEVCAP_DXFMT_X1R5G5B5: case SVGA3D_DEVCAP_DXFMT_A1R5G5B5: case SVGA3D_DEVCAP_DXFMT_A4R4G4B4: case SVGA3D_DEVCAP_DXFMT_Z_D32: case SVGA3D_DEVCAP_DXFMT_Z_D16: case SVGA3D_DEVCAP_DXFMT_Z_D24S8: case SVGA3D_DEVCAP_DXFMT_Z_D15S1: case SVGA3D_DEVCAP_DXFMT_LUMINANCE8: case SVGA3D_DEVCAP_DXFMT_LUMINANCE4_ALPHA4: case SVGA3D_DEVCAP_DXFMT_LUMINANCE16: case SVGA3D_DEVCAP_DXFMT_LUMINANCE8_ALPHA8: case SVGA3D_DEVCAP_DXFMT_DXT1: case SVGA3D_DEVCAP_DXFMT_DXT2: case SVGA3D_DEVCAP_DXFMT_DXT3: case SVGA3D_DEVCAP_DXFMT_DXT4: case SVGA3D_DEVCAP_DXFMT_DXT5: case SVGA3D_DEVCAP_DXFMT_BUMPU8V8: case SVGA3D_DEVCAP_DXFMT_BUMPL6V5U5: case SVGA3D_DEVCAP_DXFMT_BUMPX8L8V8U8: case SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD1: case SVGA3D_DEVCAP_DXFMT_ARGB_S10E5: case SVGA3D_DEVCAP_DXFMT_ARGB_S23E8: case SVGA3D_DEVCAP_DXFMT_A2R10G10B10: case SVGA3D_DEVCAP_DXFMT_V8U8: case SVGA3D_DEVCAP_DXFMT_Q8W8V8U8: case SVGA3D_DEVCAP_DXFMT_CxV8U8: case SVGA3D_DEVCAP_DXFMT_X8L8V8U8: case SVGA3D_DEVCAP_DXFMT_A2W10V10U10: case SVGA3D_DEVCAP_DXFMT_ALPHA8: case SVGA3D_DEVCAP_DXFMT_R_S10E5: case SVGA3D_DEVCAP_DXFMT_R_S23E8: case SVGA3D_DEVCAP_DXFMT_RG_S10E5: case SVGA3D_DEVCAP_DXFMT_RG_S23E8: case SVGA3D_DEVCAP_DXFMT_BUFFER: case SVGA3D_DEVCAP_DXFMT_Z_D24X8: case SVGA3D_DEVCAP_DXFMT_V16U16: case SVGA3D_DEVCAP_DXFMT_G16R16: case SVGA3D_DEVCAP_DXFMT_A16B16G16R16: case SVGA3D_DEVCAP_DXFMT_UYVY: case SVGA3D_DEVCAP_DXFMT_YUY2: case SVGA3D_DEVCAP_DXFMT_NV12: case SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD2: /* SVGA3D_DEVCAP_DXFMT_AYUV */ case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_UINT: case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_SINT: case SVGA3D_DEVCAP_DXFMT_R32G32B32_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R32G32B32_FLOAT: case SVGA3D_DEVCAP_DXFMT_R32G32B32_UINT: case SVGA3D_DEVCAP_DXFMT_R32G32B32_SINT: case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UINT: case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SNORM: case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SINT: case SVGA3D_DEVCAP_DXFMT_R32G32_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R32G32_UINT: case SVGA3D_DEVCAP_DXFMT_R32G32_SINT: case SVGA3D_DEVCAP_DXFMT_R32G8X24_TYPELESS: case SVGA3D_DEVCAP_DXFMT_D32_FLOAT_S8X24_UINT: case SVGA3D_DEVCAP_DXFMT_R32_FLOAT_X8X24: case SVGA3D_DEVCAP_DXFMT_X32_G8X24_UINT: case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UINT: case SVGA3D_DEVCAP_DXFMT_R11G11B10_FLOAT: case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM: case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM_SRGB: case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UINT: case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SINT: case SVGA3D_DEVCAP_DXFMT_R16G16_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R16G16_UINT: case SVGA3D_DEVCAP_DXFMT_R16G16_SINT: case SVGA3D_DEVCAP_DXFMT_R32_TYPELESS: case SVGA3D_DEVCAP_DXFMT_D32_FLOAT: case SVGA3D_DEVCAP_DXFMT_R32_UINT: case SVGA3D_DEVCAP_DXFMT_R32_SINT: case SVGA3D_DEVCAP_DXFMT_R24G8_TYPELESS: case SVGA3D_DEVCAP_DXFMT_D24_UNORM_S8_UINT: case SVGA3D_DEVCAP_DXFMT_R24_UNORM_X8: case SVGA3D_DEVCAP_DXFMT_X24_G8_UINT: case SVGA3D_DEVCAP_DXFMT_R8G8_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R8G8_UNORM: case SVGA3D_DEVCAP_DXFMT_R8G8_UINT: case SVGA3D_DEVCAP_DXFMT_R8G8_SINT: case SVGA3D_DEVCAP_DXFMT_R16_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R16_UNORM: case SVGA3D_DEVCAP_DXFMT_R16_UINT: case SVGA3D_DEVCAP_DXFMT_R16_SNORM: case SVGA3D_DEVCAP_DXFMT_R16_SINT: case SVGA3D_DEVCAP_DXFMT_R8_TYPELESS: case SVGA3D_DEVCAP_DXFMT_R8_UNORM: case SVGA3D_DEVCAP_DXFMT_R8_UINT: case SVGA3D_DEVCAP_DXFMT_R8_SNORM: case SVGA3D_DEVCAP_DXFMT_R8_SINT: case SVGA3D_DEVCAP_DXFMT_P8: case SVGA3D_DEVCAP_DXFMT_R9G9B9E5_SHAREDEXP: case SVGA3D_DEVCAP_DXFMT_R8G8_B8G8_UNORM: case SVGA3D_DEVCAP_DXFMT_G8R8_G8B8_UNORM: case SVGA3D_DEVCAP_DXFMT_BC1_TYPELESS: case SVGA3D_DEVCAP_DXFMT_BC1_UNORM_SRGB: case SVGA3D_DEVCAP_DXFMT_BC2_TYPELESS: case SVGA3D_DEVCAP_DXFMT_BC2_UNORM_SRGB: case SVGA3D_DEVCAP_DXFMT_BC3_TYPELESS: case SVGA3D_DEVCAP_DXFMT_BC3_UNORM_SRGB: case SVGA3D_DEVCAP_DXFMT_BC4_TYPELESS: case SVGA3D_DEVCAP_DXFMT_ATI1: case SVGA3D_DEVCAP_DXFMT_BC4_SNORM: case SVGA3D_DEVCAP_DXFMT_BC5_TYPELESS: case SVGA3D_DEVCAP_DXFMT_ATI2: case SVGA3D_DEVCAP_DXFMT_BC5_SNORM: case SVGA3D_DEVCAP_DXFMT_R10G10B10_XR_BIAS_A2_UNORM: case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_TYPELESS: case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM_SRGB: case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_TYPELESS: case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM_SRGB: case SVGA3D_DEVCAP_DXFMT_Z_DF16: case SVGA3D_DEVCAP_DXFMT_Z_DF24: case SVGA3D_DEVCAP_DXFMT_Z_D24S8_INT: case SVGA3D_DEVCAP_DXFMT_YV12: case SVGA3D_DEVCAP_DXFMT_R32G32B32A32_FLOAT: case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_FLOAT: case SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UNORM: case SVGA3D_DEVCAP_DXFMT_R32G32_FLOAT: case SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UNORM: case SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SNORM: case SVGA3D_DEVCAP_DXFMT_R16G16_FLOAT: case SVGA3D_DEVCAP_DXFMT_R16G16_UNORM: case SVGA3D_DEVCAP_DXFMT_R16G16_SNORM: case SVGA3D_DEVCAP_DXFMT_R32_FLOAT: case SVGA3D_DEVCAP_DXFMT_R8G8_SNORM: case SVGA3D_DEVCAP_DXFMT_R16_FLOAT: case SVGA3D_DEVCAP_DXFMT_D16_UNORM: case SVGA3D_DEVCAP_DXFMT_A8_UNORM: case SVGA3D_DEVCAP_DXFMT_BC1_UNORM: case SVGA3D_DEVCAP_DXFMT_BC2_UNORM: case SVGA3D_DEVCAP_DXFMT_BC3_UNORM: case SVGA3D_DEVCAP_DXFMT_B5G6R5_UNORM: case SVGA3D_DEVCAP_DXFMT_B5G5R5A1_UNORM: case SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM: case SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM: case SVGA3D_DEVCAP_DXFMT_BC4_UNORM: case SVGA3D_DEVCAP_DXFMT_BC5_UNORM: case SVGA3D_DEVCAP_DXFMT_BC6H_TYPELESS: case SVGA3D_DEVCAP_DXFMT_BC6H_UF16: case SVGA3D_DEVCAP_DXFMT_BC6H_SF16: case SVGA3D_DEVCAP_DXFMT_BC7_TYPELESS: case SVGA3D_DEVCAP_DXFMT_BC7_UNORM: case SVGA3D_DEVCAP_DXFMT_BC7_UNORM_SRGB: { SVGA3dSurfaceFormat const enmFormat = vmsvgaDXDevCapDxfmt2Format(idx3dCaps); rc = vmsvgaDXCheckFormatSupport(pState, enmFormat, pu32Val); break; } case SVGA3D_DEVCAP_SM41: *pu32Val = 1; /* boolean */ break; case SVGA3D_DEVCAP_MULTISAMPLE_2X: *pu32Val = 0; /* boolean */ break; case SVGA3D_DEVCAP_MULTISAMPLE_4X: *pu32Val = 0; /* boolean */ break; case SVGA3D_DEVCAP_MS_FULL_QUALITY: *pu32Val = 0; /* boolean */ break; case SVGA3D_DEVCAP_LOGICOPS: AssertCompile(SVGA3D_DEVCAP_LOGICOPS == 248); *pu32Val = 0; /* boolean */ break; case SVGA3D_DEVCAP_LOGIC_BLENDOPS: *pu32Val = 0; /* boolean */ break; case SVGA3D_DEVCAP_RESERVED_1: break; case SVGA3D_DEVCAP_RESERVED_2: break; case SVGA3D_DEVCAP_SM5: *pu32Val = 1; /* boolean */ break; case SVGA3D_DEVCAP_MULTISAMPLE_8X: *pu32Val = 0; /* boolean */ break; case SVGA3D_DEVCAP_MAX: case SVGA3D_DEVCAP_INVALID: rc = VERR_NOT_SUPPORTED; break; } return rc; } static DECLCALLBACK(int) vmsvga3dBackChangeMode(PVGASTATECC pThisCC) { PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSurfaceCopy(PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src, uint32_t cCopyBoxes, SVGA3dCopyBox *pBox) { RT_NOREF(cCopyBoxes, pBox); LogFunc(("src sid %d -> dst sid %d\n", src.sid, dest.sid)); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); PVMSVGA3DBACKEND pBackend = pState->pBackend; PVMSVGA3DSURFACE pSrcSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, src.sid, &pSrcSurface); AssertRCReturn(rc, rc); PVMSVGA3DSURFACE pDstSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, dest.sid, &pDstSurface); AssertRCReturn(rc, rc); LogFunc(("src%s cid %d -> dst%s cid %d\n", pSrcSurface->pBackendSurface ? "" : " sysmem", pSrcSurface ? pSrcSurface->idAssociatedContext : SVGA_ID_INVALID, pDstSurface->pBackendSurface ? "" : " sysmem", pDstSurface ? pDstSurface->idAssociatedContext : SVGA_ID_INVALID)); //DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); //AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); if (pSrcSurface->pBackendSurface) { if (pDstSurface->pBackendSurface == NULL) { /* Create the target if it can be used as a device context shared resource (render or screen target). */ if (pBackend->fSingleDevice || dxIsSurfaceShareable(pDstSurface)) { rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, NULL, pDstSurface); AssertRCReturn(rc, rc); } } if (pDstSurface->pBackendSurface) { /* Surface -> Surface. */ /* Expect both of them to be shared surfaces created by the backend context. */ Assert(pSrcSurface->idAssociatedContext == DX_CID_BACKEND && pDstSurface->idAssociatedContext == DX_CID_BACKEND); /* Wait for the source surface to finish drawing. */ dxSurfaceWait(pState, pSrcSurface, DX_CID_BACKEND); DXDEVICE *pDXDevice = &pBackend->dxDevice; /* Clip the box. */ PVMSVGA3DMIPMAPLEVEL pSrcMipLevel; rc = vmsvga3dMipmapLevel(pSrcSurface, src.face, src.mipmap, &pSrcMipLevel); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); PVMSVGA3DMIPMAPLEVEL pDstMipLevel; rc = vmsvga3dMipmapLevel(pDstSurface, dest.face, dest.mipmap, &pDstMipLevel); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); SVGA3dCopyBox clipBox = *pBox; vmsvgaR3ClipCopyBox(&pSrcMipLevel->mipmapSize, &pDstMipLevel->mipmapSize, &clipBox); UINT DstSubresource = vmsvga3dCalcSubresource(dest.mipmap, dest.face, pDstSurface->cLevels); UINT DstX = clipBox.x; UINT DstY = clipBox.y; UINT DstZ = clipBox.z; UINT SrcSubresource = vmsvga3dCalcSubresource(src.mipmap, src.face, pSrcSurface->cLevels); D3D11_BOX SrcBox; SrcBox.left = clipBox.srcx; SrcBox.top = clipBox.srcy; SrcBox.front = clipBox.srcz; SrcBox.right = clipBox.srcx + clipBox.w; SrcBox.bottom = clipBox.srcy + clipBox.h; SrcBox.back = clipBox.srcz + clipBox.d; Assert(cCopyBoxes == 1); /** @todo */ ID3D11Resource *pDstResource; ID3D11Resource *pSrcResource; pDstResource = dxResource(pState, pDstSurface, NULL); pSrcResource = dxResource(pState, pSrcSurface, NULL); pDXDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, &SrcBox); pDstSurface->pBackendSurface->cidDrawing = DX_CID_BACKEND; } else { /* Surface -> Memory. */ AssertFailed(); /** @todo implement */ } } else { /* Memory -> Surface. */ AssertFailed(); /** @todo implement */ } return rc; } static DECLCALLBACK(void) vmsvga3dBackUpdateHostScreenViewport(PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport) { RT_NOREF(pThisCC, idScreen, pOldViewport); /** @todo Scroll the screen content without requiring the guest to redraw. */ } static DECLCALLBACK(int) vmsvga3dBackSurfaceUpdateHeapBuffers(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface) { /** @todo */ RT_NOREF(pThisCC, pSurface); return VERR_NOT_IMPLEMENTED; } /* * * VGPU9 callbacks. Not implemented. * */ /** @todo later */ /** * Create a new 3d context * * @returns VBox status code. * @param pThisCC The VGA/VMSVGA state for ring-3. * @param cid Context id */ static DECLCALLBACK(int) vmsvga3dBackContextDefine(PVGASTATECC pThisCC, uint32_t cid) { RT_NOREF(cid); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VERR_NOT_IMPLEMENTED; } /** * Destroy an existing 3d context * * @returns VBox status code. * @param pThisCC The VGA/VMSVGA state for ring-3. * @param cid Context id */ static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid) { RT_NOREF(cid); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetTransform(PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16]) { RT_NOREF(cid, type, matrix); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetZRange(PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange) { RT_NOREF(cid, zRange); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState) { RT_NOREF(cid, cRenderStates, pRenderState); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target) { RT_NOREF(cid, type, target); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState) { RT_NOREF(cid, cTextureStates, pTextureState); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetMaterial(PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial) { RT_NOREF(cid, face, pMaterial); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData) { RT_NOREF(cid, index, pData); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetLightEnabled(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled) { RT_NOREF(cid, index, enabled); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) { RT_NOREF(cid, pRect); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4]) { RT_NOREF(cid, index, plane); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackCommandClear(PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, uint32_t stencil, uint32_t cRects, SVGA3dRect *pRect) { /* From SVGA3D_BeginClear comments: * * Clear is not affected by clipping, depth test, or other * render state which affects the fragment pipeline. * * Therefore this code must ignore the current scissor rect. */ RT_NOREF(cid, clearFlag, color, depth, stencil, cRects, pRect); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDrawPrimitives(PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl, uint32_t numRanges, SVGA3dPrimitiveRange *pRange, uint32_t cVertexDivisor, SVGA3dVertexDivisor *pVertexDivisor) { RT_NOREF(cid, numVertexDecls, pVertexDecl, numRanges, pRange, cVertexDivisor, pVertexDivisor); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect) { RT_NOREF(cid, pRect); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackGenerateMipmaps(PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter) { RT_NOREF(sid, filter); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackShaderDefine(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, uint32_t cbData, uint32_t *pShaderData) { RT_NOREF(cid, shid, type, cbData, pShaderData); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type) { RT_NOREF(cid, shid, type); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackShaderSet(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid) { RT_NOREF(pContext, cid, type, shid); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackShaderSetConst(PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues) { RT_NOREF(cid, reg, type, ctype, cRegisters, pValues); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryCreate(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) { RT_NOREF(pThisCC, pContext); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) { RT_NOREF(pThisCC, pContext); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryBegin(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) { RT_NOREF(pThisCC, pContext); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryEnd(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext) { RT_NOREF(pThisCC, pContext); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryGetData(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t *pu32Pixels) { RT_NOREF(pThisCC, pContext, pu32Pixels); DEBUG_BREAKPOINT_TEST(); return VINF_SUCCESS; } /** * Destroy backend specific surface bits (part of SVGA_3D_CMD_SURFACE_DESTROY). * * @param pThisCC The device context. * @param fClearCOTableEntry Whether to clear the corresponding COTable entry. * @param pSurface The surface being destroyed. */ static DECLCALLBACK(void) vmsvga3dBackSurfaceDestroy(PVGASTATECC pThisCC, bool fClearCOTableEntry, PVMSVGA3DSURFACE pSurface) { RT_NOREF(pThisCC); /* The caller should not use the function for system memory surfaces. */ PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; if (!pBackendSurface) return; pSurface->pBackendSurface = NULL; LogFunc(("sid=%u\n", pSurface->id)); /* If any views have been created for this resource, then also release them. */ DXVIEW *pIter, *pNext; RTListForEachSafe(&pBackendSurface->listView, pIter, pNext, DXVIEW, nodeSurfaceView) { LogFunc(("pIter=%p, pNext=%p\n", pIter, pNext)); /** @todo The common DX code should track the views and clean COTable on a surface destruction. */ if (fClearCOTableEntry) { PVMSVGA3DDXCONTEXT pDXContext; int rc = vmsvga3dDXContextFromCid(pThisCC->svga.p3dState, pIter->cid, &pDXContext); AssertRC(rc); if (RT_SUCCESS(rc)) { switch (pIter->enmViewType) { case VMSVGA3D_VIEWTYPE_RENDERTARGET: { SVGACOTableDXRTViewEntry *pEntry = &pDXContext->cot.paRTView[pIter->viewId]; RT_ZERO(*pEntry); break; } case VMSVGA3D_VIEWTYPE_DEPTHSTENCIL: { SVGACOTableDXDSViewEntry *pEntry = &pDXContext->cot.paDSView[pIter->viewId]; RT_ZERO(*pEntry); break; } case VMSVGA3D_VIEWTYPE_SHADERRESOURCE: { SVGACOTableDXSRViewEntry *pEntry = &pDXContext->cot.paSRView[pIter->viewId]; RT_ZERO(*pEntry); break; } case VMSVGA3D_VIEWTYPE_UNORDEREDACCESS: { SVGACOTableDXUAViewEntry *pEntry = &pDXContext->cot.paUAView[pIter->viewId]; RT_ZERO(*pEntry); break; } default: AssertFailed(); } } } dxViewDestroy(pIter); } if ( pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_1D || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_CUBE || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) { D3D_RELEASE(pBackendSurface->staging.pResource); D3D_RELEASE(pBackendSurface->dynamic.pResource); D3D_RELEASE(pBackendSurface->u.pResource); } else if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_BUFFER) { #ifndef DX_COMMON_STAGING_BUFFER D3D_RELEASE(pBackendSurface->staging.pBuffer); D3D_RELEASE(pBackendSurface->dynamic.pBuffer); #endif D3D_RELEASE(pBackendSurface->u.pBuffer); } else { AssertFailed(); } RTMemFree(pBackendSurface); /* No context has created the surface, because the surface does not exist anymore. */ pSurface->idAssociatedContext = SVGA_ID_INVALID; } static DECLCALLBACK(void) vmsvga3dBackSurfaceInvalidateImage(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface, uint32_t uFace, uint32_t uMipmap) { RT_NOREF(pThisCC, uFace, uMipmap); /* The caller should not use the function for system memory surfaces. */ PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; if (!pBackendSurface) return; LogFunc(("sid=%u\n", pSurface->id)); /* The guest uses this to invalidate a buffer. */ if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_BUFFER) { Assert(uFace == 0 && uMipmap == 0); /* The caller ensures this. */ /** @todo This causes flickering when a buffer is invalidated and re-created right before a draw call. */ //vmsvga3dBackSurfaceDestroy(pThisCC, false, pSurface); } else { /** @todo Delete views that have been created for this mipmap. * For now just delete all views, they will be recte=reated if necessary. */ ASSERT_GUEST_FAILED(); DXVIEW *pIter, *pNext; RTListForEachSafe(&pBackendSurface->listView, pIter, pNext, DXVIEW, nodeSurfaceView) { dxViewDestroy(pIter); } } } /** * Backend worker for implementing SVGA_3D_CMD_SURFACE_STRETCHBLT. * * @returns VBox status code. * @param pThis The VGA device instance. * @param pState The VMSVGA3d state. * @param pDstSurface The destination host surface. * @param uDstFace The destination face (valid). * @param uDstMipmap The destination mipmap level (valid). * @param pDstBox The destination box. * @param pSrcSurface The source host surface. * @param uSrcFace The destination face (valid). * @param uSrcMipmap The source mimap level (valid). * @param pSrcBox The source box. * @param enmMode The strecht blt mode . * @param pContext The VMSVGA3d context (already current for OGL). */ static DECLCALLBACK(int) vmsvga3dBackSurfaceStretchBlt(PVGASTATE pThis, PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pDstSurface, uint32_t uDstFace, uint32_t uDstMipmap, SVGA3dBox const *pDstBox, PVMSVGA3DSURFACE pSrcSurface, uint32_t uSrcFace, uint32_t uSrcMipmap, SVGA3dBox const *pSrcBox, SVGA3dStretchBltMode enmMode, PVMSVGA3DCONTEXT pContext) { RT_NOREF(pThis, pState, pDstSurface, uDstFace, uDstMipmap, pDstBox, pSrcSurface, uSrcFace, uSrcMipmap, pSrcBox, enmMode, pContext); AssertFailed(); return VINF_SUCCESS; } /** * Backend worker for implementing SVGA_3D_CMD_SURFACE_DMA that copies one box. * * @returns Failure status code or @a rc. * @param pThis The shared VGA/VMSVGA instance data. * @param pThisCC The VGA/VMSVGA state for ring-3. * @param pState The VMSVGA3d state. * @param pSurface The host surface. * @param pMipLevel Mipmap level. The caller knows it already. * @param uHostFace The host face (valid). * @param uHostMipmap The host mipmap level (valid). * @param GuestPtr The guest pointer. * @param cbGuestPitch The guest pitch. * @param transfer The transfer direction. * @param pBox The box to copy (clipped, valid, except for guest's srcx, srcy, srcz). * @param pContext The context (for OpenGL). * @param rc The current rc for all boxes. * @param iBox The current box number (for Direct 3D). */ static DECLCALLBACK(int) vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, PVMSVGA3DMIPMAPLEVEL pMipLevel, uint32_t uHostFace, uint32_t uHostMipmap, SVGAGuestPtr GuestPtr, uint32_t cbGuestPitch, SVGA3dTransferType transfer, SVGA3dCopyBox const *pBox, PVMSVGA3DCONTEXT pContext, int rc, int iBox) { RT_NOREF(pState, pMipLevel, pContext, iBox); /* The called should not use the function for system memory surfaces. */ PVMSVGA3DBACKENDSURFACE pBackendSurface = pSurface->pBackendSurface; AssertReturn(pBackendSurface, VERR_INVALID_PARAMETER); if ( pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_1D || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_2D || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_CUBE || pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) { /** @todo This is generic code and should be in DevVGA-SVGA3d.cpp for backends which support Map/Unmap. */ uint32_t const u32GuestBlockX = pBox->srcx / pSurface->cxBlock; uint32_t const u32GuestBlockY = pBox->srcy / pSurface->cyBlock; Assert(u32GuestBlockX * pSurface->cxBlock == pBox->srcx); Assert(u32GuestBlockY * pSurface->cyBlock == pBox->srcy); uint32_t const cBlocksX = (pBox->w + pSurface->cxBlock - 1) / pSurface->cxBlock; uint32_t const cBlocksY = (pBox->h + pSurface->cyBlock - 1) / pSurface->cyBlock; AssertMsgReturn(cBlocksX && cBlocksY && pBox->d, ("Empty box %dx%dx%d\n", pBox->w, pBox->h, pBox->d), VERR_INTERNAL_ERROR); /* vmsvgaR3GmrTransfer verifies uGuestOffset. * srcx(u32GuestBlockX) and srcy(u32GuestBlockY) have been verified in vmsvga3dSurfaceDMA * to not cause 32 bit overflow when multiplied by cbBlock and cbGuestPitch. */ uint64_t uGuestOffset = u32GuestBlockX * pSurface->cbBlock + u32GuestBlockY * cbGuestPitch; AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER); /* 3D texture needs additional processing. */ ASSERT_GUEST_RETURN( pBox->z < D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION && pBox->d <= D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION && pBox->d <= D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION - pBox->z, VERR_INVALID_PARAMETER); ASSERT_GUEST_RETURN( pBox->srcz < D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION && pBox->d <= D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION && pBox->d <= D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION - pBox->srcz, VERR_INVALID_PARAMETER); uGuestOffset += pBox->srcz * pMipLevel->cbSurfacePlane; SVGA3dSurfaceImageId image; image.sid = pSurface->id; image.face = uHostFace; image.mipmap = uHostMipmap; SVGA3dBox box; box.x = pBox->x; box.y = pBox->y; box.z = pBox->z; box.w = pBox->w; box.h = pBox->h; box.d = pBox->d; VMSVGA3D_SURFACE_MAP const enmMap = transfer == SVGA3D_WRITE_HOST_VRAM ? VMSVGA3D_SURFACE_MAP_WRITE : VMSVGA3D_SURFACE_MAP_READ; VMSVGA3D_MAPPED_SURFACE map; rc = vmsvga3dBackSurfaceMap(pThisCC, &image, &box, enmMap, &map); if (RT_SUCCESS(rc)) { #if 0 if (box.w == 250 && box.h == 250 && box.d == 1 && enmMap == VMSVGA3D_SURFACE_MAP_READ) { DEBUG_BREAKPOINT_TEST(); vmsvga3dMapWriteBmpFile(&map, "P"); } #endif /* Prepare parameters for vmsvgaR3GmrTransfer, which needs the host buffer address, size * and offset of the first scanline. */ uint32_t cbLockedBuf = map.cbRowPitch * cBlocksY; if (pBackendSurface->enmResType == VMSVGA3D_RESTYPE_TEXTURE_3D) cbLockedBuf += map.cbDepthPitch * (pBox->d - 1); /// @todo why map does not compute this for 2D textures uint8_t *pu8LockedBuf = (uint8_t *)map.pvData; uint32_t offLockedBuf = 0; for (uint32_t iPlane = 0; iPlane < pBox->d; ++iPlane) { AssertBreak(uGuestOffset < UINT32_MAX); rc = vmsvgaR3GmrTransfer(pThis, pThisCC, transfer, pu8LockedBuf, cbLockedBuf, offLockedBuf, map.cbRowPitch, GuestPtr, (uint32_t)uGuestOffset, cbGuestPitch, cBlocksX * pSurface->cbBlock, cBlocksY); AssertRC(rc); uGuestOffset += pMipLevel->cbSurfacePlane; offLockedBuf += map.cbDepthPitch; } bool const fWritten = (transfer == SVGA3D_WRITE_HOST_VRAM); vmsvga3dBackSurfaceUnmap(pThisCC, &image, &map, fWritten); } } else { AssertMsgFailed(("Unsupported surface type %d\n", pBackendSurface->enmResType)); rc = VERR_NOT_IMPLEMENTED; } return rc; } /** * Create D3D/OpenGL texture object for the specified surface. * * Surfaces are created when needed. * * @param pThisCC The device context. * @param pContext The context. * @param idAssociatedContext Probably the same as pContext->id. * @param pSurface The surface to create the texture for. */ static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext, PVMSVGA3DSURFACE pSurface) { RT_NOREF(pThisCC, pContext, idAssociatedContext, pSurface); AssertFailed(); return VINF_SUCCESS; } /* * DX callbacks. */ static DECLCALLBACK(int) vmsvga3dBackDXDefineContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; /* Allocate a backend specific context structure. */ PVMSVGA3DBACKENDDXCONTEXT pBackendDXContext = (PVMSVGA3DBACKENDDXCONTEXT)RTMemAllocZ(sizeof(VMSVGA3DBACKENDDXCONTEXT)); AssertPtrReturn(pBackendDXContext, VERR_NO_MEMORY); pDXContext->pBackendDXContext = pBackendDXContext; LogFunc(("cid %d\n", pDXContext->cid)); int rc = dxDeviceCreate(pBackend, &pBackendDXContext->dxDevice); return rc; } static DECLCALLBACK(int) vmsvga3dBackDXDestroyContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; LogFunc(("cid %d\n", pDXContext->cid)); if (pDXContext->pBackendDXContext) { /* Clean up context resources. */ VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; for (uint32_t idxShaderState = 0; idxShaderState < RT_ELEMENTS(pBackendDXContext->resources.shaderState); ++idxShaderState) { ID3D11Buffer **papConstantBuffer = &pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers[0]; D3D_RELEASE_ARRAY(RT_ELEMENTS(pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers), papConstantBuffer); } for (uint32_t i = 0; i < RT_ELEMENTS(pBackendDXContext->resources.inputAssembly.vertexBuffers); ++i) { D3D_RELEASE(pBackendDXContext->resources.inputAssembly.vertexBuffers[i].pBuffer); } D3D_RELEASE(pBackendDXContext->resources.inputAssembly.indexBuffer.pBuffer); if (pBackendDXContext->dxDevice.pImmediateContext) dxDeviceFlush(&pBackendDXContext->dxDevice); /* Make sure that any pending draw calls are finished. */ if (pBackendDXContext->paRenderTargetView) { for (uint32_t i = 0; i < pBackendDXContext->cRenderTargetView; ++i) D3D_RELEASE(pBackendDXContext->paRenderTargetView[i].u.pRenderTargetView); } if (pBackendDXContext->paDepthStencilView) { for (uint32_t i = 0; i < pBackendDXContext->cDepthStencilView; ++i) D3D_RELEASE(pBackendDXContext->paDepthStencilView[i].u.pDepthStencilView); } if (pBackendDXContext->paShaderResourceView) { for (uint32_t i = 0; i < pBackendDXContext->cShaderResourceView; ++i) D3D_RELEASE(pBackendDXContext->paShaderResourceView[i].u.pShaderResourceView); } if (pBackendDXContext->paElementLayout) { for (uint32_t i = 0; i < pBackendDXContext->cElementLayout; ++i) D3D_RELEASE(pBackendDXContext->paElementLayout[i].pElementLayout); } if (pBackendDXContext->papBlendState) D3D_RELEASE_ARRAY(pBackendDXContext->cBlendState, pBackendDXContext->papBlendState); if (pBackendDXContext->papDepthStencilState) D3D_RELEASE_ARRAY(pBackendDXContext->cDepthStencilState, pBackendDXContext->papDepthStencilState); if (pBackendDXContext->papRasterizerState) D3D_RELEASE_ARRAY(pBackendDXContext->cRasterizerState, pBackendDXContext->papRasterizerState); if (pBackendDXContext->papSamplerState) D3D_RELEASE_ARRAY(pBackendDXContext->cSamplerState, pBackendDXContext->papSamplerState); if (pBackendDXContext->paQuery) { for (uint32_t i = 0; i < pBackendDXContext->cQuery; ++i) dxDestroyQuery(&pBackendDXContext->paQuery[i]); } if (pBackendDXContext->paShader) { for (uint32_t i = 0; i < pBackendDXContext->cShader; ++i) dxDestroyShader(&pBackendDXContext->paShader[i]); } if (pBackendDXContext->paStreamOutput) { for (uint32_t i = 0; i < pBackendDXContext->cStreamOutput; ++i) dxDestroyStreamOutput(&pBackendDXContext->paStreamOutput[i]); } if (pBackendDXContext->paUnorderedAccessView) { for (uint32_t i = 0; i < pBackendDXContext->cUnorderedAccessView; ++i) D3D_RELEASE(pBackendDXContext->paUnorderedAccessView[i].u.pUnorderedAccessView); } RTMemFreeZ(pBackendDXContext->papBlendState, sizeof(pBackendDXContext->papBlendState[0]) * pBackendDXContext->cBlendState); RTMemFreeZ(pBackendDXContext->papDepthStencilState, sizeof(pBackendDXContext->papDepthStencilState[0]) * pBackendDXContext->cDepthStencilState); RTMemFreeZ(pBackendDXContext->papSamplerState, sizeof(pBackendDXContext->papSamplerState[0]) * pBackendDXContext->cSamplerState); RTMemFreeZ(pBackendDXContext->papRasterizerState, sizeof(pBackendDXContext->papRasterizerState[0]) * pBackendDXContext->cRasterizerState); RTMemFreeZ(pBackendDXContext->paElementLayout, sizeof(pBackendDXContext->paElementLayout[0]) * pBackendDXContext->cElementLayout); RTMemFreeZ(pBackendDXContext->paRenderTargetView, sizeof(pBackendDXContext->paRenderTargetView[0]) * pBackendDXContext->cRenderTargetView); RTMemFreeZ(pBackendDXContext->paDepthStencilView, sizeof(pBackendDXContext->paDepthStencilView[0]) * pBackendDXContext->cDepthStencilView); RTMemFreeZ(pBackendDXContext->paShaderResourceView, sizeof(pBackendDXContext->paShaderResourceView[0]) * pBackendDXContext->cShaderResourceView); RTMemFreeZ(pBackendDXContext->paQuery, sizeof(pBackendDXContext->paQuery[0]) * pBackendDXContext->cQuery); RTMemFreeZ(pBackendDXContext->paShader, sizeof(pBackendDXContext->paShader[0]) * pBackendDXContext->cShader); RTMemFreeZ(pBackendDXContext->paStreamOutput, sizeof(pBackendDXContext->paStreamOutput[0]) * pBackendDXContext->cStreamOutput); RTMemFreeZ(pBackendDXContext->paUnorderedAccessView, sizeof(pBackendDXContext->paUnorderedAccessView[0]) * pBackendDXContext->cUnorderedAccessView); /* Destroy backend surfaces which belong to this context. */ /** @todo The context should have a list of surfaces (and also shared resources). */ /** @todo This should not be needed in fSingleDevice mode. */ for (uint32_t sid = 0; sid < pThisCC->svga.p3dState->cSurfaces; ++sid) { PVMSVGA3DSURFACE const pSurface = pThisCC->svga.p3dState->papSurfaces[sid]; if ( pSurface && pSurface->id == sid) { if (pSurface->idAssociatedContext == pDXContext->cid) { if (pSurface->pBackendSurface) vmsvga3dBackSurfaceDestroy(pThisCC, true, pSurface); } else if (pSurface->idAssociatedContext == DX_CID_BACKEND) { /* May have shared resources in this context. */ if (pSurface->pBackendSurface) { DXSHAREDTEXTURE *pSharedTexture = (DXSHAREDTEXTURE *)RTAvlU32Get(&pSurface->pBackendSurface->SharedTextureTree, pDXContext->cid); if (pSharedTexture) { Assert(pSharedTexture->sid == sid); RTAvlU32Remove(&pSurface->pBackendSurface->SharedTextureTree, pDXContext->cid); D3D_RELEASE(pSharedTexture->pTexture); RTMemFreeZ(pSharedTexture, sizeof(*pSharedTexture)); } } } } } dxDeviceDestroy(pBackend, &pBackendDXContext->dxDevice); RTMemFreeZ(pBackendDXContext, sizeof(*pBackendDXContext)); pDXContext->pBackendDXContext = NULL; } return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXBindContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSwitchContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; if (!pBackend->fSingleDevice) return VINF_NOT_IMPLEMENTED; /* Not required. */ /* The new context state will be applied by the generic DX code. */ RT_NOREF(pDXContext); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXReadbackContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXInvalidateContext(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXSetSingleConstantBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t slot, SVGA3dShaderType type, SVGA3dSurfaceId sid, uint32_t offsetInBytes, uint32_t sizeInBytes) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); if (sid == SVGA_ID_INVALID) { uint32_t const idxShaderState = type - SVGA3D_SHADERTYPE_MIN; D3D_RELEASE(pDXContext->pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers[slot]); return VINF_SUCCESS; } PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); AssertRCReturn(rc, rc); PVMSVGA3DMIPMAPLEVEL pMipLevel; rc = vmsvga3dMipmapLevel(pSurface, 0, 0, &pMipLevel); AssertRCReturn(rc, rc); uint32_t const cbSurface = pMipLevel->cbSurface; ASSERT_GUEST_RETURN( offsetInBytes < cbSurface && sizeInBytes <= cbSurface - offsetInBytes, VERR_INVALID_PARAMETER); /* Constant buffers are created on demand. */ Assert(pSurface->pBackendSurface == NULL); /* Upload the current data, if any. */ D3D11_SUBRESOURCE_DATA *pInitialData = NULL; D3D11_SUBRESOURCE_DATA initialData; if (pMipLevel->pSurfaceData) { initialData.pSysMem = (uint8_t *)pMipLevel->pSurfaceData + offsetInBytes; initialData.SysMemPitch = sizeInBytes; initialData.SysMemSlicePitch = sizeInBytes; pInitialData = &initialData; #ifdef LOG_ENABLED if (LogIs8Enabled()) { float *pValuesF = (float *)initialData.pSysMem; for (unsigned i = 0; i < sizeInBytes / sizeof(float) / 4; ++i) { Log(("ConstantF[%d]: " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR "\n", i, FLOAT_FMT_ARGS(pValuesF[i*4 + 0]), FLOAT_FMT_ARGS(pValuesF[i*4 + 1]), FLOAT_FMT_ARGS(pValuesF[i*4 + 2]), FLOAT_FMT_ARGS(pValuesF[i*4 + 3]))); } } #endif } D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = sizeInBytes; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; bd.StructureByteStride = 0; ID3D11Buffer *pBuffer = 0; HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pBuffer); if (SUCCEEDED(hr)) { uint32_t const idxShaderState = type - SVGA3D_SHADERTYPE_MIN; ID3D11Buffer **ppOldBuffer = &pDXContext->pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers[slot]; LogFunc(("constant buffer: [%u][%u]: sid = %u, %u, %u (%p -> %p)\n", idxShaderState, slot, sid, offsetInBytes, sizeInBytes, *ppOldBuffer, pBuffer)); D3D_RELEASE(*ppOldBuffer); *ppOldBuffer = pBuffer; } return VINF_SUCCESS; } static int dxSetShaderResources(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderType type) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); //DEBUG_BREAKPOINT_TEST(); AssertReturn(type >= SVGA3D_SHADERTYPE_MIN && type < SVGA3D_SHADERTYPE_MAX, VERR_INVALID_PARAMETER); uint32_t const idxShaderState = type - SVGA3D_SHADERTYPE_MIN; uint32_t const *pSRIds = &pDXContext->svgaDXContext.shaderState[idxShaderState].shaderResources[0]; ID3D11ShaderResourceView *papShaderResourceView[SVGA3D_DX_MAX_SRVIEWS]; for (uint32_t i = 0; i < SVGA3D_DX_MAX_SRVIEWS; ++i) { SVGA3dShaderResourceViewId shaderResourceViewId = pSRIds[i]; if (shaderResourceViewId != SVGA3D_INVALID_ID) { ASSERT_GUEST_RETURN(shaderResourceViewId < pDXContext->pBackendDXContext->cShaderResourceView, VERR_INVALID_PARAMETER); DXVIEW *pDXView = &pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId]; Assert(pDXView->u.pShaderResourceView); papShaderResourceView[i] = pDXView->u.pShaderResourceView; } else papShaderResourceView[i] = NULL; } dxShaderResourceViewSet(pDevice, type, 0, SVGA3D_DX_MAX_SRVIEWS, papShaderResourceView); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetShaderResources(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startView, SVGA3dShaderType type, uint32_t cShaderResourceViewId, SVGA3dShaderResourceViewId const *paShaderResourceViewId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(startView, type, cShaderResourceViewId, paShaderResourceViewId); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, SVGA3dShaderType type) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(shaderId, type); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetSamplers(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startSampler, SVGA3dShaderType type, uint32_t cSamplerId, SVGA3dSamplerId const *paSamplerId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); ID3D11SamplerState *papSamplerState[SVGA3D_DX_MAX_SAMPLERS]; for (uint32_t i = 0; i < cSamplerId; ++i) { SVGA3dSamplerId samplerId = paSamplerId[i]; if (samplerId != SVGA3D_INVALID_ID) { ASSERT_GUEST_RETURN(samplerId < pDXContext->pBackendDXContext->cSamplerState, VERR_INVALID_PARAMETER); papSamplerState[i] = pDXContext->pBackendDXContext->papSamplerState[samplerId]; } else papSamplerState[i] = NULL; } dxSamplerSet(pDevice, type, startSampler, cSamplerId, papSamplerState); return VINF_SUCCESS; } static void vboxDXMatchShaderInput(DXSHADER *pDXShader, DXSHADER *pDXShaderPrior) { /* For each input generic attribute of the shader find corresponding entry in the prior shader. */ for (uint32_t i = 0; i < pDXShader->shaderInfo.cInputSignature; ++i) { SVGA3dDXSignatureEntry const *pSignatureEntry = &pDXShader->shaderInfo.aInputSignature[i]; DXShaderAttributeSemantic *pSemantic = &pDXShader->shaderInfo.aInputSemantic[i]; if (pSignatureEntry->semanticName != SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED) continue; int iMatch = -1; for (uint32_t iPrior = 0; iPrior < pDXShaderPrior->shaderInfo.cOutputSignature; ++iPrior) { SVGA3dDXSignatureEntry const *pPriorSignatureEntry = &pDXShaderPrior->shaderInfo.aOutputSignature[iPrior]; if (pPriorSignatureEntry->semanticName != SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED) continue; if (pPriorSignatureEntry->registerIndex == pSignatureEntry->registerIndex) { iMatch = iPrior; if (pPriorSignatureEntry->mask == pSignatureEntry->mask) break; /* Exact match, no need to continue search. */ } } if (iMatch >= 0) { SVGA3dDXSignatureEntry const *pPriorSignatureEntry = &pDXShaderPrior->shaderInfo.aOutputSignature[iMatch]; DXShaderAttributeSemantic const *pPriorSemantic = &pDXShaderPrior->shaderInfo.aOutputSemantic[iMatch]; Assert(pPriorSignatureEntry->registerIndex == pSignatureEntry->registerIndex); Assert((pPriorSignatureEntry->mask & pSignatureEntry->mask) == pSignatureEntry->mask); RT_NOREF(pPriorSignatureEntry); pSemantic->SemanticIndex = pPriorSemantic->SemanticIndex; } } } static void vboxDXMatchShaderSignatures(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, DXSHADER *pDXShader) { SVGA3dShaderId const shaderIdVS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_VS - SVGA3D_SHADERTYPE_MIN].shaderId; SVGA3dShaderId const shaderIdHS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_HS - SVGA3D_SHADERTYPE_MIN].shaderId; SVGA3dShaderId const shaderIdDS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_DS - SVGA3D_SHADERTYPE_MIN].shaderId; SVGA3dShaderId const shaderIdGS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_GS - SVGA3D_SHADERTYPE_MIN].shaderId; SVGA3dShaderId const shaderIdPS = pDXContext->svgaDXContext.shaderState[SVGA3D_SHADERTYPE_PS - SVGA3D_SHADERTYPE_MIN].shaderId; /* Try to fix the input semantic indices. Output is usually not changed. */ switch (pDXShader->enmShaderType) { case SVGA3D_SHADERTYPE_VS: { /* Match input to input layout, which sets generic semantic indices to the source registerIndex (dxCreateInputLayout). */ for (uint32_t i = 0; i < pDXShader->shaderInfo.cInputSignature; ++i) { SVGA3dDXSignatureEntry const *pSignatureEntry = &pDXShader->shaderInfo.aInputSignature[i]; DXShaderAttributeSemantic *pSemantic = &pDXShader->shaderInfo.aInputSemantic[i]; if (pSignatureEntry->semanticName != SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED) continue; pSemantic->SemanticIndex = pSignatureEntry->registerIndex; } break; } case SVGA3D_SHADERTYPE_HS: { /* Input of a HS shader is the output of VS. */ DXSHADER *pDXShaderPrior; if (shaderIdVS != SVGA3D_INVALID_ID) pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdVS]; else pDXShaderPrior = NULL; if (pDXShaderPrior) vboxDXMatchShaderInput(pDXShader, pDXShaderPrior); break; } case SVGA3D_SHADERTYPE_DS: { /* Input of a DS shader is the output of HS. */ DXSHADER *pDXShaderPrior; if (shaderIdHS != SVGA3D_INVALID_ID) pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdHS]; else pDXShaderPrior = NULL; if (pDXShaderPrior) vboxDXMatchShaderInput(pDXShader, pDXShaderPrior); break; } case SVGA3D_SHADERTYPE_GS: { /* Input signature of a GS shader is the output of DS or VS. */ DXSHADER *pDXShaderPrior; if (shaderIdDS != SVGA3D_INVALID_ID) pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdDS]; else if (shaderIdVS != SVGA3D_INVALID_ID) pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdVS]; else pDXShaderPrior = NULL; if (pDXShaderPrior) { /* If GS shader does not have input signature (Windows guest can do that), * then assign the prior shader signature as GS input. */ if (pDXShader->shaderInfo.cInputSignature == 0) { pDXShader->shaderInfo.cInputSignature = pDXShaderPrior->shaderInfo.cOutputSignature; memcpy(pDXShader->shaderInfo.aInputSignature, pDXShaderPrior->shaderInfo.aOutputSignature, pDXShaderPrior->shaderInfo.cOutputSignature * sizeof(SVGA3dDXSignatureEntry)); memcpy(pDXShader->shaderInfo.aInputSemantic, pDXShaderPrior->shaderInfo.aOutputSemantic, pDXShaderPrior->shaderInfo.cOutputSignature * sizeof(DXShaderAttributeSemantic)); } else vboxDXMatchShaderInput(pDXShader, pDXShaderPrior); } /* Output signature of a GS shader is the input of the pixel shader. */ if (shaderIdPS != SVGA3D_INVALID_ID) { /* If GS shader does not have output signature (Windows guest can do that), * then assign the PS shader signature as GS output. */ if (pDXShader->shaderInfo.cOutputSignature == 0) { DXSHADER const *pDXShaderPosterior = &pDXContext->pBackendDXContext->paShader[shaderIdPS]; pDXShader->shaderInfo.cOutputSignature = pDXShaderPosterior->shaderInfo.cInputSignature; memcpy(pDXShader->shaderInfo.aOutputSignature, pDXShaderPosterior->shaderInfo.aInputSignature, pDXShaderPosterior->shaderInfo.cInputSignature * sizeof(SVGA3dDXSignatureEntry)); memcpy(pDXShader->shaderInfo.aOutputSemantic, pDXShaderPosterior->shaderInfo.aInputSemantic, pDXShaderPosterior->shaderInfo.cInputSignature * sizeof(DXShaderAttributeSemantic)); } } SVGA3dStreamOutputId const soid = pDXContext->svgaDXContext.streamOut.soid; if (soid != SVGA3D_INVALID_ID) { ASSERT_GUEST_RETURN_VOID(soid < pDXContext->pBackendDXContext->cStreamOutput); /* Set semantic names and indices for SO declaration entries according to the shader output. */ SVGACOTableDXStreamOutputEntry const *pStreamOutputEntry = &pDXContext->cot.paStreamOutput[soid]; DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; if (pDXStreamOutput->cDeclarationEntry == 0) { int rc = dxDefineStreamOutput(pThisCC, pDXContext, soid, pStreamOutputEntry, pDXShader); AssertRCReturnVoid(rc); #ifdef LOG_ENABLED Log6(("Stream output declaration:\n\n")); Log6(("Stream SemanticName SemanticIndex StartComponent ComponentCount OutputSlot\n")); Log6(("------ -------------- ------------- -------------- -------------- ----------\n")); for (unsigned i = 0; i < pDXStreamOutput->cDeclarationEntry; ++i) { D3D11_SO_DECLARATION_ENTRY *p = &pDXStreamOutput->aDeclarationEntry[i]; Log6(("%d %-14s %d %d %d %d\n", p->Stream, p->SemanticName, p->SemanticIndex, p->StartComponent, p->ComponentCount, p->OutputSlot)); } Log6(("\n")); #endif } } break; } case SVGA3D_SHADERTYPE_PS: { /* Input of a PS shader is the output of GS, DS or VS. */ DXSHADER *pDXShaderPrior; if (shaderIdGS != SVGA3D_INVALID_ID) pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdGS]; else if (shaderIdDS != SVGA3D_INVALID_ID) pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdDS]; else if (shaderIdVS != SVGA3D_INVALID_ID) pDXShaderPrior = &pDXContext->pBackendDXContext->paShader[shaderIdVS]; else pDXShaderPrior = NULL; if (pDXShaderPrior) vboxDXMatchShaderInput(pDXShader, pDXShaderPrior); break; } default: break; } /* Intermediate shaders normally have both input and output signatures. However it is ok if they do not. * Just catch this unusual case in order to see if everything is fine. */ Assert( ( pDXShader->enmShaderType == SVGA3D_SHADERTYPE_VS || pDXShader->enmShaderType == SVGA3D_SHADERTYPE_PS || pDXShader->enmShaderType == SVGA3D_SHADERTYPE_CS) || (pDXShader->shaderInfo.cInputSignature && pDXShader->shaderInfo.cOutputSignature)); } static void vboxDXUpdateVSInputSignature(PVMSVGA3DDXCONTEXT pDXContext, DXSHADER *pDXShader) { SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; if (elementLayoutId != SVGA3D_INVALID_ID) { SVGACOTableDXElementLayoutEntry const *pElementLayout = &pDXContext->cot.paElementLayout[elementLayoutId]; for (uint32_t i = 0; i < RT_MIN(pElementLayout->numDescs, pDXShader->shaderInfo.cInputSignature); ++i) { SVGA3dInputElementDesc const *pElementDesc = &pElementLayout->descs[i]; SVGA3dDXSignatureEntry *pSignatureEntry = &pDXShader->shaderInfo.aInputSignature[i]; pSignatureEntry->componentType = DXShaderComponentTypeFromFormat(pElementDesc->format); } } } static void dxCreateInputLayout(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId, DXSHADER *pDXShader) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturnVoid(pDevice->pDevice); SVGACOTableDXElementLayoutEntry const *pEntry = &pDXContext->cot.paElementLayout[elementLayoutId]; DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; if (pDXElementLayout->cElementDesc == 0) { /* Semantic name is not interpreted by D3D, therefore arbitrary names can be used * if they are consistent between the element layout and shader input signature. * "In general, data passed between pipeline stages is completely generic and is not uniquely * interpreted by the system; arbitrary semantics are allowed ..." * * However D3D runtime insists that "SemanticName string ("POSITIO1") cannot end with a number." * * System-Value semantics ("SV_*") between shaders require proper names of course. * But they are irrelevant for input attributes. */ pDXElementLayout->cElementDesc = pEntry->numDescs; for (uint32_t i = 0; i < pEntry->numDescs; ++i) { D3D11_INPUT_ELEMENT_DESC *pDst = &pDXElementLayout->aElementDesc[i]; SVGA3dInputElementDesc const *pSrc = &pEntry->descs[i]; pDst->SemanticName = "ATTRIB"; pDst->SemanticIndex = pSrc->inputRegister; pDst->Format = vmsvgaDXSurfaceFormat2Dxgi(pSrc->format); Assert(pDst->Format != DXGI_FORMAT_UNKNOWN); pDst->InputSlot = pSrc->inputSlot; pDst->AlignedByteOffset = pSrc->alignedByteOffset; pDst->InputSlotClass = (D3D11_INPUT_CLASSIFICATION)pSrc->inputSlotClass; pDst->InstanceDataStepRate = pSrc->instanceDataStepRate; } } HRESULT hr = pDevice->pDevice->CreateInputLayout(pDXElementLayout->aElementDesc, pDXElementLayout->cElementDesc, pDXShader->pvDXBC, pDXShader->cbDXBC, &pDXElementLayout->pElementLayout); Assert(SUCCEEDED(hr)); RT_NOREF(hr); } static void dxSetConstantBuffers(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { //DEBUG_BREAKPOINT_TEST(); PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; AssertCompile(RT_ELEMENTS(pBackendDXContext->resources.shaderState[0].constantBuffers) == SVGA3D_DX_MAX_CONSTBUFFERS); for (uint32_t idxShaderState = 0; idxShaderState < SVGA3D_NUM_SHADERTYPE; ++idxShaderState) { SVGA3dShaderType const shaderType = (SVGA3dShaderType)(idxShaderState + SVGA3D_SHADERTYPE_MIN); for (uint32_t idxSlot = 0; idxSlot < SVGA3D_DX_MAX_CONSTBUFFERS; ++idxSlot) { ID3D11Buffer **pBufferContext = &pBackendDXContext->resources.shaderState[idxShaderState].constantBuffers[idxSlot]; ID3D11Buffer **pBufferPipeline = &pBackend->resources.shaderState[idxShaderState].constantBuffers[idxSlot]; if (*pBufferContext != *pBufferPipeline) { LogFunc(("constant buffer: [%u][%u]: %p -> %p\n", idxShaderState, idxSlot, *pBufferPipeline, *pBufferContext)); dxConstantBufferSet(pDXDevice, idxSlot, shaderType, *pBufferContext); if (*pBufferContext) (*pBufferContext)->AddRef(); D3D_RELEASE(*pBufferPipeline); *pBufferPipeline = *pBufferContext; } } } } static void dxSetVertexBuffers(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { //DEBUG_BREAKPOINT_TEST(); PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; AssertCompile(RT_ELEMENTS(pBackendDXContext->resources.inputAssembly.vertexBuffers) == SVGA3D_DX_MAX_VERTEXBUFFERS); ID3D11Buffer *paResources[SVGA3D_DX_MAX_VERTEXBUFFERS]; UINT paStride[SVGA3D_DX_MAX_VERTEXBUFFERS]; UINT paOffset[SVGA3D_DX_MAX_VERTEXBUFFERS]; int32_t idxMaxSlot = -1; for (uint32_t i = 0; i < SVGA3D_DX_MAX_VERTEXBUFFERS; ++i) { DXBOUNDVERTEXBUFFER *pBufferContext = &pBackendDXContext->resources.inputAssembly.vertexBuffers[i]; DXBOUNDVERTEXBUFFER *pBufferPipeline = &pBackend->resources.inputAssembly.vertexBuffers[i]; if ( pBufferContext->pBuffer != pBufferPipeline->pBuffer || pBufferContext->stride != pBufferPipeline->stride || pBufferContext->offset != pBufferPipeline->offset) { LogFunc(("vertex buffer: [%u]: sid = %u, %p (stride %d, off %d) -> %p (stride %d, off %d)\n", i, pDXContext->svgaDXContext.inputAssembly.vertexBuffers[i].bufferId, pBufferPipeline->pBuffer, pBufferPipeline->stride, pBufferPipeline->offset, pBufferContext->pBuffer, pBufferContext->stride, pBufferContext->offset)); if (pBufferContext->pBuffer != pBufferPipeline->pBuffer) { if (pBufferContext->pBuffer) pBufferContext->pBuffer->AddRef(); D3D_RELEASE(pBufferPipeline->pBuffer); } *pBufferPipeline = *pBufferContext; idxMaxSlot = i; } #ifdef LOG_ENABLED else if (pBufferContext->pBuffer) { LogFunc(("vertex buffer: [%u]: sid = %u, %p (stride %d, off %d)\n", i, pDXContext->svgaDXContext.inputAssembly.vertexBuffers[i].bufferId, pBufferContext->pBuffer, pBufferContext->stride, pBufferContext->offset)); } #endif paResources[i] = pBufferContext->pBuffer; if (pBufferContext->pBuffer) { paStride[i] = pBufferContext->stride; paOffset[i] = pBufferContext->offset; } else { paStride[i] = 0; paOffset[i] = 0; } } LogFunc(("idxMaxSlot = %d\n", idxMaxSlot)); if (idxMaxSlot >= 0) pDXDevice->pImmediateContext->IASetVertexBuffers(0, idxMaxSlot + 1, paResources, paStride, paOffset); } static void dxSetIndexBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { //DEBUG_BREAKPOINT_TEST(); PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; DXBOUNDINDEXBUFFER *pBufferContext = &pBackendDXContext->resources.inputAssembly.indexBuffer; DXBOUNDINDEXBUFFER *pBufferPipeline = &pBackend->resources.inputAssembly.indexBuffer; if ( pBufferContext->pBuffer != pBufferPipeline->pBuffer || pBufferContext->indexBufferOffset != pBufferPipeline->indexBufferOffset || pBufferContext->indexBufferFormat != pBufferPipeline->indexBufferFormat) { LogFunc(("index_buffer: sid = %u, %p -> %p\n", pDXContext->svgaDXContext.inputAssembly.indexBufferSid, pBufferPipeline->pBuffer, pBufferContext->pBuffer)); if (pBufferContext->pBuffer != pBufferPipeline->pBuffer) { if (pBufferContext->pBuffer) pBufferContext->pBuffer->AddRef(); D3D_RELEASE(pBufferPipeline->pBuffer); } *pBufferPipeline = *pBufferContext; pDXDevice->pImmediateContext->IASetIndexBuffer(pBufferContext->pBuffer, pBufferContext->indexBufferFormat, pBufferContext->indexBufferOffset); } } #ifdef LOG_ENABLED static void dxDbgLogVertexElement(DXGI_FORMAT Format, void const *pvElementData) { switch (Format) { case DXGI_FORMAT_R32G32B32A32_FLOAT: { float const *pValues = (float const *)pvElementData; Log8(("{ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " },", FLOAT_FMT_ARGS(pValues[0]), FLOAT_FMT_ARGS(pValues[1]), FLOAT_FMT_ARGS(pValues[2]), FLOAT_FMT_ARGS(pValues[3]))); break; } case DXGI_FORMAT_R32G32B32_FLOAT: { float const *pValues = (float const *)pvElementData; Log8(("{ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " },", FLOAT_FMT_ARGS(pValues[0]), FLOAT_FMT_ARGS(pValues[1]), FLOAT_FMT_ARGS(pValues[2]))); break; } case DXGI_FORMAT_R32G32_FLOAT: { float const *pValues = (float const *)pvElementData; Log8(("{ " FLOAT_FMT_STR ", " FLOAT_FMT_STR " },", FLOAT_FMT_ARGS(pValues[0]), FLOAT_FMT_ARGS(pValues[1]))); break; } case DXGI_FORMAT_R16G16_FLOAT: { uint16_t const *pValues = (uint16_t const *)pvElementData; Log8(("{ f16 " FLOAT_FMT_STR ", " FLOAT_FMT_STR " },", FLOAT_FMT_ARGS(float16ToFloat(pValues[0])), FLOAT_FMT_ARGS(float16ToFloat(pValues[1])))); break; } case DXGI_FORMAT_R32G32_SINT: { int32_t const *pValues = (int32_t const *)pvElementData; Log8(("{ %d, %d },", pValues[0], pValues[1])); break; } case DXGI_FORMAT_R32G32_UINT: { uint32_t const *pValues = (uint32_t const *)pvElementData; Log8(("{ %u, %u },", pValues[0], pValues[1])); break; } case DXGI_FORMAT_R32_SINT: { int32_t const *pValues = (int32_t const *)pvElementData; Log8(("{ %d },", pValues[0])); break; } case DXGI_FORMAT_R32_UINT: { uint32_t const *pValues = (uint32_t const *)pvElementData; Log8(("{ %u },", pValues[0])); break; } case DXGI_FORMAT_R16G16_SINT: { int16_t const *pValues = (int16_t const *)pvElementData; Log8(("{ s %d, %d },", pValues[0], pValues[1])); break; } case DXGI_FORMAT_R16G16_UINT: { uint16_t const *pValues = (uint16_t const *)pvElementData; Log8(("{ u %u, %u },", pValues[0], pValues[1])); break; } case DXGI_FORMAT_R8G8B8A8_UNORM: { uint8_t const *pValues = (uint8_t const *)pvElementData; Log8(("{ 8unorm %u, %u, %u, %u },", pValues[0], pValues[1], pValues[2], pValues[3])); break; } case DXGI_FORMAT_R8G8_UNORM: { uint8_t const *pValues = (uint8_t const *)pvElementData; Log8(("{ 8unorm %u, %u },", pValues[0], pValues[1])); break; } default: Log8(("{ ??? DXGI_FORMAT %d },", Format)); AssertFailed(); } } static void dxDbgDumpVertexData(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCount, uint32_t startVertexLocation) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; for (uint32_t iSlot = 0; iSlot < SVGA3D_DX_MAX_VERTEXBUFFERS; ++iSlot) { DXBOUNDVERTEXBUFFER *pBufferPipeline = &pBackend->resources.inputAssembly.vertexBuffers[iSlot]; uint32_t const sid = pDXContext->svgaDXContext.inputAssembly.vertexBuffers[iSlot].bufferId; if (sid == SVGA3D_INVALID_ID) { Assert(pBufferPipeline->pBuffer == 0); continue; } Assert(pBufferPipeline->pBuffer); SVGA3dSurfaceImageId image; image.sid = sid; image.face = 0; image.mipmap = 0; VMSVGA3D_MAPPED_SURFACE map; int rc = vmsvga3dBackSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map); AssertRC(rc); if (RT_SUCCESS(rc)) { uint8_t const *pu8VertexData = (uint8_t *)map.pvData; pu8VertexData += pBufferPipeline->offset; pu8VertexData += startVertexLocation * pBufferPipeline->stride; SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; Assert(pDXElementLayout->cElementDesc > 0); Log8(("Vertex buffer dump: sid = %u, vertexCount %u, startVertexLocation %d, offset = %d, stride = %d:\n", sid, vertexCount, startVertexLocation, pBufferPipeline->offset, pBufferPipeline->stride)); for (uint32_t v = 0; v < vertexCount; ++v) { Log8(("slot[%u] v%u { ", iSlot, startVertexLocation + v)); for (uint32_t iElement = 0; iElement < pDXElementLayout->cElementDesc; ++iElement) { D3D11_INPUT_ELEMENT_DESC *pElement = &pDXElementLayout->aElementDesc[iElement]; if (pElement->InputSlot == iSlot) dxDbgLogVertexElement(pElement->Format, pu8VertexData + pElement->AlignedByteOffset); } Log8((" }\n")); if (pBufferPipeline->stride == 0) break; pu8VertexData += pBufferPipeline->stride; } vmsvga3dBackSurfaceUnmap(pThisCC, &image, &map, /* fWritten = */ false); } } } static void dxDbgDumpIndexedVertexData(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCount, uint32_t startIndexLocation, int32_t baseVertexLocation) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); SVGA3dSurfaceImageId image; DXBOUNDINDEXBUFFER *pIB = &pBackend->resources.inputAssembly.indexBuffer; uint32_t const sidIB = pDXContext->svgaDXContext.inputAssembly.indexBufferSid; if (sidIB == SVGA3D_INVALID_ID) { Assert(pIB->pBuffer == 0); return; } Assert(pIB->pBuffer); UINT const BytesPerIndex = pIB->indexBufferFormat == DXGI_FORMAT_R16_UINT ? 2 : 4; void *pvIndexBuffer; uint32_t cbIndexBuffer; int rc = dxReadBuffer(pDXDevice, pIB->pBuffer, pIB->indexBufferOffset + startIndexLocation * BytesPerIndex, indexCount * BytesPerIndex, &pvIndexBuffer, &cbIndexBuffer); AssertRC(rc); if (RT_SUCCESS(rc)) { uint8_t const *pu8IndexData = (uint8_t *)pvIndexBuffer; for (uint32_t iSlot = 0; iSlot < SVGA3D_DX_MAX_VERTEXBUFFERS; ++iSlot) { DXBOUNDVERTEXBUFFER *pVB = &pBackend->resources.inputAssembly.vertexBuffers[iSlot]; uint32_t const sidVB = pDXContext->svgaDXContext.inputAssembly.vertexBuffers[iSlot].bufferId; if (sidVB == SVGA3D_INVALID_ID) { Assert(pVB->pBuffer == 0); continue; } Assert(pVB->pBuffer); image.sid = sidVB; image.face = 0; image.mipmap = 0; VMSVGA3D_MAPPED_SURFACE mapVB; rc = vmsvga3dBackSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &mapVB); AssertRC(rc); if (RT_SUCCESS(rc)) { uint8_t const *pu8VertexData = (uint8_t *)mapVB.pvData; pu8VertexData += pVB->offset; pu8VertexData += baseVertexLocation * pVB->stride; SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; Assert(pDXElementLayout->cElementDesc > 0); Log8(("Vertex buffer dump: sid = %u, indexCount %u, startIndexLocation %d, baseVertexLocation %d, offset = %d, stride = %d:\n", sidVB, indexCount, startIndexLocation, baseVertexLocation, pVB->offset, pVB->stride)); for (uint32_t i = 0; i < indexCount; ++i) { uint32_t Index; if (BytesPerIndex == 2) Index = ((uint16_t *)pu8IndexData)[i]; else Index = ((uint32_t *)pu8IndexData)[i]; Log8(("slot[%u] v%u { ", iSlot, Index)); for (uint32_t iElement = 0; iElement < pDXElementLayout->cElementDesc; ++iElement) { D3D11_INPUT_ELEMENT_DESC *pElement = &pDXElementLayout->aElementDesc[iElement]; if (pElement->InputSlotClass != D3D11_INPUT_PER_VERTEX_DATA) continue; if (pElement->InputSlot == iSlot) { uint8_t const *pu8Vertex = pu8VertexData + Index * pVB->stride; dxDbgLogVertexElement(pElement->Format, pu8Vertex + pElement->AlignedByteOffset); } } Log8((" }\n")); if (pVB->stride == 0) break; } vmsvga3dBackSurfaceUnmap(pThisCC, &image, &mapVB, /* fWritten = */ false); } } RTMemFree(pvIndexBuffer); } } static void dxDbgDumpInstanceData(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t instanceCount, uint32_t startInstanceLocation) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; SVGA3dSurfaceImageId image; /* * Dump per-instance data. */ for (uint32_t iInstance = 0; iInstance < instanceCount; ++iInstance) { for (uint32_t iSlot = 0; iSlot < SVGA3D_DX_MAX_VERTEXBUFFERS; ++iSlot) { DXBOUNDVERTEXBUFFER *pVB = &pBackend->resources.inputAssembly.vertexBuffers[iSlot]; uint32_t const sidVB = pDXContext->svgaDXContext.inputAssembly.vertexBuffers[iSlot].bufferId; if (sidVB == SVGA3D_INVALID_ID) { Assert(pVB->pBuffer == 0); continue; } Assert(pVB->pBuffer); image.sid = sidVB; image.face = 0; image.mipmap = 0; VMSVGA3D_MAPPED_SURFACE mapVB; int rc = vmsvga3dBackSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &mapVB); AssertRC(rc); if (RT_SUCCESS(rc)) { uint8_t const *pu8VertexData = (uint8_t *)mapVB.pvData; pu8VertexData += pVB->offset; pu8VertexData += startInstanceLocation * pVB->stride; SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; Assert(pDXElementLayout->cElementDesc > 0); Log8(("Instance data dump: sid = %u, iInstance %u, startInstanceLocation %d, offset = %d, stride = %d:\n", sidVB, iInstance, startInstanceLocation, pVB->offset, pVB->stride)); Log8(("slot[%u] i%u { ", iSlot, iInstance)); for (uint32_t iElement = 0; iElement < pDXElementLayout->cElementDesc; ++iElement) { D3D11_INPUT_ELEMENT_DESC *pElement = &pDXElementLayout->aElementDesc[iElement]; if (pElement->InputSlotClass != D3D11_INPUT_PER_INSTANCE_DATA) continue; if (pElement->InputSlot == iSlot) { uint8_t const *pu8Vertex = pu8VertexData + iInstance * pVB->stride; dxDbgLogVertexElement(pElement->Format, pu8Vertex + pElement->AlignedByteOffset); } } Log8((" }\n")); vmsvga3dBackSurfaceUnmap(pThisCC, &image, &mapVB, /* fWritten = */ false); } } } } static void dxDbgDumpVertices_Draw(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCount, uint32_t startVertexLocation) { dxDbgDumpVertexData(pThisCC, pDXContext, vertexCount, startVertexLocation); } static void dxDbgDumpVertices_DrawIndexed(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCount, uint32_t startIndexLocation, int32_t baseVertexLocation) { dxDbgDumpIndexedVertexData(pThisCC, pDXContext, indexCount, startIndexLocation, baseVertexLocation); } static void dxDbgDumpVertices_DrawInstanced(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation) { dxDbgDumpVertexData(pThisCC, pDXContext, vertexCountPerInstance, startVertexLocation); dxDbgDumpInstanceData(pThisCC, pDXContext, instanceCount, startInstanceLocation); } static void dxDbgDumpVertices_DrawIndexedInstanced(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndexLocation, int32_t baseVertexLocation, uint32_t startInstanceLocation) { dxDbgDumpIndexedVertexData(pThisCC, pDXContext, indexCountPerInstance, startIndexLocation, baseVertexLocation); dxDbgDumpInstanceData(pThisCC, pDXContext, instanceCount, startInstanceLocation); } #endif static void dxSetupPipeline(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { /* Make sure that any draw operations on shader resource views have finished. */ AssertCompile(RT_ELEMENTS(pDXContext->svgaDXContext.shaderState) == SVGA3D_NUM_SHADERTYPE); AssertCompile(RT_ELEMENTS(pDXContext->svgaDXContext.shaderState[0].shaderResources) == SVGA3D_DX_MAX_SRVIEWS); int rc; /* Unbind render target views because they mught be (re-)used as shader resource views. */ DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); pDXDevice->pImmediateContext->OMSetRenderTargetsAndUnorderedAccessViews(0, NULL, NULL, 0, 0, NULL, NULL); for (unsigned i = 0; i < SVGA3D_DX11_1_MAX_UAVIEWS; ++i) { ID3D11UnorderedAccessView *pNullUA = 0; pDXDevice->pImmediateContext->CSSetUnorderedAccessViews(i, 1, &pNullUA, NULL); } dxSetConstantBuffers(pThisCC, pDXContext); dxSetVertexBuffers(pThisCC, pDXContext); dxSetIndexBuffer(pThisCC, pDXContext); /* * Shader resources */ /* Make sure that the shader resource views exist. */ for (uint32_t idxShaderState = 0; idxShaderState < SVGA3D_NUM_SHADERTYPE; ++idxShaderState) { for (uint32_t idxSR = 0; idxSR < SVGA3D_DX_MAX_SRVIEWS; ++idxSR) { SVGA3dShaderResourceViewId const shaderResourceViewId = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderResources[idxSR]; if (shaderResourceViewId != SVGA3D_INVALID_ID) { ASSERT_GUEST_RETURN_VOID(shaderResourceViewId < pDXContext->pBackendDXContext->cShaderResourceView); SVGACOTableDXSRViewEntry const *pSRViewEntry = dxGetShaderResourceViewEntry(pDXContext, shaderResourceViewId); AssertContinue(pSRViewEntry != NULL); uint32_t const sid = pSRViewEntry->sid; PVMSVGA3DSURFACE pSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); if (RT_FAILURE(rc)) { AssertMsgFailed(("sid = %u, rc = %Rrc\n", sid, rc)); continue; } /* The guest might have invalidated the surface in which case pSurface->pBackendSurface is NULL. */ /** @todo This is not needed for "single DX device" mode. */ if (pSurface->pBackendSurface) { /* Wait for the surface to finish drawing. */ dxSurfaceWait(pThisCC->svga.p3dState, pSurface, pDXContext->cid); } /* If a view has not been created yet, do it now. */ if (!pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId].u.pView) { //DEBUG_BREAKPOINT_TEST(); LogFunc(("Re-creating SRV: sid=%u srvid = %u\n", sid, shaderResourceViewId)); rc = dxDefineShaderResourceView(pThisCC, pDXContext, shaderResourceViewId, pSRViewEntry); AssertContinue(RT_SUCCESS(rc)); } LogFunc(("srv[%d][%d] sid = %u, srvid = %u, format = %s(%d)\n", idxShaderState, idxSR, sid, shaderResourceViewId, vmsvgaLookupEnum((int)pSRViewEntry->format, &g_SVGA3dSurfaceFormat2String), pSRViewEntry->format)); #ifdef DUMP_BITMAPS SVGA3dSurfaceImageId image; image.sid = sid; image.face = 0; image.mipmap = 0; VMSVGA3D_MAPPED_SURFACE map; int rc2 = vmsvga3dSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map); if (RT_SUCCESS(rc2)) { vmsvga3dMapWriteBmpFile(&map, "sr-"); vmsvga3dSurfaceUnmap(pThisCC, &image, &map, /* fWritten = */ false); } else Log(("Map failed %Rrc\n", rc)); #endif } } /* Set shader resources. */ rc = dxSetShaderResources(pThisCC, pDXContext, (SVGA3dShaderType)(idxShaderState + SVGA3D_SHADERTYPE_MIN)); AssertRC(rc); } /* * Compute shader unordered access views */ for (uint32_t idxUA = 0; idxUA < SVGA3D_DX11_1_MAX_UAVIEWS; ++idxUA) { SVGA3dUAViewId const uaViewId = pDXContext->svgaDXContext.csuaViewIds[idxUA]; if (uaViewId != SVGA3D_INVALID_ID) { //DEBUG_BREAKPOINT_TEST(); ASSERT_GUEST_RETURN_VOID(uaViewId < pDXContext->pBackendDXContext->cUnorderedAccessView); SVGACOTableDXUAViewEntry const *pUAViewEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); AssertContinue(pUAViewEntry != NULL); uint32_t const sid = pUAViewEntry->sid; PVMSVGA3DSURFACE pSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); AssertRCReturnVoid(rc); /* The guest might have invalidated the surface in which case pSurface->pBackendSurface is NULL. */ /** @todo This is not needed for "single DX device" mode. */ if (pSurface->pBackendSurface) { /* Wait for the surface to finish drawing. */ dxSurfaceWait(pThisCC->svga.p3dState, pSurface, pDXContext->cid); } /* If a view has not been created yet, do it now. */ if (!pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId].u.pView) { LogFunc(("Re-creating UAV: sid=%u uaid = %u\n", sid, uaViewId)); rc = dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pUAViewEntry); AssertContinue(RT_SUCCESS(rc)); } LogFunc(("csuav[%d] sid = %u, uaid = %u\n", idxUA, sid, uaViewId)); } } /* Set views. */ rc = dxSetCSUnorderedAccessViews(pThisCC, pDXContext); AssertRC(rc); /* * Render targets and unordered access views. */ DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturnVoid(pDevice->pDevice); /* Make sure that the render target views exist. Similar to SRVs. */ if (pDXContext->svgaDXContext.renderState.depthStencilViewId != SVGA3D_INVALID_ID) { uint32_t const viewId = pDXContext->svgaDXContext.renderState.depthStencilViewId; ASSERT_GUEST_RETURN_VOID(viewId < pDXContext->pBackendDXContext->cDepthStencilView); SVGACOTableDXDSViewEntry const *pDSViewEntry = dxGetDepthStencilViewEntry(pDXContext, viewId); AssertReturnVoid(pDSViewEntry != NULL); PVMSVGA3DSURFACE pSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pDSViewEntry->sid, &pSurface); AssertRCReturnVoid(rc); /* If a view has not been created yet, do it now. */ if (!pDXContext->pBackendDXContext->paDepthStencilView[viewId].u.pView) { //DEBUG_BREAKPOINT_TEST(); LogFunc(("Re-creating DSV: sid=%u dsvid = %u\n", pDSViewEntry->sid, viewId)); rc = dxDefineDepthStencilView(pThisCC, pDXContext, viewId, pDSViewEntry); AssertReturnVoid(RT_SUCCESS(rc)); } LogFunc(("dsv sid = %u, dsvid = %u\n", pDSViewEntry->sid, viewId)); } for (uint32_t i = 0; i < SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS; ++i) { if (pDXContext->svgaDXContext.renderState.renderTargetViewIds[i] != SVGA3D_INVALID_ID) { uint32_t const viewId = pDXContext->svgaDXContext.renderState.renderTargetViewIds[i]; ASSERT_GUEST_RETURN_VOID(viewId < pDXContext->pBackendDXContext->cRenderTargetView); SVGACOTableDXRTViewEntry const *pRTViewEntry = dxGetRenderTargetViewEntry(pDXContext, viewId); AssertReturnVoid(pRTViewEntry != NULL); PVMSVGA3DSURFACE pSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pRTViewEntry->sid, &pSurface); AssertRCReturnVoid(rc); /* If a view has not been created yet, do it now. */ if (!pDXContext->pBackendDXContext->paRenderTargetView[viewId].u.pView) { //DEBUG_BREAKPOINT_TEST(); LogFunc(("Re-creating RTV: sid=%u rtvid = %u\n", pRTViewEntry->sid, viewId)); rc = dxDefineRenderTargetView(pThisCC, pDXContext, viewId, pRTViewEntry); AssertReturnVoid(RT_SUCCESS(rc)); } LogFunc(("rtv sid = %u, rtvid = %u, format = %s(%d)\n", pRTViewEntry->sid, viewId, vmsvgaLookupEnum((int)pRTViewEntry->format, &g_SVGA3dSurfaceFormat2String), pRTViewEntry->format)); } } for (uint32_t idxUA = 0; idxUA < SVGA3D_DX11_1_MAX_UAVIEWS; ++idxUA) { SVGA3dUAViewId const uaViewId = pDXContext->svgaDXContext.uaViewIds[idxUA]; if (uaViewId != SVGA3D_INVALID_ID) { //DEBUG_BREAKPOINT_TEST(); ASSERT_GUEST_RETURN_VOID(uaViewId < pDXContext->pBackendDXContext->cUnorderedAccessView); SVGACOTableDXUAViewEntry const *pUAViewEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); AssertContinue(pUAViewEntry != NULL); uint32_t const sid = pUAViewEntry->sid; PVMSVGA3DSURFACE pSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); AssertRCReturnVoid(rc); /* The guest might have invalidated the surface in which case pSurface->pBackendSurface is NULL. */ /** @todo This is not needed for "single DX device" mode. */ if (pSurface->pBackendSurface) { /* Wait for the surface to finish drawing. */ dxSurfaceWait(pThisCC->svga.p3dState, pSurface, pDXContext->cid); } /* If a view has not been created yet, do it now. */ if (!pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId].u.pView) { LogFunc(("Re-creating UAV: sid=%u uaid = %u\n", sid, uaViewId)); rc = dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pUAViewEntry); AssertContinue(RT_SUCCESS(rc)); } LogFunc(("uav[%d] sid = %u, uaid = %u\n", idxUA, sid, uaViewId)); } } /* Set render targets. */ rc = dxSetRenderTargets(pThisCC, pDXContext); AssertRC(rc); /* * Shaders */ for (uint32_t idxShaderState = 0; idxShaderState < SVGA3D_NUM_SHADERTYPE; ++idxShaderState) { DXSHADER *pDXShader; SVGA3dShaderType const shaderType = (SVGA3dShaderType)(idxShaderState + SVGA3D_SHADERTYPE_MIN); SVGA3dShaderId const shaderId = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderId; if (shaderId != SVGA3D_INVALID_ID) { pDXShader = &pDXContext->pBackendDXContext->paShader[shaderId]; if (pDXShader->pShader == NULL) { /* Create a new shader. */ /* Apply resource types to a pixel shader. */ if (shaderType == SVGA3D_SHADERTYPE_PS) /* Others too? */ { VGPU10_RESOURCE_DIMENSION aResourceDimension[SVGA3D_DX_MAX_SRVIEWS]; RT_ZERO(aResourceDimension); VGPU10_RESOURCE_RETURN_TYPE aResourceReturnType[SVGA3D_DX_MAX_SRVIEWS]; RT_ZERO(aResourceReturnType); uint32_t cResources = 0; for (uint32_t idxSR = 0; idxSR < SVGA3D_DX_MAX_SRVIEWS; ++idxSR) { SVGA3dShaderResourceViewId const shaderResourceViewId = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderResources[idxSR]; if (shaderResourceViewId != SVGA3D_INVALID_ID) { SVGACOTableDXSRViewEntry const *pSRViewEntry = dxGetShaderResourceViewEntry(pDXContext, shaderResourceViewId); AssertContinue(pSRViewEntry != NULL); PVMSVGA3DSURFACE pSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pSRViewEntry->sid, &pSurface); AssertRCReturnVoid(rc); aResourceReturnType[idxSR] = DXShaderResourceReturnTypeFromFormat(pSRViewEntry->format); switch (pSRViewEntry->resourceDimension) { case SVGA3D_RESOURCE_BUFFEREX: case SVGA3D_RESOURCE_BUFFER: aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_BUFFER; break; case SVGA3D_RESOURCE_TEXTURE1D: if (pSurface->surfaceDesc.numArrayElements <= 1) aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE1D; else aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE1DARRAY; break; case SVGA3D_RESOURCE_TEXTURE2D: if (pSurface->surfaceDesc.numArrayElements <= 1) aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE2D; else aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE2DARRAY; break; case SVGA3D_RESOURCE_TEXTURE3D: aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE3D; break; case SVGA3D_RESOURCE_TEXTURECUBE: if (pSurface->surfaceDesc.numArrayElements <= 6) aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURECUBE; else aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURECUBEARRAY; break; default: ASSERT_GUEST_FAILED(); aResourceDimension[idxSR] = VGPU10_RESOURCE_DIMENSION_TEXTURE2D; } cResources = idxSR + 1; /* Update componentType of the pixel shader output signature to correspond to the bound resources. */ if (idxSR < pDXShader->shaderInfo.cOutputSignature) { SVGA3dDXSignatureEntry *pSignatureEntry = &pDXShader->shaderInfo.aOutputSignature[idxSR]; pSignatureEntry->componentType = DXShaderComponentTypeFromFormat(pSRViewEntry->format); } } } rc = DXShaderUpdateResources(&pDXShader->shaderInfo, aResourceDimension, aResourceReturnType, cResources); AssertRC(rc); /* Ignore rc because the shader will most likely work anyway. */ } if (shaderType == SVGA3D_SHADERTYPE_VS) { /* Update componentType of the vertex shader input signature to correspond to the input declaration. */ vboxDXUpdateVSInputSignature(pDXContext, pDXShader); } vboxDXMatchShaderSignatures(pThisCC, pDXContext, pDXShader); rc = DXShaderCreateDXBC(&pDXShader->shaderInfo, &pDXShader->pvDXBC, &pDXShader->cbDXBC); if (RT_SUCCESS(rc)) { #ifdef LOG_ENABLED PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; if (pBackend->pfnD3DDisassemble && LogIs6Enabled()) { ID3D10Blob *pBlob = 0; HRESULT hr2 = pBackend->pfnD3DDisassemble(pDXShader->pvDXBC, pDXShader->cbDXBC, 0, NULL, &pBlob); if (SUCCEEDED(hr2) && pBlob && pBlob->GetBufferSize()) Log6(("%s\n", pBlob->GetBufferPointer())); else AssertFailed(); D3D_RELEASE(pBlob); } LogFunc(("Shader: set cid=%u shid=%u type=%d, GuestSignatures %d\n", pDXContext->cid, shaderId, pDXShader->enmShaderType, pDXShader->shaderInfo.fGuestSignatures)); #endif HRESULT hr = dxShaderCreate(pThisCC, pDXContext, pDXShader); if (FAILED(hr)) rc = VERR_INVALID_STATE; } } LogFunc(("Shader: cid=%u shid=%u type=%d, GuestSignatures %d, %Rrc\n", pDXContext->cid, shaderId, pDXShader->enmShaderType, pDXShader->shaderInfo.fGuestSignatures, rc)); } else pDXShader = NULL; if (RT_SUCCESS(rc)) dxShaderSet(pThisCC, pDXContext, shaderType, pDXShader); AssertRC(rc); } /* * InputLayout */ SVGA3dElementLayoutId const elementLayoutId = pDXContext->svgaDXContext.inputAssembly.layoutId; ID3D11InputLayout *pInputLayout = NULL; if (elementLayoutId != SVGA3D_INVALID_ID) { DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; if (!pDXElementLayout->pElementLayout) { uint32_t const idxShaderState = SVGA3D_SHADERTYPE_VS - SVGA3D_SHADERTYPE_MIN; uint32_t const shid = pDXContext->svgaDXContext.shaderState[idxShaderState].shaderId; if (shid < pDXContext->pBackendDXContext->cShader) { DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[shid]; if (pDXShader->pvDXBC) dxCreateInputLayout(pThisCC, pDXContext, elementLayoutId, pDXShader); else LogRelMax(16, ("VMSVGA: DX shader bytecode is not available in DXSetInputLayout: shid = %u\n", shid)); } else LogRelMax(16, ("VMSVGA: DX shader is not set in DXSetInputLayout: shid = 0x%x\n", shid)); } pInputLayout = pDXElementLayout->pElementLayout; LogFunc(("Input layout id %u\n", elementLayoutId)); } pDevice->pImmediateContext->IASetInputLayout(pInputLayout); } static DECLCALLBACK(int) vmsvga3dBackDXDraw(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCount, uint32_t startVertexLocation) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); dxSetupPipeline(pThisCC, pDXContext); #ifdef LOG_ENABLED if (LogIs8Enabled()) dxDbgDumpVertices_Draw(pThisCC, pDXContext, vertexCount, startVertexLocation); #endif if (pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN) pDevice->pImmediateContext->Draw(vertexCount, startVertexLocation); else { /* * Emulate SVGA3D_PRIMITIVE_TRIANGLEFAN using an indexed draw of a triangle list. */ /* Make sure that 16 bit indices are enough. */ if (vertexCount > 65535) { LogRelMax(1, ("VMSVGA: ignore Draw(TRIANGLEFAN, %u)\n", vertexCount)); return VERR_NOT_SUPPORTED; } /* Generate indices. */ UINT const IndexCount = 3 * (vertexCount - 2); /* 3_per_triangle * num_triangles */ UINT const cbAlloc = IndexCount * sizeof(USHORT); USHORT *paIndices = (USHORT *)RTMemAlloc(cbAlloc); AssertReturn(paIndices, VERR_NO_MEMORY); USHORT iVertex = 1; for (UINT i = 0; i < IndexCount; i+= 3) { paIndices[i] = 0; paIndices[i + 1] = iVertex; ++iVertex; paIndices[i + 2] = iVertex; } D3D11_SUBRESOURCE_DATA InitData; InitData.pSysMem = paIndices; InitData.SysMemPitch = cbAlloc; InitData.SysMemSlicePitch = cbAlloc; D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = cbAlloc; bd.Usage = D3D11_USAGE_IMMUTABLE; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; //bd.CPUAccessFlags = 0; //bd.MiscFlags = 0; //bd.StructureByteStride = 0; ID3D11Buffer *pIndexBuffer = 0; HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, &InitData, &pIndexBuffer); Assert(SUCCEEDED(hr));RT_NOREF(hr); /* Save the current index buffer. */ ID3D11Buffer *pSavedIndexBuffer = 0; DXGI_FORMAT SavedFormat = DXGI_FORMAT_UNKNOWN; UINT SavedOffset = 0; pDevice->pImmediateContext->IAGetIndexBuffer(&pSavedIndexBuffer, &SavedFormat, &SavedOffset); /* Set up the device state. */ pDevice->pImmediateContext->IASetIndexBuffer(pIndexBuffer, DXGI_FORMAT_R16_UINT, 0); pDevice->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); UINT const StartIndexLocation = 0; INT const BaseVertexLocation = startVertexLocation; pDevice->pImmediateContext->DrawIndexed(IndexCount, StartIndexLocation, BaseVertexLocation); /* Restore the device state. */ pDevice->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); pDevice->pImmediateContext->IASetIndexBuffer(pSavedIndexBuffer, SavedFormat, SavedOffset); D3D_RELEASE(pSavedIndexBuffer); /* Cleanup. */ D3D_RELEASE(pIndexBuffer); RTMemFree(paIndices); } /* Note which surfaces are being drawn. */ dxTrackRenderTargets(pThisCC, pDXContext); #ifdef DX_FLUSH_AFTER_DRAW dxDeviceFlush(pDevice); #endif return VINF_SUCCESS; } static int dxReadBuffer(DXDEVICE *pDevice, ID3D11Buffer *pBuffer, UINT Offset, UINT Bytes, void **ppvData, uint32_t *pcbData) { D3D11_BUFFER_DESC desc; RT_ZERO(desc); pBuffer->GetDesc(&desc); AssertReturn( Offset < desc.ByteWidth && Bytes <= desc.ByteWidth - Offset, VERR_INVALID_STATE); void *pvData = RTMemAlloc(Bytes); if (!pvData) return VERR_NO_MEMORY; *ppvData = pvData; *pcbData = Bytes; #ifdef DX_COMMON_STAGING_BUFFER int rc = dxStagingBufferRealloc(pDevice, Bytes); if (RT_SUCCESS(rc)) { /* Copy 'Bytes' bytes starting at 'Offset' from the buffer to the start of staging buffer. */ ID3D11Resource *pDstResource = pDevice->pStagingBuffer; UINT DstSubresource = 0; UINT DstX = 0; UINT DstY = 0; UINT DstZ = 0; ID3D11Resource *pSrcResource = pBuffer; UINT SrcSubresource = 0; D3D11_BOX SrcBox; SrcBox.left = Offset; SrcBox.top = 0; SrcBox.front = 0; SrcBox.right = Offset + Bytes; SrcBox.bottom = 1; SrcBox.back = 1; pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, &SrcBox); D3D11_MAPPED_SUBRESOURCE mappedResource; UINT const Subresource = 0; /* Buffers have only one subresource. */ HRESULT hr = pDevice->pImmediateContext->Map(pDevice->pStagingBuffer, Subresource, D3D11_MAP_READ, /* MapFlags = */ 0, &mappedResource); if (SUCCEEDED(hr)) { memcpy(pvData, mappedResource.pData, Bytes); /* Unmap the staging buffer. */ pDevice->pImmediateContext->Unmap(pDevice->pStagingBuffer, Subresource); } else AssertFailedStmt(rc = VERR_NOT_SUPPORTED); } #else uint32_t const cbAlloc = Bytes; D3D11_SUBRESOURCE_DATA *pInitialData = NULL; D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = Bytes; bd.Usage = D3D11_USAGE_STAGING; //bd.BindFlags = 0; /* No bind flags are allowed for staging resources. */ bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; int rc = VINF_SUCCESS; ID3D11Buffer *pStagingBuffer; HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, pInitialData, &pStagingBuffer); if (SUCCEEDED(hr)) { /* Copy from the buffer to the staging buffer. */ ID3D11Resource *pDstResource = pStagingBuffer; UINT DstSubresource = 0; UINT DstX = 0; UINT DstY = 0; UINT DstZ = 0; ID3D11Resource *pSrcResource = pBuffer; UINT SrcSubresource = 0; D3D11_BOX SrcBox; SrcBox.left = Offset; SrcBox.top = 0; SrcBox.front = 0; SrcBox.right = Offset + Bytes; SrcBox.bottom = 1; SrcBox.back = 1; pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, &SrcBox); D3D11_MAPPED_SUBRESOURCE mappedResource; UINT const Subresource = 0; /* Buffers have only one subresource. */ hr = pDevice->pImmediateContext->Map(pStagingBuffer, Subresource, D3D11_MAP_READ, /* MapFlags = */ 0, &mappedResource); if (SUCCEEDED(hr)) { memcpy(pvData, mappedResource.pData, Bytes); /* Unmap the staging buffer. */ pDevice->pImmediateContext->Unmap(pStagingBuffer, Subresource); } else AssertFailedStmt(rc = VERR_NOT_SUPPORTED); D3D_RELEASE(pStagingBuffer); } else { rc = VERR_NO_MEMORY; } #endif if (RT_FAILURE(rc)) { RTMemFree(*ppvData); *ppvData = NULL; *pcbData = 0; } return rc; } static int dxDrawIndexedTriangleFan(DXDEVICE *pDevice, uint32_t IndexCountTF, uint32_t StartIndexLocationTF, int32_t BaseVertexLocationTF) { /* * Emulate an indexed SVGA3D_PRIMITIVE_TRIANGLEFAN using an indexed draw of triangle list. */ /* Make sure that 16 bit indices are enough. */ if (IndexCountTF > 65535) { LogRelMax(1, ("VMSVGA: ignore DrawIndexed(TRIANGLEFAN, %u)\n", IndexCountTF)); return VERR_NOT_SUPPORTED; } /* Save the current index buffer. */ ID3D11Buffer *pSavedIndexBuffer = 0; DXGI_FORMAT SavedFormat = DXGI_FORMAT_UNKNOWN; UINT SavedOffset = 0; pDevice->pImmediateContext->IAGetIndexBuffer(&pSavedIndexBuffer, &SavedFormat, &SavedOffset); AssertReturn( SavedFormat == DXGI_FORMAT_R16_UINT || SavedFormat == DXGI_FORMAT_R32_UINT, VERR_NOT_SUPPORTED); /* How many bytes are used by triangle fan indices. */ UINT const BytesPerIndexTF = SavedFormat == DXGI_FORMAT_R16_UINT ? 2 : 4; UINT const BytesTF = BytesPerIndexTF * IndexCountTF; /* Read the current index buffer content to obtain indices. */ void *pvDataTF; uint32_t cbDataTF; int rc = dxReadBuffer(pDevice, pSavedIndexBuffer, StartIndexLocationTF, BytesTF, &pvDataTF, &cbDataTF); AssertRCReturn(rc, rc); AssertReturnStmt(cbDataTF >= BytesPerIndexTF, RTMemFree(pvDataTF), VERR_INVALID_STATE); /* Generate indices for triangle list. */ UINT const IndexCount = 3 * (IndexCountTF - 2); /* 3_per_triangle * num_triangles */ UINT const cbAlloc = IndexCount * sizeof(USHORT); USHORT *paIndices = (USHORT *)RTMemAlloc(cbAlloc); AssertReturnStmt(paIndices, RTMemFree(pvDataTF), VERR_NO_MEMORY); USHORT iVertex = 1; if (BytesPerIndexTF == 2) { USHORT *paIndicesTF = (USHORT *)pvDataTF; for (UINT i = 0; i < IndexCount; i+= 3) { paIndices[i] = paIndicesTF[0]; AssertBreakStmt(iVertex < IndexCountTF, rc = VERR_INVALID_STATE); paIndices[i + 1] = paIndicesTF[iVertex]; ++iVertex; AssertBreakStmt(iVertex < IndexCountTF, rc = VERR_INVALID_STATE); paIndices[i + 2] = paIndicesTF[iVertex]; } } else { UINT *paIndicesTF = (UINT *)pvDataTF; for (UINT i = 0; i < IndexCount; i+= 3) { paIndices[i] = paIndicesTF[0]; AssertBreakStmt(iVertex < IndexCountTF, rc = VERR_INVALID_STATE); paIndices[i + 1] = paIndicesTF[iVertex]; ++iVertex; AssertBreakStmt(iVertex < IndexCountTF, rc = VERR_INVALID_STATE); paIndices[i + 2] = paIndicesTF[iVertex]; } } D3D11_SUBRESOURCE_DATA InitData; InitData.pSysMem = paIndices; InitData.SysMemPitch = cbAlloc; InitData.SysMemSlicePitch = cbAlloc; D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = cbAlloc; bd.Usage = D3D11_USAGE_IMMUTABLE; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; //bd.CPUAccessFlags = 0; //bd.MiscFlags = 0; //bd.StructureByteStride = 0; ID3D11Buffer *pIndexBuffer = 0; HRESULT hr = pDevice->pDevice->CreateBuffer(&bd, &InitData, &pIndexBuffer); Assert(SUCCEEDED(hr));RT_NOREF(hr); /* Set up the device state. */ pDevice->pImmediateContext->IASetIndexBuffer(pIndexBuffer, DXGI_FORMAT_R16_UINT, 0); pDevice->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); UINT const StartIndexLocation = 0; INT const BaseVertexLocation = BaseVertexLocationTF; pDevice->pImmediateContext->DrawIndexed(IndexCount, StartIndexLocation, BaseVertexLocation); /* Restore the device state. */ pDevice->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); pDevice->pImmediateContext->IASetIndexBuffer(pSavedIndexBuffer, SavedFormat, SavedOffset); D3D_RELEASE(pSavedIndexBuffer); /* Cleanup. */ D3D_RELEASE(pIndexBuffer); RTMemFree(paIndices); RTMemFree(pvDataTF); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDrawIndexed(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCount, uint32_t startIndexLocation, int32_t baseVertexLocation) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); dxSetupPipeline(pThisCC, pDXContext); #ifdef LOG_ENABLED if (LogIs8Enabled()) dxDbgDumpVertices_DrawIndexed(pThisCC, pDXContext, indexCount, startIndexLocation, baseVertexLocation); #endif if (pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN) pDevice->pImmediateContext->DrawIndexed(indexCount, startIndexLocation, baseVertexLocation); else { dxDrawIndexedTriangleFan(pDevice, indexCount, startIndexLocation, baseVertexLocation); } /* Note which surfaces are being drawn. */ dxTrackRenderTargets(pThisCC, pDXContext); #ifdef DX_FLUSH_AFTER_DRAW dxDeviceFlush(pDevice); #endif return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDrawInstanced(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); dxSetupPipeline(pThisCC, pDXContext); #ifdef LOG_ENABLED if (LogIs8Enabled()) dxDbgDumpVertices_DrawInstanced(pThisCC, pDXContext, vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation); #endif Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); pDevice->pImmediateContext->DrawInstanced(vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation); /* Note which surfaces are being drawn. */ dxTrackRenderTargets(pThisCC, pDXContext); #ifdef DX_FLUSH_AFTER_DRAW dxDeviceFlush(pDevice); #endif return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDrawIndexedInstanced(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndexLocation, int32_t baseVertexLocation, uint32_t startInstanceLocation) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); dxSetupPipeline(pThisCC, pDXContext); #ifdef LOG_ENABLED if (LogIs8Enabled()) dxDbgDumpVertices_DrawIndexedInstanced(pThisCC, pDXContext, indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); #endif Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); pDevice->pImmediateContext->DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); /* Note which surfaces are being drawn. */ dxTrackRenderTargets(pThisCC, pDXContext); #ifdef DX_FLUSH_AFTER_DRAW dxDeviceFlush(pDevice); #endif return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDrawAuto(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); dxSetupPipeline(pThisCC, pDXContext); Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); pDevice->pImmediateContext->DrawAuto(); /* Note which surfaces are being drawn. */ dxTrackRenderTargets(pThisCC, pDXContext); #ifdef DX_FLUSH_AFTER_DRAW dxDeviceFlush(pDevice); #endif return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetInputLayout(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(elementLayoutId); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetVertexBuffers(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startBuffer, uint32_t cVertexBuffer, SVGA3dVertexBuffer const *paVertexBuffer) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); for (uint32_t i = 0; i < cVertexBuffer; ++i) { uint32_t const idxVertexBuffer = startBuffer + i; /* Get corresponding resource. Create the buffer if does not yet exist. */ if (paVertexBuffer[i].sid != SVGA_ID_INVALID) { PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, paVertexBuffer[i].sid, &pSurface); AssertRCReturn(rc, rc); if (pSurface->pBackendSurface == NULL) { /* Create the resource and initialize it with the current surface data. */ rc = vmsvga3dBackSurfaceCreateBuffer(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } Assert(pSurface->pBackendSurface->u.pBuffer); DXBOUNDVERTEXBUFFER *pBoundBuffer = &pDXContext->pBackendDXContext->resources.inputAssembly.vertexBuffers[idxVertexBuffer]; if ( pBoundBuffer->pBuffer != pSurface->pBackendSurface->u.pBuffer || pBoundBuffer->stride != paVertexBuffer[i].stride || pBoundBuffer->offset != paVertexBuffer[i].offset) { LogFunc(("vertex buffer: [%u]: sid = %u, offset %u, stride %u (%p -> %p)\n", idxVertexBuffer, paVertexBuffer[i].sid, paVertexBuffer[i].offset, paVertexBuffer[i].stride, pBoundBuffer->pBuffer, pSurface->pBackendSurface->u.pBuffer)); if (pBoundBuffer->pBuffer != pSurface->pBackendSurface->u.pBuffer) { D3D_RELEASE(pBoundBuffer->pBuffer); pBoundBuffer->pBuffer = pSurface->pBackendSurface->u.pBuffer; pBoundBuffer->pBuffer->AddRef(); } pBoundBuffer->stride = paVertexBuffer[i].stride; pBoundBuffer->offset = paVertexBuffer[i].offset; } } else { DXBOUNDVERTEXBUFFER *pBoundBuffer = &pDXContext->pBackendDXContext->resources.inputAssembly.vertexBuffers[idxVertexBuffer]; D3D_RELEASE(pBoundBuffer->pBuffer); pBoundBuffer->stride = 0; pBoundBuffer->offset = 0; } } return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetIndexBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId sid, SVGA3dSurfaceFormat format, uint32_t offset) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /* Get corresponding resource. Create the buffer if does not yet exist. */ if (sid != SVGA_ID_INVALID) { PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); AssertRCReturn(rc, rc); if (pSurface->pBackendSurface == NULL) { /* Create the resource and initialize it with the current surface data. */ rc = vmsvga3dBackSurfaceCreateBuffer(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } DXGI_FORMAT const enmDxgiFormat = vmsvgaDXSurfaceFormat2Dxgi(format); AssertReturn(enmDxgiFormat == DXGI_FORMAT_R16_UINT || enmDxgiFormat == DXGI_FORMAT_R32_UINT, VERR_INVALID_PARAMETER); DXBOUNDINDEXBUFFER *pBoundBuffer = &pDXContext->pBackendDXContext->resources.inputAssembly.indexBuffer; if ( pBoundBuffer->pBuffer != pSurface->pBackendSurface->u.pBuffer || pBoundBuffer->indexBufferOffset != offset || pBoundBuffer->indexBufferFormat != enmDxgiFormat) { LogFunc(("index_buffer: sid = %u, offset %u, (%p -> %p)\n", sid, offset, pBoundBuffer->pBuffer, pSurface->pBackendSurface->u.pBuffer)); if (pBoundBuffer->pBuffer != pSurface->pBackendSurface->u.pBuffer) { D3D_RELEASE(pBoundBuffer->pBuffer); pBoundBuffer->pBuffer = pSurface->pBackendSurface->u.pBuffer; pBoundBuffer->pBuffer->AddRef(); } pBoundBuffer->indexBufferOffset = offset; pBoundBuffer->indexBufferFormat = enmDxgiFormat; } } else { DXBOUNDINDEXBUFFER *pBoundBuffer = &pDXContext->pBackendDXContext->resources.inputAssembly.indexBuffer; D3D_RELEASE(pBoundBuffer->pBuffer); pBoundBuffer->indexBufferOffset = 0; pBoundBuffer->indexBufferFormat = DXGI_FORMAT_UNKNOWN; } return VINF_SUCCESS; } static D3D11_PRIMITIVE_TOPOLOGY dxTopology(SVGA3dPrimitiveType primitiveType) { static D3D11_PRIMITIVE_TOPOLOGY const aD3D11PrimitiveTopology[SVGA3D_PRIMITIVE_MAX] = { D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, D3D11_PRIMITIVE_TOPOLOGY_LINELIST, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, /* SVGA3D_PRIMITIVE_TRIANGLEFAN: No FAN in D3D11. */ D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ, D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST, D3D11_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST, }; return aD3D11PrimitiveTopology[primitiveType]; } static DECLCALLBACK(int) vmsvga3dBackDXSetTopology(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dPrimitiveType topology) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); D3D11_PRIMITIVE_TOPOLOGY const enmTopology = dxTopology(topology); pDevice->pImmediateContext->IASetPrimitiveTopology(enmTopology); return VINF_SUCCESS; } static int dxSetRenderTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); UINT UAVStartSlot = 0; UINT NumUAVs = 0; ID3D11UnorderedAccessView *apUnorderedAccessViews[SVGA3D_DX11_1_MAX_UAVIEWS]; UINT aUAVInitialCounts[SVGA3D_DX11_1_MAX_UAVIEWS]; for (uint32_t idxUA = 0; idxUA < SVGA3D_DX11_1_MAX_UAVIEWS; ++idxUA) { SVGA3dUAViewId const uaViewId = pDXContext->svgaDXContext.uaViewIds[idxUA]; if (uaViewId != SVGA3D_INVALID_ID) { if (NumUAVs == 0) UAVStartSlot = idxUA; NumUAVs = idxUA - UAVStartSlot + 1; apUnorderedAccessViews[idxUA] = pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId].u.pUnorderedAccessView; SVGACOTableDXUAViewEntry const *pEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); aUAVInitialCounts[idxUA] = pEntry->structureCount; } else { apUnorderedAccessViews[idxUA] = NULL; aUAVInitialCounts[idxUA] = (UINT)-1; } } UINT NumRTVs = 0; ID3D11RenderTargetView *apRenderTargetViews[SVGA3D_MAX_RENDER_TARGETS]; RT_ZERO(apRenderTargetViews); for (uint32_t i = 0; i < pDXContext->cRenderTargets; ++i) { SVGA3dRenderTargetViewId const renderTargetViewId = pDXContext->svgaDXContext.renderState.renderTargetViewIds[i]; if (renderTargetViewId != SVGA3D_INVALID_ID) { ASSERT_GUEST_RETURN(renderTargetViewId < pDXContext->pBackendDXContext->cRenderTargetView, VERR_INVALID_PARAMETER); apRenderTargetViews[i] = pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId].u.pRenderTargetView; ++NumRTVs; } } /* RTVs are followed by UAVs. */ Assert(NumUAVs == 0 || NumRTVs <= pDXContext->svgaDXContext.uavSpliceIndex); ID3D11DepthStencilView *pDepthStencilView = NULL; SVGA3dDepthStencilViewId const depthStencilViewId = pDXContext->svgaDXContext.renderState.depthStencilViewId; if (depthStencilViewId != SVGA_ID_INVALID) pDepthStencilView = pDXContext->pBackendDXContext->paDepthStencilView[depthStencilViewId].u.pDepthStencilView; pDevice->pImmediateContext->OMSetRenderTargetsAndUnorderedAccessViews(NumRTVs, apRenderTargetViews, pDepthStencilView, pDXContext->svgaDXContext.uavSpliceIndex, NumUAVs, apUnorderedAccessViews, aUAVInitialCounts); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetRenderTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, uint32_t cRenderTargetViewId, SVGA3dRenderTargetViewId const *paRenderTargetViewId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(depthStencilViewId, cRenderTargetViewId, paRenderTargetViewId); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetBlendState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dBlendStateId blendId, float const blendFactor[4], uint32_t sampleMask) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); if (blendId != SVGA3D_INVALID_ID) { ID3D11BlendState1 *pBlendState = pDXContext->pBackendDXContext->papBlendState[blendId]; pDevice->pImmediateContext->OMSetBlendState(pBlendState, blendFactor, sampleMask); } else pDevice->pImmediateContext->OMSetBlendState(NULL, NULL, 0); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetDepthStencilState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId, uint32_t stencilRef) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); if (depthStencilId != SVGA3D_INVALID_ID) { ID3D11DepthStencilState *pDepthStencilState = pDXContext->pBackendDXContext->papDepthStencilState[depthStencilId]; pDevice->pImmediateContext->OMSetDepthStencilState(pDepthStencilState, stencilRef); } else pDevice->pImmediateContext->OMSetDepthStencilState(NULL, 0); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetRasterizerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(pBackend); if (rasterizerId != SVGA3D_INVALID_ID) { ID3D11RasterizerState1 *pRasterizerState = pDXContext->pBackendDXContext->papRasterizerState[rasterizerId]; pDevice->pImmediateContext->RSSetState(pRasterizerState); } else pDevice->pImmediateContext->RSSetState(NULL); return VINF_SUCCESS; } typedef struct VGPU10QUERYINFO { SVGA3dQueryType svgaQueryType; uint32_t cbDataVMSVGA; D3D11_QUERY dxQueryType; uint32_t cbDataD3D11; } VGPU10QUERYINFO; static VGPU10QUERYINFO const *dxQueryInfo(SVGA3dQueryType type) { static VGPU10QUERYINFO const aQueryInfo[SVGA3D_QUERYTYPE_MAX] = { { SVGA3D_QUERYTYPE_OCCLUSION, sizeof(SVGADXOcclusionQueryResult), D3D11_QUERY_OCCLUSION, sizeof(UINT64) }, { SVGA3D_QUERYTYPE_TIMESTAMP, sizeof(SVGADXTimestampQueryResult), D3D11_QUERY_TIMESTAMP, sizeof(UINT64) }, { SVGA3D_QUERYTYPE_TIMESTAMPDISJOINT, sizeof(SVGADXTimestampDisjointQueryResult), D3D11_QUERY_TIMESTAMP_DISJOINT, sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT) }, { SVGA3D_QUERYTYPE_PIPELINESTATS, sizeof(SVGADXPipelineStatisticsQueryResult), D3D11_QUERY_PIPELINE_STATISTICS, sizeof(D3D11_QUERY_DATA_PIPELINE_STATISTICS) }, { SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE, sizeof(SVGADXOcclusionPredicateQueryResult), D3D11_QUERY_OCCLUSION_PREDICATE, sizeof(BOOL) }, { SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS, sizeof(SVGADXStreamOutStatisticsQueryResult), D3D11_QUERY_SO_STATISTICS, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, { SVGA3D_QUERYTYPE_STREAMOVERFLOWPREDICATE, sizeof(SVGADXStreamOutPredicateQueryResult), D3D11_QUERY_SO_OVERFLOW_PREDICATE, sizeof(BOOL) }, { SVGA3D_QUERYTYPE_OCCLUSION64, sizeof(SVGADXOcclusion64QueryResult), D3D11_QUERY_OCCLUSION, sizeof(UINT64) }, { SVGA3D_QUERYTYPE_SOSTATS_STREAM0, sizeof(SVGADXStreamOutStatisticsQueryResult), D3D11_QUERY_SO_STATISTICS_STREAM0, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, { SVGA3D_QUERYTYPE_SOSTATS_STREAM1, sizeof(SVGADXStreamOutStatisticsQueryResult), D3D11_QUERY_SO_STATISTICS_STREAM1, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, { SVGA3D_QUERYTYPE_SOSTATS_STREAM2, sizeof(SVGADXStreamOutStatisticsQueryResult), D3D11_QUERY_SO_STATISTICS_STREAM2, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, { SVGA3D_QUERYTYPE_SOSTATS_STREAM3, sizeof(SVGADXStreamOutStatisticsQueryResult), D3D11_QUERY_SO_STATISTICS_STREAM3, sizeof(D3D11_QUERY_DATA_SO_STATISTICS) }, { SVGA3D_QUERYTYPE_SOP_STREAM0, sizeof(SVGADXStreamOutPredicateQueryResult), D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0, sizeof(BOOL) }, { SVGA3D_QUERYTYPE_SOP_STREAM1, sizeof(SVGADXStreamOutPredicateQueryResult), D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1, sizeof(BOOL) }, { SVGA3D_QUERYTYPE_SOP_STREAM2, sizeof(SVGADXStreamOutPredicateQueryResult), D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2, sizeof(BOOL) }, { SVGA3D_QUERYTYPE_SOP_STREAM3, sizeof(SVGADXStreamOutPredicateQueryResult), D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3, sizeof(BOOL) }, }; ASSERT_GUEST_RETURN(type < RT_ELEMENTS(aQueryInfo), NULL); return &aQueryInfo[type]; } static int dxDefineQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGACOTableDXQueryEntry const *pEntry) { DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; VGPU10QUERYINFO const *pQueryInfo = dxQueryInfo((SVGA3dQueryType)pEntry->type); if (!pQueryInfo) return VERR_INVALID_PARAMETER; D3D11_QUERY_DESC desc; desc.Query = pQueryInfo->dxQueryType; desc.MiscFlags = 0; if (pEntry->flags & SVGA3D_DXQUERY_FLAG_PREDICATEHINT) desc.MiscFlags |= (UINT)D3D11_QUERY_MISC_PREDICATEHINT; HRESULT hr = pDXDevice->pDevice->CreateQuery(&desc, &pDXQuery->pQuery); AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); return VINF_SUCCESS; } static int dxDestroyQuery(DXQUERY *pDXQuery) { D3D_RELEASE(pDXQuery->pQuery); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDefineQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGACOTableDXQueryEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxDefineQuery(pThisCC, pDXContext, queryId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; dxDestroyQuery(pDXQuery); return VINF_SUCCESS; } /** @todo queryId makes pDXQuery redundant */ static int dxBeginQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, DXQUERY *pDXQuery) { DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); /* Begin is disabled for some queries. */ SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; if (pEntry->type == SVGA3D_QUERYTYPE_TIMESTAMP) return VINF_SUCCESS; pDXDevice->pImmediateContext->Begin(pDXQuery->pQuery); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXBeginQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; int rc = dxBeginQuery(pThisCC, pDXContext, queryId, pDXQuery); return rc; } static int dxGetQueryResult(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGADXQueryResultUnion *pQueryResult, uint32_t *pcbOut) { DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); typedef union _DXQUERYRESULT { UINT64 occlusion; UINT64 timestamp; D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timestampDisjoint; D3D11_QUERY_DATA_PIPELINE_STATISTICS pipelineStatistics; BOOL occlusionPredicate; D3D11_QUERY_DATA_SO_STATISTICS soStatistics; BOOL soOverflowPredicate; } DXQUERYRESULT; DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; VGPU10QUERYINFO const *pQueryInfo = dxQueryInfo((SVGA3dQueryType)pEntry->type); if (!pQueryInfo) return VERR_INVALID_PARAMETER; DXQUERYRESULT dxQueryResult; while (pDXDevice->pImmediateContext->GetData(pDXQuery->pQuery, &dxQueryResult, pQueryInfo->cbDataD3D11, 0) != S_OK) { RTThreadYield(); } /* Copy back the result. */ switch (pEntry->type) { case SVGA3D_QUERYTYPE_OCCLUSION: pQueryResult->occ.samplesRendered = (uint32_t)dxQueryResult.occlusion; break; case SVGA3D_QUERYTYPE_TIMESTAMP: pQueryResult->ts.timestamp = dxQueryResult.timestamp; break; case SVGA3D_QUERYTYPE_TIMESTAMPDISJOINT: pQueryResult->tsDisjoint.realFrequency = dxQueryResult.timestampDisjoint.Frequency; pQueryResult->tsDisjoint.disjoint = dxQueryResult.timestampDisjoint.Disjoint; break; case SVGA3D_QUERYTYPE_PIPELINESTATS: pQueryResult->pipelineStats.inputAssemblyVertices = dxQueryResult.pipelineStatistics.IAVertices; pQueryResult->pipelineStats.inputAssemblyPrimitives = dxQueryResult.pipelineStatistics.IAPrimitives; pQueryResult->pipelineStats.vertexShaderInvocations = dxQueryResult.pipelineStatistics.VSInvocations; pQueryResult->pipelineStats.geometryShaderInvocations = dxQueryResult.pipelineStatistics.GSInvocations; pQueryResult->pipelineStats.geometryShaderPrimitives = dxQueryResult.pipelineStatistics.GSPrimitives; pQueryResult->pipelineStats.clipperInvocations = dxQueryResult.pipelineStatistics.CInvocations; pQueryResult->pipelineStats.clipperPrimitives = dxQueryResult.pipelineStatistics.CPrimitives; pQueryResult->pipelineStats.pixelShaderInvocations = dxQueryResult.pipelineStatistics.PSInvocations; pQueryResult->pipelineStats.hullShaderInvocations = dxQueryResult.pipelineStatistics.HSInvocations; pQueryResult->pipelineStats.domainShaderInvocations = dxQueryResult.pipelineStatistics.DSInvocations; pQueryResult->pipelineStats.computeShaderInvocations = dxQueryResult.pipelineStatistics.CSInvocations; break; case SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE: pQueryResult->occPred.anySamplesRendered = dxQueryResult.occlusionPredicate; break; case SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS: case SVGA3D_QUERYTYPE_SOSTATS_STREAM0: case SVGA3D_QUERYTYPE_SOSTATS_STREAM1: case SVGA3D_QUERYTYPE_SOSTATS_STREAM2: case SVGA3D_QUERYTYPE_SOSTATS_STREAM3: pQueryResult->soStats.numPrimitivesWritten = dxQueryResult.soStatistics.NumPrimitivesWritten; pQueryResult->soStats.numPrimitivesRequired = dxQueryResult.soStatistics.PrimitivesStorageNeeded; break; case SVGA3D_QUERYTYPE_STREAMOVERFLOWPREDICATE: case SVGA3D_QUERYTYPE_SOP_STREAM0: case SVGA3D_QUERYTYPE_SOP_STREAM1: case SVGA3D_QUERYTYPE_SOP_STREAM2: case SVGA3D_QUERYTYPE_SOP_STREAM3: pQueryResult->soPred.overflowed = dxQueryResult.soOverflowPredicate; break; case SVGA3D_QUERYTYPE_OCCLUSION64: pQueryResult->occ64.samplesRendered = dxQueryResult.occlusion; break; } *pcbOut = pQueryInfo->cbDataVMSVGA; return VINF_SUCCESS; } static int dxEndQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGADXQueryResultUnion *pQueryResult, uint32_t *pcbOut) { DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; pDXDevice->pImmediateContext->End(pDXQuery->pQuery); /** @todo Consider issuing QueryEnd and getting data later in FIFO thread loop. */ return dxGetQueryResult(pThisCC, pDXContext, queryId, pQueryResult, pcbOut); } static DECLCALLBACK(int) vmsvga3dBackDXEndQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, SVGADXQueryResultUnion *pQueryResult, uint32_t *pcbOut) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); int rc = dxEndQuery(pThisCC, pDXContext, queryId, pQueryResult, pcbOut); return rc; } static DECLCALLBACK(int) vmsvga3dBackDXSetPredication(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dQueryId queryId, uint32_t predicateValue) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDXDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDXDevice->pDevice, VERR_INVALID_STATE); if (queryId != SVGA3D_INVALID_ID) { DEBUG_BREAKPOINT_TEST(); DXQUERY *pDXQuery = &pDXContext->pBackendDXContext->paQuery[queryId]; SVGACOTableDXQueryEntry *pEntry = &pDXContext->cot.paQuery[queryId]; VGPU10QUERYINFO const *pQueryInfo = dxQueryInfo((SVGA3dQueryType)pEntry->type); if (!pQueryInfo) return VERR_INVALID_PARAMETER; D3D_RELEASE(pDXQuery->pQuery); D3D11_QUERY_DESC desc; desc.Query = pQueryInfo->dxQueryType; desc.MiscFlags = 0; if (pEntry->flags & SVGA3D_DXQUERY_FLAG_PREDICATEHINT) desc.MiscFlags |= (UINT)D3D11_QUERY_MISC_PREDICATEHINT; HRESULT hr = pDXDevice->pDevice->CreatePredicate(&desc, &pDXQuery->pPredicate); AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); pDXDevice->pImmediateContext->SetPredication(pDXQuery->pPredicate, RT_BOOL(predicateValue)); } else pDXDevice->pImmediateContext->SetPredication(NULL, FALSE); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetSOTargets(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t cSOTarget, SVGA3dSoTarget const *paSoTarget) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /* For each paSoTarget[i]: * If the stream outout buffer object does not exist then create it. * If the surface has been updated by the guest then update the buffer object. * Use SOSetTargets to set the buffers. */ ID3D11Buffer *paResource[SVGA3D_DX_MAX_SOTARGETS]; UINT paOffset[SVGA3D_DX_MAX_SOTARGETS]; /* Always re-bind all 4 SO targets. They can be NULL. */ for (uint32_t i = 0; i < SVGA3D_DX_MAX_SOTARGETS; ++i) { /* Get corresponding resource. Create the buffer if does not yet exist. */ if (i < cSOTarget && paSoTarget[i].sid != SVGA_ID_INVALID) { PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, paSoTarget[i].sid, &pSurface); AssertRCReturn(rc, rc); if (pSurface->pBackendSurface == NULL) { /* Create the resource. */ rc = vmsvga3dBackSurfaceCreateSoBuffer(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } /** @todo How paSoTarget[i].sizeInBytes is used? Maybe when the buffer is created? */ paResource[i] = pSurface->pBackendSurface->u.pBuffer; paOffset[i] = paSoTarget[i].offset; } else { paResource[i] = NULL; paOffset[i] = 0; } } pDevice->pImmediateContext->SOSetTargets(SVGA3D_DX_MAX_SOTARGETS, paResource, paOffset); pDXContext->pBackendDXContext->cSOTarget = cSOTarget; return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetViewports(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t cViewport, SVGA3dViewport const *paViewport) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(pBackend); /* D3D11_VIEWPORT is identical to SVGA3dViewport. */ D3D11_VIEWPORT *pViewports = (D3D11_VIEWPORT *)paViewport; pDevice->pImmediateContext->RSSetViewports(cViewport, pViewports); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetScissorRects(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t cRect, SVGASignedRect const *paRect) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /* D3D11_RECT is identical to SVGASignedRect. */ D3D11_RECT *pRects = (D3D11_RECT *)paRect; pDevice->pImmediateContext->RSSetScissorRects(cRect, pRects); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXClearRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGA3dRGBAFloat const *pRGBA) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); DXVIEW *pDXView = &pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId]; if (!pDXView->u.pRenderTargetView) { //DEBUG_BREAKPOINT_TEST(); /* (Re-)create the render target view, because a creation of a view is deferred until a draw or a clear call. */ SVGACOTableDXRTViewEntry const *pEntry = &pDXContext->cot.paRTView[renderTargetViewId]; int rc = dxDefineRenderTargetView(pThisCC, pDXContext, renderTargetViewId, pEntry); AssertRCReturn(rc, rc); } pDevice->pImmediateContext->ClearRenderTargetView(pDXView->u.pRenderTargetView, pRGBA->value); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackVBDXClearRenderTargetViewRegion(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGA3dRGBAFloat const *pColor, uint32_t cRect, SVGASignedRect const *paRect) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); DXVIEW *pDXView = &pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId]; if (!pDXView->u.pRenderTargetView) { /* (Re-)create the render target view, because a creation of a view is deferred until a draw or a clear call. */ SVGACOTableDXRTViewEntry const *pEntry = &pDXContext->cot.paRTView[renderTargetViewId]; int rc = dxDefineRenderTargetView(pThisCC, pDXContext, renderTargetViewId, pEntry); AssertRCReturn(rc, rc); } pDevice->pImmediateContext->ClearView(pDXView->u.pRenderTargetView, pColor->value, (D3D11_RECT *)paRect, cRect); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXClearDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t flags, SVGA3dDepthStencilViewId depthStencilViewId, float depth, uint8_t stencil) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); DXVIEW *pDXView = &pDXContext->pBackendDXContext->paDepthStencilView[depthStencilViewId]; if (!pDXView->u.pDepthStencilView) { //DEBUG_BREAKPOINT_TEST(); /* (Re-)create the depth stencil view, because a creation of a view is deferred until a draw or a clear call. */ SVGACOTableDXDSViewEntry const *pEntry = &pDXContext->cot.paDSView[depthStencilViewId]; int rc = dxDefineDepthStencilView(pThisCC, pDXContext, depthStencilViewId, pEntry); AssertRCReturn(rc, rc); } UINT ClearFlags = 0; if (flags & SVGA3D_CLEAR_DEPTH) ClearFlags |= D3D11_CLEAR_DEPTH; if (flags & SVGA3D_CLEAR_STENCIL) ClearFlags |= D3D11_CLEAR_STENCIL; pDevice->pImmediateContext->ClearDepthStencilView(pDXView->u.pDepthStencilView, ClearFlags, depth, stencil); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXPredCopyRegion(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId dstSid, uint32_t dstSubResource, SVGA3dSurfaceId srcSid, uint32_t srcSubResource, SVGA3dCopyBox const *pBox) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); PVMSVGA3DSURFACE pSrcSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, srcSid, &pSrcSurface); AssertRCReturn(rc, rc); PVMSVGA3DSURFACE pDstSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, dstSid, &pDstSurface); AssertRCReturn(rc, rc); if (pSrcSurface->pBackendSurface == NULL) { /* Create the resource. */ if (pSrcSurface->format != SVGA3D_BUFFER) rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSrcSurface); else rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSrcSurface); AssertRCReturn(rc, rc); } if (pDstSurface->pBackendSurface == NULL) { /* Create the resource. */ if (pSrcSurface->format != SVGA3D_BUFFER) rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pDstSurface); else rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pDstSurface); AssertRCReturn(rc, rc); } LogFunc(("cid %d: src cid %d%s -> dst cid %d%s\n", pDXContext->cid, pSrcSurface->idAssociatedContext, (pSrcSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "", pDstSurface->idAssociatedContext, (pDstSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "")); /* Clip the box. */ /** @todo Use [src|dst]SubResource to index p[Src|Dst]Surface->paMipmapLevels array directly. */ uint32_t iSrcFace; uint32_t iSrcMipmap; vmsvga3dCalcMipmapAndFace(pSrcSurface->cLevels, srcSubResource, &iSrcMipmap, &iSrcFace); uint32_t iDstFace; uint32_t iDstMipmap; vmsvga3dCalcMipmapAndFace(pDstSurface->cLevels, dstSubResource, &iDstMipmap, &iDstFace); PVMSVGA3DMIPMAPLEVEL pSrcMipLevel; rc = vmsvga3dMipmapLevel(pSrcSurface, iSrcFace, iSrcMipmap, &pSrcMipLevel); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); PVMSVGA3DMIPMAPLEVEL pDstMipLevel; rc = vmsvga3dMipmapLevel(pDstSurface, iDstFace, iDstMipmap, &pDstMipLevel); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); SVGA3dCopyBox clipBox = *pBox; vmsvgaR3ClipCopyBox(&pSrcMipLevel->mipmapSize, &pDstMipLevel->mipmapSize, &clipBox); UINT DstSubresource = dstSubResource; UINT DstX = clipBox.x; UINT DstY = clipBox.y; UINT DstZ = clipBox.z; UINT SrcSubresource = srcSubResource; D3D11_BOX SrcBox; SrcBox.left = clipBox.srcx; SrcBox.top = clipBox.srcy; SrcBox.front = clipBox.srcz; SrcBox.right = clipBox.srcx + clipBox.w; SrcBox.bottom = clipBox.srcy + clipBox.h; SrcBox.back = clipBox.srcz + clipBox.d; ID3D11Resource *pDstResource; ID3D11Resource *pSrcResource; pDstResource = dxResource(pThisCC->svga.p3dState, pDstSurface, pDXContext); pSrcResource = dxResource(pThisCC->svga.p3dState, pSrcSurface, pDXContext); pDevice->pImmediateContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, &SrcBox); #ifdef DUMP_BITMAPS SVGA3dSurfaceImageId image; image.sid = pDstSurface->id; image.face = 0; image.mipmap = 0; VMSVGA3D_MAPPED_SURFACE map; int rc2 = vmsvga3dSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map); if (RT_SUCCESS(rc2)) { vmsvga3dMapWriteBmpFile(&map, "copyregion-"); vmsvga3dSurfaceUnmap(pThisCC, &image, &map, /* fWritten = */ false); } else Log(("Map failed %Rrc\n", rc)); #endif pDstSurface->pBackendSurface->cidDrawing = pDXContext->cid; return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXPredCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId dstSid, SVGA3dSurfaceId srcSid) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); PVMSVGA3DSURFACE pSrcSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, srcSid, &pSrcSurface); AssertRCReturn(rc, rc); PVMSVGA3DSURFACE pDstSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, dstSid, &pDstSurface); AssertRCReturn(rc, rc); if (pSrcSurface->pBackendSurface == NULL) { /* Create the resource. */ if (pSrcSurface->format != SVGA3D_BUFFER) rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSrcSurface); else rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSrcSurface); AssertRCReturn(rc, rc); } if (pDstSurface->pBackendSurface == NULL) { /* Create the resource. */ if (pSrcSurface->format != SVGA3D_BUFFER) rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pDstSurface); else rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pDstSurface); AssertRCReturn(rc, rc); } LogFunc(("cid %d: src cid %d%s -> dst cid %d%s\n", pDXContext->cid, pSrcSurface->idAssociatedContext, (pSrcSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "", pDstSurface->idAssociatedContext, (pDstSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "")); ID3D11Resource *pDstResource = dxResource(pThisCC->svga.p3dState, pDstSurface, pDXContext); ID3D11Resource *pSrcResource = dxResource(pThisCC->svga.p3dState, pSrcSurface, pDXContext); pDevice->pImmediateContext->CopyResource(pDstResource, pSrcResource); pDstSurface->pBackendSurface->cidDrawing = pDXContext->cid; return VINF_SUCCESS; } #include "shaders/d3d11blitter.hlsl.vs.h" #include "shaders/d3d11blitter.hlsl.ps.h" #define HTEST(stmt) \ hr = stmt; \ AssertReturn(SUCCEEDED(hr), hr) static void BlitRelease(D3D11BLITTER *pBlitter) { D3D_RELEASE(pBlitter->pVertexShader); D3D_RELEASE(pBlitter->pPixelShader); D3D_RELEASE(pBlitter->pSamplerState); D3D_RELEASE(pBlitter->pRasterizerState); D3D_RELEASE(pBlitter->pBlendState); RT_ZERO(*pBlitter); } static HRESULT BlitInit(D3D11BLITTER *pBlitter, ID3D11Device1 *pDevice, ID3D11DeviceContext1 *pImmediateContext) { HRESULT hr; RT_ZERO(*pBlitter); pBlitter->pDevice = pDevice; pBlitter->pImmediateContext = pImmediateContext; HTEST(pBlitter->pDevice->CreateVertexShader(g_vs_blitter, sizeof(g_vs_blitter), NULL, &pBlitter->pVertexShader)); HTEST(pBlitter->pDevice->CreatePixelShader(g_ps_blitter, sizeof(g_ps_blitter), NULL, &pBlitter->pPixelShader)); D3D11_SAMPLER_DESC SamplerDesc; SamplerDesc.Filter = D3D11_FILTER_ANISOTROPIC; SamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; SamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; SamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; SamplerDesc.MipLODBias = 0.0f; SamplerDesc.MaxAnisotropy = 4; SamplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; SamplerDesc.BorderColor[0] = 0.0f; SamplerDesc.BorderColor[1] = 0.0f; SamplerDesc.BorderColor[2] = 0.0f; SamplerDesc.BorderColor[3] = 0.0f; SamplerDesc.MinLOD = 0.0f; SamplerDesc.MaxLOD = 0.0f; HTEST(pBlitter->pDevice->CreateSamplerState(&SamplerDesc, &pBlitter->pSamplerState)); D3D11_RASTERIZER_DESC1 RasterizerDesc; RasterizerDesc.FillMode = D3D11_FILL_SOLID; RasterizerDesc.CullMode = D3D11_CULL_NONE; RasterizerDesc.FrontCounterClockwise = FALSE; RasterizerDesc.DepthBias = 0; RasterizerDesc.DepthBiasClamp = 0.0f; RasterizerDesc.SlopeScaledDepthBias = 0.0f; RasterizerDesc.DepthClipEnable = FALSE; RasterizerDesc.ScissorEnable = FALSE; RasterizerDesc.MultisampleEnable = FALSE; RasterizerDesc.AntialiasedLineEnable = FALSE; RasterizerDesc.ForcedSampleCount = 0; HTEST(pBlitter->pDevice->CreateRasterizerState1(&RasterizerDesc, &pBlitter->pRasterizerState)); D3D11_BLEND_DESC1 BlendDesc; BlendDesc.AlphaToCoverageEnable = FALSE; BlendDesc.IndependentBlendEnable = FALSE; for (unsigned i = 0; i < RT_ELEMENTS(BlendDesc.RenderTarget); ++i) { BlendDesc.RenderTarget[i].BlendEnable = FALSE; BlendDesc.RenderTarget[i].LogicOpEnable = FALSE; BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_SRC_COLOR; BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO; BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD; BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO; BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD; BlendDesc.RenderTarget[i].LogicOp = D3D11_LOGIC_OP_CLEAR; BlendDesc.RenderTarget[i].RenderTargetWriteMask = 0xF; } HTEST(pBlitter->pDevice->CreateBlendState1(&BlendDesc, &pBlitter->pBlendState)); return S_OK; } static HRESULT BlitFromTexture(D3D11BLITTER *pBlitter, ID3D11RenderTargetView *pDstRenderTargetView, float cDstWidth, float cDstHeight, D3D11_RECT const &rectDst, ID3D11ShaderResourceView *pSrcShaderResourceView) { HRESULT hr; /* * Save pipeline state. */ struct { D3D11_PRIMITIVE_TOPOLOGY Topology; ID3D11InputLayout *pInputLayout; ID3D11Buffer *pConstantBuffer; ID3D11VertexShader *pVertexShader; ID3D11HullShader *pHullShader; ID3D11DomainShader *pDomainShader; ID3D11GeometryShader *pGeometryShader; ID3D11ShaderResourceView *pShaderResourceView; ID3D11PixelShader *pPixelShader; ID3D11SamplerState *pSamplerState; ID3D11RasterizerState *pRasterizerState; ID3D11BlendState *pBlendState; FLOAT BlendFactor[4]; UINT SampleMask; ID3D11RenderTargetView *apRenderTargetView[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; ID3D11DepthStencilView *pDepthStencilView; UINT NumViewports; D3D11_VIEWPORT aViewport[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; } SavedState; pBlitter->pImmediateContext->IAGetPrimitiveTopology(&SavedState.Topology); pBlitter->pImmediateContext->IAGetInputLayout(&SavedState.pInputLayout); pBlitter->pImmediateContext->VSGetConstantBuffers(0, 1, &SavedState.pConstantBuffer); pBlitter->pImmediateContext->VSGetShader(&SavedState.pVertexShader, NULL, NULL); pBlitter->pImmediateContext->HSGetShader(&SavedState.pHullShader, NULL, NULL); pBlitter->pImmediateContext->DSGetShader(&SavedState.pDomainShader, NULL, NULL); pBlitter->pImmediateContext->GSGetShader(&SavedState.pGeometryShader, NULL, NULL); pBlitter->pImmediateContext->PSGetShaderResources(0, 1, &SavedState.pShaderResourceView); pBlitter->pImmediateContext->PSGetShader(&SavedState.pPixelShader, NULL, NULL); pBlitter->pImmediateContext->PSGetSamplers(0, 1, &SavedState.pSamplerState); pBlitter->pImmediateContext->RSGetState(&SavedState.pRasterizerState); pBlitter->pImmediateContext->OMGetBlendState(&SavedState.pBlendState, SavedState.BlendFactor, &SavedState.SampleMask); pBlitter->pImmediateContext->OMGetRenderTargets(RT_ELEMENTS(SavedState.apRenderTargetView), SavedState.apRenderTargetView, &SavedState.pDepthStencilView); SavedState.NumViewports = RT_ELEMENTS(SavedState.aViewport); pBlitter->pImmediateContext->RSGetViewports(&SavedState.NumViewports, &SavedState.aViewport[0]); /* * Setup pipeline for the blitter. */ /* Render target is first. * If the source texture is bound as a render target, then this call will unbind it * and allow to use it as the shader resource. */ pBlitter->pImmediateContext->OMSetRenderTargets(1, &pDstRenderTargetView, NULL); /* Input assembler. */ pBlitter->pImmediateContext->IASetInputLayout(NULL); pBlitter->pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); /* Constant buffer. */ struct { float scaleX; float scaleY; float offsetX; float offsetY; } VSConstantBuffer; VSConstantBuffer.scaleX = (float)(rectDst.right - rectDst.left) / cDstWidth; VSConstantBuffer.scaleY = (float)(rectDst.bottom - rectDst.top) / cDstHeight; VSConstantBuffer.offsetX = (float)(rectDst.right + rectDst.left) / cDstWidth - 1.0f; VSConstantBuffer.offsetY = -((float)(rectDst.bottom + rectDst.top) / cDstHeight - 1.0f); D3D11_SUBRESOURCE_DATA initialData; initialData.pSysMem = &VSConstantBuffer; initialData.SysMemPitch = sizeof(VSConstantBuffer); initialData.SysMemSlicePitch = sizeof(VSConstantBuffer); D3D11_BUFFER_DESC bd; RT_ZERO(bd); bd.ByteWidth = sizeof(VSConstantBuffer); bd.Usage = D3D11_USAGE_IMMUTABLE; bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; ID3D11Buffer *pConstantBuffer; HTEST(pBlitter->pDevice->CreateBuffer(&bd, &initialData, &pConstantBuffer)); pBlitter->pImmediateContext->VSSetConstantBuffers(0, 1, &pConstantBuffer); D3D_RELEASE(pConstantBuffer); /* xSSetConstantBuffers "will hold a reference to the interfaces passed in." */ /* Vertex shader. */ pBlitter->pImmediateContext->VSSetShader(pBlitter->pVertexShader, NULL, 0); /* Unused shaders. */ pBlitter->pImmediateContext->HSSetShader(NULL, NULL, 0); pBlitter->pImmediateContext->DSSetShader(NULL, NULL, 0); pBlitter->pImmediateContext->GSSetShader(NULL, NULL, 0); /* Shader resource view. */ pBlitter->pImmediateContext->PSSetShaderResources(0, 1, &pSrcShaderResourceView); /* Pixel shader. */ pBlitter->pImmediateContext->PSSetShader(pBlitter->pPixelShader, NULL, 0); /* Sampler. */ pBlitter->pImmediateContext->PSSetSamplers(0, 1, &pBlitter->pSamplerState); /* Rasterizer. */ pBlitter->pImmediateContext->RSSetState(pBlitter->pRasterizerState); /* Blend state. */ static FLOAT const BlendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; pBlitter->pImmediateContext->OMSetBlendState(pBlitter->pBlendState, BlendFactor, 0xffffffff); /* Viewport. */ D3D11_VIEWPORT Viewport; Viewport.TopLeftX = 0; Viewport.TopLeftY = 0; Viewport.Width = cDstWidth; Viewport.Height = cDstHeight; Viewport.MinDepth = 0.0f; Viewport.MaxDepth = 1.0f; pBlitter->pImmediateContext->RSSetViewports(1, &Viewport); /* Draw. */ pBlitter->pImmediateContext->Draw(4, 0); /* * Restore pipeline state. */ pBlitter->pImmediateContext->IASetPrimitiveTopology(SavedState.Topology); pBlitter->pImmediateContext->IASetInputLayout(SavedState.pInputLayout); D3D_RELEASE(SavedState.pInputLayout); pBlitter->pImmediateContext->VSSetConstantBuffers(0, 1, &SavedState.pConstantBuffer); D3D_RELEASE(SavedState.pConstantBuffer); pBlitter->pImmediateContext->VSSetShader(SavedState.pVertexShader, NULL, 0); D3D_RELEASE(SavedState.pVertexShader); pBlitter->pImmediateContext->HSSetShader(SavedState.pHullShader, NULL, 0); D3D_RELEASE(SavedState.pHullShader); pBlitter->pImmediateContext->DSSetShader(SavedState.pDomainShader, NULL, 0); D3D_RELEASE(SavedState.pDomainShader); pBlitter->pImmediateContext->GSSetShader(SavedState.pGeometryShader, NULL, 0); D3D_RELEASE(SavedState.pGeometryShader); pBlitter->pImmediateContext->PSSetShaderResources(0, 1, &SavedState.pShaderResourceView); D3D_RELEASE(SavedState.pShaderResourceView); pBlitter->pImmediateContext->PSSetShader(SavedState.pPixelShader, NULL, 0); D3D_RELEASE(SavedState.pPixelShader); pBlitter->pImmediateContext->PSSetSamplers(0, 1, &SavedState.pSamplerState); D3D_RELEASE(SavedState.pSamplerState); pBlitter->pImmediateContext->RSSetState(SavedState.pRasterizerState); D3D_RELEASE(SavedState.pRasterizerState); pBlitter->pImmediateContext->OMSetBlendState(SavedState.pBlendState, SavedState.BlendFactor, SavedState.SampleMask); D3D_RELEASE(SavedState.pBlendState); pBlitter->pImmediateContext->OMSetRenderTargets(RT_ELEMENTS(SavedState.apRenderTargetView), SavedState.apRenderTargetView, SavedState.pDepthStencilView); D3D_RELEASE_ARRAY(RT_ELEMENTS(SavedState.apRenderTargetView), SavedState.apRenderTargetView); D3D_RELEASE(SavedState.pDepthStencilView); pBlitter->pImmediateContext->RSSetViewports(SavedState.NumViewports, &SavedState.aViewport[0]); return S_OK; } static DECLCALLBACK(int) vmsvga3dBackDXPresentBlt(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId dstSid, uint32_t dstSubResource, SVGA3dBox const *pBoxDst, SVGA3dSurfaceId srcSid, uint32_t srcSubResource, SVGA3dBox const *pBoxSrc, SVGA3dDXPresentBltMode mode) { RT_NOREF(mode); ASSERT_GUEST_RETURN(pBoxDst->z == 0 && pBoxDst->d == 1, VERR_INVALID_PARAMETER); ASSERT_GUEST_RETURN(pBoxSrc->z == 0 && pBoxSrc->d == 1, VERR_INVALID_PARAMETER); PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); PVMSVGA3DSURFACE pSrcSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, srcSid, &pSrcSurface); AssertRCReturn(rc, rc); PVMSVGA3DSURFACE pDstSurface; rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, dstSid, &pDstSurface); AssertRCReturn(rc, rc); if (pSrcSurface->pBackendSurface == NULL) { /* Create the resource. */ if (pSrcSurface->format != SVGA3D_BUFFER) rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSrcSurface); else rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSrcSurface); AssertRCReturn(rc, rc); } if (pDstSurface->pBackendSurface == NULL) { /* Create the resource. */ if (pSrcSurface->format != SVGA3D_BUFFER) rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pDstSurface); else rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pDstSurface); AssertRCReturn(rc, rc); } LogFunc(("cid %d: src cid %d%s -> dst cid %d%s\n", pDXContext->cid, pSrcSurface->idAssociatedContext, (pSrcSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "", pDstSurface->idAssociatedContext, (pDstSurface->f.surfaceFlags & SVGA3D_SURFACE_SCREENTARGET) ? " st" : "")); /* Clip the box. */ /** @todo Use [src|dst]SubResource to index p[Src|Dst]Surface->paMipmapLevels array directly. */ uint32_t iSrcFace; uint32_t iSrcMipmap; vmsvga3dCalcMipmapAndFace(pSrcSurface->cLevels, srcSubResource, &iSrcMipmap, &iSrcFace); uint32_t iDstFace; uint32_t iDstMipmap; vmsvga3dCalcMipmapAndFace(pDstSurface->cLevels, dstSubResource, &iDstMipmap, &iDstFace); PVMSVGA3DMIPMAPLEVEL pSrcMipLevel; rc = vmsvga3dMipmapLevel(pSrcSurface, iSrcFace, iSrcMipmap, &pSrcMipLevel); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); PVMSVGA3DMIPMAPLEVEL pDstMipLevel; rc = vmsvga3dMipmapLevel(pDstSurface, iDstFace, iDstMipmap, &pDstMipLevel); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); SVGA3dBox clipBoxSrc = *pBoxSrc; vmsvgaR3ClipBox(&pSrcMipLevel->mipmapSize, &clipBoxSrc); SVGA3dBox clipBoxDst = *pBoxDst; vmsvgaR3ClipBox(&pDstMipLevel->mipmapSize, &clipBoxDst); ID3D11Resource *pDstResource = dxResource(pThisCC->svga.p3dState, pDstSurface, pDXContext); ID3D11Resource *pSrcResource = dxResource(pThisCC->svga.p3dState, pSrcSurface, pDXContext); D3D11_RENDER_TARGET_VIEW_DESC RTVDesc; RT_ZERO(RTVDesc); RTVDesc.Format = vmsvgaDXSurfaceFormat2Dxgi(pDstSurface->format);; RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; RTVDesc.Texture2D.MipSlice = dstSubResource; ID3D11RenderTargetView *pDstRenderTargetView; HRESULT hr = pDevice->pDevice->CreateRenderTargetView(pDstResource, &RTVDesc, &pDstRenderTargetView); AssertReturn(SUCCEEDED(hr), VERR_NOT_SUPPORTED); D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; RT_ZERO(SRVDesc); SRVDesc.Format = vmsvgaDXSurfaceFormat2Dxgi(pSrcSurface->format); SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MostDetailedMip = srcSubResource; SRVDesc.Texture2D.MipLevels = 1; ID3D11ShaderResourceView *pSrcShaderResourceView; hr = pDevice->pDevice->CreateShaderResourceView(pSrcResource, &SRVDesc, &pSrcShaderResourceView); AssertReturnStmt(SUCCEEDED(hr), D3D_RELEASE(pDstRenderTargetView), VERR_NOT_SUPPORTED); D3D11_RECT rectDst; rectDst.left = pBoxDst->x; rectDst.top = pBoxDst->y; rectDst.right = pBoxDst->x + pBoxDst->w; rectDst.bottom = pBoxDst->y + pBoxDst->h; BlitFromTexture(&pDevice->Blitter, pDstRenderTargetView, (float)pDstMipLevel->mipmapSize.width, (float)pDstMipLevel->mipmapSize.height, rectDst, pSrcShaderResourceView); D3D_RELEASE(pSrcShaderResourceView); D3D_RELEASE(pDstRenderTargetView); pDstSurface->pBackendSurface->cidDrawing = pDXContext->cid; return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXGenMips(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); ID3D11ShaderResourceView *pShaderResourceView = pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId].u.pShaderResourceView; AssertReturn(pShaderResourceView, VERR_INVALID_STATE); SVGACOTableDXSRViewEntry const *pSRViewEntry = dxGetShaderResourceViewEntry(pDXContext, shaderResourceViewId); AssertReturn(pSRViewEntry, VERR_INVALID_STATE); uint32_t const sid = pSRViewEntry->sid; PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface); AssertRCReturn(rc, rc); AssertReturn(pSurface->pBackendSurface, VERR_INVALID_STATE); pDevice->pImmediateContext->GenerateMips(pShaderResourceView); pSurface->pBackendSurface->cidDrawing = pDXContext->cid; return VINF_SUCCESS; } static int dxDefineShaderResourceView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId, SVGACOTableDXSRViewEntry const *pEntry) { /* Get corresponding resource for pEntry->sid. Create the surface if does not yet exist. */ PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pEntry->sid, &pSurface); AssertRCReturn(rc, rc); ID3D11ShaderResourceView *pShaderResourceView; DXVIEW *pView = &pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId]; Assert(pView->u.pView == NULL); if (pSurface->pBackendSurface == NULL) { /* Create the actual texture or buffer. */ /** @todo One function to create all resources from surfaces. */ if (pSurface->format != SVGA3D_BUFFER) rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSurface); else rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } HRESULT hr = dxShaderResourceViewCreate(pThisCC, pDXContext, pEntry, pSurface, &pShaderResourceView); AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); return dxViewInit(pView, pSurface, pDXContext, shaderResourceViewId, VMSVGA3D_VIEWTYPE_SHADERRESOURCE, pShaderResourceView); } static DECLCALLBACK(int) vmsvga3dBackDXDefineShaderResourceView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId, SVGACOTableDXSRViewEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /** @todo Probably not necessary because SRVs are defined in setupPipeline. */ return dxDefineShaderResourceView(pThisCC, pDXContext, shaderResourceViewId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyShaderResourceView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderResourceViewId shaderResourceViewId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxViewDestroy(&pDXContext->pBackendDXContext->paShaderResourceView[shaderResourceViewId]); } static int dxDefineRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGACOTableDXRTViewEntry const *pEntry) { /* Get corresponding resource for pEntry->sid. Create the surface if does not yet exist. */ PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pEntry->sid, &pSurface); AssertRCReturn(rc, rc); DXVIEW *pView = &pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId]; Assert(pView->u.pView == NULL); if (pSurface->pBackendSurface == NULL) { /* Create the actual texture. */ rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } ID3D11RenderTargetView *pRenderTargetView; HRESULT hr = dxRenderTargetViewCreate(pThisCC, pDXContext, pEntry, pSurface, &pRenderTargetView); AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); return dxViewInit(pView, pSurface, pDXContext, renderTargetViewId, VMSVGA3D_VIEWTYPE_RENDERTARGET, pRenderTargetView); } static DECLCALLBACK(int) vmsvga3dBackDXDefineRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId, SVGACOTableDXRTViewEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); return dxDefineRenderTargetView(pThisCC, pDXContext, renderTargetViewId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyRenderTargetView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRenderTargetViewId renderTargetViewId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxViewDestroy(&pDXContext->pBackendDXContext->paRenderTargetView[renderTargetViewId]); } static int dxDefineDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, SVGACOTableDXDSViewEntry const *pEntry) { /* Get corresponding resource for pEntry->sid. Create the surface if does not yet exist. */ PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pEntry->sid, &pSurface); AssertRCReturn(rc, rc); DXVIEW *pView = &pDXContext->pBackendDXContext->paDepthStencilView[depthStencilViewId]; Assert(pView->u.pView == NULL); if (pSurface->pBackendSurface == NULL) { /* Create the actual texture. */ rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } ID3D11DepthStencilView *pDepthStencilView; HRESULT hr = dxDepthStencilViewCreate(pThisCC, pDXContext, pEntry, pSurface, &pDepthStencilView); AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); return dxViewInit(pView, pSurface, pDXContext, depthStencilViewId, VMSVGA3D_VIEWTYPE_DEPTHSTENCIL, pDepthStencilView); } static DECLCALLBACK(int) vmsvga3dBackDXDefineDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId, SVGACOTableDXDSViewEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); return dxDefineDepthStencilView(pThisCC, pDXContext, depthStencilViewId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyDepthStencilView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilViewId depthStencilViewId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxViewDestroy(&pDXContext->pBackendDXContext->paDepthStencilView[depthStencilViewId]); } static int dxDefineElementLayout(PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId, SVGACOTableDXElementLayoutEntry const *pEntry) { DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; D3D_RELEASE(pDXElementLayout->pElementLayout); pDXElementLayout->cElementDesc = 0; RT_ZERO(pDXElementLayout->aElementDesc); RT_NOREF(pEntry); return VINF_SUCCESS; } static int dxDestroyElementLayout(DXELEMENTLAYOUT *pDXElementLayout) { D3D_RELEASE(pDXElementLayout->pElementLayout); pDXElementLayout->cElementDesc = 0; RT_ZERO(pDXElementLayout->aElementDesc); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDefineElementLayout(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId, SVGACOTableDXElementLayoutEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(pBackend); /* Not much can be done here because ID3D11Device::CreateInputLayout requires * a pShaderBytecodeWithInputSignature which is not known at this moment. * InputLayout object will be created in setupPipeline. */ Assert(elementLayoutId == pEntry->elid); return dxDefineElementLayout(pDXContext, elementLayoutId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyElementLayout(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dElementLayoutId elementLayoutId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXELEMENTLAYOUT *pDXElementLayout = &pDXContext->pBackendDXContext->paElementLayout[elementLayoutId]; dxDestroyElementLayout(pDXElementLayout); return VINF_SUCCESS; } static int dxDefineBlendState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dBlendStateId blendId, SVGACOTableDXBlendStateEntry const *pEntry) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); HRESULT hr = dxBlendStateCreate(pDevice, pEntry, &pDXContext->pBackendDXContext->papBlendState[blendId]); if (SUCCEEDED(hr)) return VINF_SUCCESS; return VERR_INVALID_STATE; } static DECLCALLBACK(int) vmsvga3dBackDXDefineBlendState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dBlendStateId blendId, SVGACOTableDXBlendStateEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxDefineBlendState(pThisCC, pDXContext, blendId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyBlendState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dBlendStateId blendId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); D3D_RELEASE(pDXContext->pBackendDXContext->papBlendState[blendId]); return VINF_SUCCESS; } static int dxDefineDepthStencilState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId, SVGACOTableDXDepthStencilEntry const *pEntry) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); HRESULT hr = dxDepthStencilStateCreate(pDevice, pEntry, &pDXContext->pBackendDXContext->papDepthStencilState[depthStencilId]); if (SUCCEEDED(hr)) return VINF_SUCCESS; return VERR_INVALID_STATE; } static DECLCALLBACK(int) vmsvga3dBackDXDefineDepthStencilState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId, SVGACOTableDXDepthStencilEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxDefineDepthStencilState(pThisCC, pDXContext, depthStencilId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyDepthStencilState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dDepthStencilStateId depthStencilId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); D3D_RELEASE(pDXContext->pBackendDXContext->papDepthStencilState[depthStencilId]); return VINF_SUCCESS; } static int dxDefineRasterizerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId, SVGACOTableDXRasterizerStateEntry const *pEntry) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); HRESULT hr = dxRasterizerStateCreate(pDevice, pEntry, &pDXContext->pBackendDXContext->papRasterizerState[rasterizerId]); if (SUCCEEDED(hr)) return VINF_SUCCESS; return VERR_INVALID_STATE; } static DECLCALLBACK(int) vmsvga3dBackDXDefineRasterizerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId, SVGACOTableDXRasterizerStateEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxDefineRasterizerState(pThisCC, pDXContext, rasterizerId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyRasterizerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dRasterizerStateId rasterizerId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); D3D_RELEASE(pDXContext->pBackendDXContext->papRasterizerState[rasterizerId]); return VINF_SUCCESS; } static int dxDefineSamplerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSamplerId samplerId, SVGACOTableDXSamplerEntry const *pEntry) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); HRESULT hr = dxSamplerStateCreate(pDevice, pEntry, &pDXContext->pBackendDXContext->papSamplerState[samplerId]); if (SUCCEEDED(hr)) return VINF_SUCCESS; return VERR_INVALID_STATE; } static DECLCALLBACK(int) vmsvga3dBackDXDefineSamplerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSamplerId samplerId, SVGACOTableDXSamplerEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxDefineSamplerState(pThisCC, pDXContext, samplerId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroySamplerState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSamplerId samplerId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); D3D_RELEASE(pDXContext->pBackendDXContext->papSamplerState[samplerId]); return VINF_SUCCESS; } static int dxDefineShader(PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, SVGACOTableDXShaderEntry const *pEntry) { /** @todo A common approach for creation of COTable backend objects: runtime, empty DX COTable, live DX COTable. */ DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[shaderId]; Assert(pDXShader->enmShaderType == SVGA3D_SHADERTYPE_INVALID); /* Init the backend shader structure, if the shader has not been created yet. */ pDXShader->enmShaderType = pEntry->type; pDXShader->pShader = NULL; pDXShader->soid = SVGA_ID_INVALID; return VINF_SUCCESS; } static int dxDestroyShader(DXSHADER *pDXShader) { pDXShader->enmShaderType = SVGA3D_SHADERTYPE_INVALID; DXShaderFree(&pDXShader->shaderInfo); D3D_RELEASE(pDXShader->pShader); RTMemFree(pDXShader->pvDXBC); pDXShader->pvDXBC = NULL; pDXShader->cbDXBC = 0; pDXShader->soid = SVGA_ID_INVALID; return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDefineShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, SVGACOTableDXShaderEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxDefineShader(pDXContext, shaderId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[shaderId]; dxDestroyShader(pDXShader); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXBindShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dShaderId shaderId, DXShaderInfo const *pShaderInfo) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(pBackend); DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[shaderId]; if (pDXShader->pvDXBC) { /* New DXBC code and new shader must be created. */ D3D_RELEASE(pDXShader->pShader); RTMemFree(pDXShader->pvDXBC); pDXShader->pvDXBC = NULL; pDXShader->cbDXBC = 0; } pDXShader->shaderInfo = *pShaderInfo; return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDefineStreamOutput(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid, SVGACOTableDXStreamOutputEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; dxDestroyStreamOutput(pDXStreamOutput); RT_NOREF(pEntry); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDestroyStreamOutput(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[soid]; dxDestroyStreamOutput(pDXStreamOutput); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetStreamOutput(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dStreamOutputId soid) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext, soid); return VINF_SUCCESS; } static int dxCOTableRealloc(void **ppvCOTable, uint32_t *pcCOTable, uint32_t cbEntry, uint32_t cEntries, uint32_t cValidEntries) { uint32_t const cCOTableCurrent = *pcCOTable; if (*pcCOTable != cEntries) { /* Grow/shrink the array. */ if (cEntries) { void *pvNew = RTMemRealloc(*ppvCOTable, cEntries * cbEntry); AssertReturn(pvNew, VERR_NO_MEMORY); *ppvCOTable = pvNew; } else { RTMemFree(*ppvCOTable); *ppvCOTable = NULL; } *pcCOTable = cEntries; } if (*ppvCOTable) { uint32_t const cEntriesToKeep = RT_MIN(cCOTableCurrent, cValidEntries); memset((uint8_t *)(*ppvCOTable) + cEntriesToKeep * cbEntry, 0, (cEntries - cEntriesToKeep) * cbEntry); } return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetCOTable(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGACOTableType type, uint32_t cValidEntries) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); VMSVGA3DBACKENDDXCONTEXT *pBackendDXContext = pDXContext->pBackendDXContext; int rc = VINF_SUCCESS; /* * 1) Release current backend table, if exists; * 2) Reallocate memory for the new backend table; * 3) If cValidEntries is not zero, then re-define corresponding backend table elements. */ switch (type) { case SVGA_COTABLE_RTVIEW: /* Clear current entries. */ if (pBackendDXContext->paRenderTargetView) { for (uint32_t i = 0; i < pBackendDXContext->cRenderTargetView; ++i) { DXVIEW *pDXView = &pBackendDXContext->paRenderTargetView[i]; if (i < cValidEntries) dxViewRemoveFromList(pDXView); /* Remove from list because DXVIEW array will be reallocated. */ else dxViewDestroy(pDXView); } } rc = dxCOTableRealloc((void **)&pBackendDXContext->paRenderTargetView, &pBackendDXContext->cRenderTargetView, sizeof(pBackendDXContext->paRenderTargetView[0]), pDXContext->cot.cRTView, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXRTViewEntry const *pEntry = &pDXContext->cot.paRTView[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ /* Define views which were not defined yet in backend. */ DXVIEW *pDXView = &pBackendDXContext->paRenderTargetView[i]; /** @todo Verify that the pEntry content still corresponds to the view. */ if (pDXView->u.pView) dxViewAddToList(pThisCC, pDXView); else if (pDXView->enmViewType == VMSVGA3D_VIEWTYPE_NONE) dxDefineRenderTargetView(pThisCC, pDXContext, i, pEntry); } break; case SVGA_COTABLE_DSVIEW: if (pBackendDXContext->paDepthStencilView) { for (uint32_t i = 0; i < pBackendDXContext->cDepthStencilView; ++i) { DXVIEW *pDXView = &pBackendDXContext->paDepthStencilView[i]; if (i < cValidEntries) dxViewRemoveFromList(pDXView); /* Remove from list because DXVIEW array will be reallocated. */ else dxViewDestroy(pDXView); } } rc = dxCOTableRealloc((void **)&pBackendDXContext->paDepthStencilView, &pBackendDXContext->cDepthStencilView, sizeof(pBackendDXContext->paDepthStencilView[0]), pDXContext->cot.cDSView, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXDSViewEntry const *pEntry = &pDXContext->cot.paDSView[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ /* Define views which were not defined yet in backend. */ DXVIEW *pDXView = &pBackendDXContext->paDepthStencilView[i]; /** @todo Verify that the pEntry content still corresponds to the view. */ if (pDXView->u.pView) dxViewAddToList(pThisCC, pDXView); else if (pDXView->enmViewType == VMSVGA3D_VIEWTYPE_NONE) dxDefineDepthStencilView(pThisCC, pDXContext, i, pEntry); } break; case SVGA_COTABLE_SRVIEW: if (pBackendDXContext->paShaderResourceView) { for (uint32_t i = 0; i < pBackendDXContext->cShaderResourceView; ++i) { DXVIEW *pDXView = &pBackendDXContext->paShaderResourceView[i]; if (i < cValidEntries) dxViewRemoveFromList(pDXView); /* Remove from list because DXVIEW array will be reallocated. */ else dxViewDestroy(pDXView); } } rc = dxCOTableRealloc((void **)&pBackendDXContext->paShaderResourceView, &pBackendDXContext->cShaderResourceView, sizeof(pBackendDXContext->paShaderResourceView[0]), pDXContext->cot.cSRView, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXSRViewEntry const *pEntry = &pDXContext->cot.paSRView[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ /* Define views which were not defined yet in backend. */ DXVIEW *pDXView = &pBackendDXContext->paShaderResourceView[i]; /** @todo Verify that the pEntry content still corresponds to the view. */ if (pDXView->u.pView) dxViewAddToList(pThisCC, pDXView); else if (pDXView->enmViewType == VMSVGA3D_VIEWTYPE_NONE) dxDefineShaderResourceView(pThisCC, pDXContext, i, pEntry); } break; case SVGA_COTABLE_ELEMENTLAYOUT: if (pBackendDXContext->paElementLayout) { for (uint32_t i = cValidEntries; i < pBackendDXContext->cElementLayout; ++i) D3D_RELEASE(pBackendDXContext->paElementLayout[i].pElementLayout); } rc = dxCOTableRealloc((void **)&pBackendDXContext->paElementLayout, &pBackendDXContext->cElementLayout, sizeof(pBackendDXContext->paElementLayout[0]), pDXContext->cot.cElementLayout, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXElementLayoutEntry const *pEntry = &pDXContext->cot.paElementLayout[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ dxDefineElementLayout(pDXContext, i, pEntry); } break; case SVGA_COTABLE_BLENDSTATE: if (pBackendDXContext->papBlendState) { for (uint32_t i = cValidEntries; i < pBackendDXContext->cBlendState; ++i) D3D_RELEASE(pBackendDXContext->papBlendState[i]); } rc = dxCOTableRealloc((void **)&pBackendDXContext->papBlendState, &pBackendDXContext->cBlendState, sizeof(pBackendDXContext->papBlendState[0]), pDXContext->cot.cBlendState, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXBlendStateEntry const *pEntry = &pDXContext->cot.paBlendState[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ dxDefineBlendState(pThisCC, pDXContext, i, pEntry); } break; case SVGA_COTABLE_DEPTHSTENCIL: if (pBackendDXContext->papDepthStencilState) { for (uint32_t i = cValidEntries; i < pBackendDXContext->cDepthStencilState; ++i) D3D_RELEASE(pBackendDXContext->papDepthStencilState[i]); } rc = dxCOTableRealloc((void **)&pBackendDXContext->papDepthStencilState, &pBackendDXContext->cDepthStencilState, sizeof(pBackendDXContext->papDepthStencilState[0]), pDXContext->cot.cDepthStencil, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXDepthStencilEntry const *pEntry = &pDXContext->cot.paDepthStencil[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ dxDefineDepthStencilState(pThisCC, pDXContext, i, pEntry); } break; case SVGA_COTABLE_RASTERIZERSTATE: if (pBackendDXContext->papRasterizerState) { for (uint32_t i = cValidEntries; i < pBackendDXContext->cRasterizerState; ++i) D3D_RELEASE(pBackendDXContext->papRasterizerState[i]); } rc = dxCOTableRealloc((void **)&pBackendDXContext->papRasterizerState, &pBackendDXContext->cRasterizerState, sizeof(pBackendDXContext->papRasterizerState[0]), pDXContext->cot.cRasterizerState, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXRasterizerStateEntry const *pEntry = &pDXContext->cot.paRasterizerState[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ dxDefineRasterizerState(pThisCC, pDXContext, i, pEntry); } break; case SVGA_COTABLE_SAMPLER: if (pBackendDXContext->papSamplerState) { for (uint32_t i = cValidEntries; i < pBackendDXContext->cSamplerState; ++i) D3D_RELEASE(pBackendDXContext->papSamplerState[i]); } rc = dxCOTableRealloc((void **)&pBackendDXContext->papSamplerState, &pBackendDXContext->cSamplerState, sizeof(pBackendDXContext->papSamplerState[0]), pDXContext->cot.cSampler, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXSamplerEntry const *pEntry = &pDXContext->cot.paSampler[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ dxDefineSamplerState(pThisCC, pDXContext, i, pEntry); } break; case SVGA_COTABLE_STREAMOUTPUT: if (pBackendDXContext->paStreamOutput) { for (uint32_t i = cValidEntries; i < pBackendDXContext->cStreamOutput; ++i) dxDestroyStreamOutput(&pBackendDXContext->paStreamOutput[i]); } rc = dxCOTableRealloc((void **)&pBackendDXContext->paStreamOutput, &pBackendDXContext->cStreamOutput, sizeof(pBackendDXContext->paStreamOutput[0]), pDXContext->cot.cStreamOutput, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXStreamOutputEntry const *pEntry = &pDXContext->cot.paStreamOutput[i]; /** @todo The caller must verify the COTable content using same rules as when a new entry is defined. */ if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ /* Reset the stream output backend data. It will be re-created when a GS shader with this streamoutput * will be set in setupPipeline. */ DXSTREAMOUTPUT *pDXStreamOutput = &pDXContext->pBackendDXContext->paStreamOutput[i]; dxDestroyStreamOutput(pDXStreamOutput); } break; case SVGA_COTABLE_DXQUERY: if (pBackendDXContext->paQuery) { /* Destroy the no longer used entries. */ for (uint32_t i = cValidEntries; i < pBackendDXContext->cQuery; ++i) dxDestroyQuery(&pBackendDXContext->paQuery[i]); } rc = dxCOTableRealloc((void **)&pBackendDXContext->paQuery, &pBackendDXContext->cQuery, sizeof(pBackendDXContext->paQuery[0]), pDXContext->cot.cQuery, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXQueryEntry const *pEntry = &pDXContext->cot.paQuery[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ /* Define queries which were not defined yet in backend. */ DXQUERY *pDXQuery = &pBackendDXContext->paQuery[i]; if ( pEntry->type != SVGA3D_QUERYTYPE_INVALID && pDXQuery->pQuery == NULL) dxDefineQuery(pThisCC, pDXContext, i, pEntry); else Assert(pEntry->type == SVGA3D_QUERYTYPE_INVALID || pDXQuery->pQuery); } break; case SVGA_COTABLE_DXSHADER: if (pBackendDXContext->paShader) { /* Destroy the no longer used entries. */ for (uint32_t i = cValidEntries; i < pBackendDXContext->cShader; ++i) dxDestroyShader(&pBackendDXContext->paShader[i]); } rc = dxCOTableRealloc((void **)&pBackendDXContext->paShader, &pBackendDXContext->cShader, sizeof(pBackendDXContext->paShader[0]), pDXContext->cot.cShader, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXShaderEntry const *pEntry = &pDXContext->cot.paShader[i]; /** @todo The caller must verify the COTable content using same rules as when a new entry is defined. */ if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ /* Define shaders which were not defined yet in backend. */ DXSHADER *pDXShader = &pBackendDXContext->paShader[i]; if ( pEntry->type != SVGA3D_SHADERTYPE_INVALID && pDXShader->enmShaderType == SVGA3D_SHADERTYPE_INVALID) dxDefineShader(pDXContext, i, pEntry); else Assert(pEntry->type == pDXShader->enmShaderType); } break; case SVGA_COTABLE_UAVIEW: if (pBackendDXContext->paUnorderedAccessView) { for (uint32_t i = 0; i < pBackendDXContext->cUnorderedAccessView; ++i) { DXVIEW *pDXView = &pBackendDXContext->paUnorderedAccessView[i]; if (i < cValidEntries) dxViewRemoveFromList(pDXView); /* Remove from list because DXVIEW array will be reallocated. */ else dxViewDestroy(pDXView); } } rc = dxCOTableRealloc((void **)&pBackendDXContext->paUnorderedAccessView, &pBackendDXContext->cUnorderedAccessView, sizeof(pBackendDXContext->paUnorderedAccessView[0]), pDXContext->cot.cUAView, cValidEntries); AssertRCBreak(rc); for (uint32_t i = 0; i < cValidEntries; ++i) { SVGACOTableDXUAViewEntry const *pEntry = &pDXContext->cot.paUAView[i]; if (ASMMemFirstNonZero(pEntry, sizeof(*pEntry)) == NULL) continue; /* Skip uninitialized entry. */ /* Define views which were not defined yet in backend. */ DXVIEW *pDXView = &pBackendDXContext->paUnorderedAccessView[i]; /** @todo Verify that the pEntry content still corresponds to the view. */ if (pDXView->u.pView) dxViewAddToList(pThisCC, pDXView); else if (pDXView->enmViewType == VMSVGA3D_VIEWTYPE_NONE) dxDefineUnorderedAccessView(pThisCC, pDXContext, i, pEntry); } break; case SVGA_COTABLE_MAX: break; /* Compiler warning */ } return rc; } static DECLCALLBACK(int) vmsvga3dBackDXBufferCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXSurfaceCopyAndReadback(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXMoveQuery(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXBindAllShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXHint(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXBufferUpdate(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXCondBindAllShader(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackScreenCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackIntraSurfaceCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceImageId const &surface, SVGA3dCopyBox const &box) { RT_NOREF(pDXContext); LogFunc(("sid %u\n", surface.sid)); PVMSVGA3DSTATE pState = pThisCC->svga.p3dState; AssertReturn(pState, VERR_INVALID_STATE); PVMSVGA3DBACKEND pBackend = pState->pBackend; PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, surface.sid, &pSurface); AssertRCReturn(rc, rc); PVMSVGA3DMIPMAPLEVEL pMipLevel; rc = vmsvga3dMipmapLevel(pSurface, surface.face, surface.mipmap, &pMipLevel); ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc); /* Clip the box. */ SVGA3dCopyBox clipBox = box; vmsvgaR3ClipCopyBox(&pMipLevel->mipmapSize, &pMipLevel->mipmapSize, &clipBox); LogFunc(("surface%s cid %d\n", pSurface->pBackendSurface ? "" : " sysmem", pSurface ? pSurface->idAssociatedContext : SVGA_ID_INVALID)); if (pSurface->pBackendSurface) { /* Surface -> Surface. */ DXDEVICE *pDXDevice = &pBackend->dxDevice; UINT DstSubresource = vmsvga3dCalcSubresource(surface.mipmap, surface.face, pSurface->cLevels); UINT DstX = clipBox.x; UINT DstY = clipBox.y; UINT DstZ = clipBox.z; UINT SrcSubresource = DstSubresource; D3D11_BOX SrcBox; SrcBox.left = clipBox.srcx; SrcBox.top = clipBox.srcy; SrcBox.front = clipBox.srcz; SrcBox.right = clipBox.srcx + clipBox.w; SrcBox.bottom = clipBox.srcy + clipBox.h; SrcBox.back = clipBox.srcz + clipBox.d; ID3D11Resource *pDstResource; ID3D11Resource *pSrcResource; pDstResource = dxResource(pState, pSurface, NULL); pSrcResource = pDstResource; pDXDevice->pImmediateContext->CopySubresourceRegion1(pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, &SrcBox, 0); } else { /* Memory -> Memory. */ uint32_t const cxBlocks = (clipBox.w + pSurface->cxBlock - 1) / pSurface->cxBlock; uint32_t const cyBlocks = (clipBox.h + pSurface->cyBlock - 1) / pSurface->cyBlock; uint32_t const cbRow = cxBlocks * pSurface->cbBlock; uint8_t const *pu8Src = (uint8_t *)pMipLevel->pSurfaceData + (clipBox.srcx / pSurface->cxBlock) * pSurface->cbBlock + (clipBox.srcy / pSurface->cyBlock) * pMipLevel->cbSurfacePitch + clipBox.srcz * pMipLevel->cbSurfacePlane; uint8_t *pu8Dst = (uint8_t *)pMipLevel->pSurfaceData + (clipBox.x / pSurface->cxBlock) * pSurface->cbBlock + (clipBox.y / pSurface->cyBlock) * pMipLevel->cbSurfacePitch + clipBox.z * pMipLevel->cbSurfacePlane; for (uint32_t z = 0; z < clipBox.d; ++z) { uint8_t const *pu8PlaneSrc = pu8Src; uint8_t *pu8PlaneDst = pu8Dst; for (uint32_t y = 0; y < cyBlocks; ++y) { memmove(pu8PlaneDst, pu8PlaneSrc, cbRow); pu8PlaneDst += pMipLevel->cbSurfacePitch; pu8PlaneSrc += pMipLevel->cbSurfacePitch; } pu8Src += pMipLevel->cbSurfacePlane; pu8Dst += pMipLevel->cbSurfacePlane; } } return rc; } static DECLCALLBACK(int) vmsvga3dBackDXResolveCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXPredResolveCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXPredConvertRegion(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXPredConvert(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackWholeSurfaceCopy(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static int dxDefineUnorderedAccessView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, SVGACOTableDXUAViewEntry const *pEntry) { /* Get corresponding resource for pEntry->sid. Create the surface if does not yet exist. */ PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pEntry->sid, &pSurface); AssertRCReturn(rc, rc); ID3D11UnorderedAccessView *pUnorderedAccessView; DXVIEW *pView = &pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]; Assert(pView->u.pView == NULL); if (pSurface->pBackendSurface == NULL) { /* Create the actual texture or buffer. */ /** @todo One function to create all resources from surfaces. */ if (pSurface->format != SVGA3D_BUFFER) rc = vmsvga3dBackSurfaceCreateTexture(pThisCC, pDXContext, pSurface); else rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } HRESULT hr = dxUnorderedAccessViewCreate(pThisCC, pDXContext, pEntry, pSurface, &pUnorderedAccessView); AssertReturn(SUCCEEDED(hr), VERR_INVALID_STATE); return dxViewInit(pView, pSurface, pDXContext, uaViewId, VMSVGA3D_VIEWTYPE_UNORDEREDACCESS, pUnorderedAccessView); } static DECLCALLBACK(int) vmsvga3dBackDXDefineUAView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, SVGACOTableDXUAViewEntry const *pEntry) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /** @todo Probably not necessary because UAVs are defined in setupPipeline. */ return dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pEntry); } static DECLCALLBACK(int) vmsvga3dBackDXDestroyUAView(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); return dxViewDestroy(&pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]); } static DECLCALLBACK(int) vmsvga3dBackDXClearUAViewUint(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, uint32_t const aValues[4]) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); DXVIEW *pDXView = &pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]; if (!pDXView->u.pUnorderedAccessView) { /* (Re-)create the view, because a creation of a view is deferred until a draw or a clear call. */ SVGACOTableDXUAViewEntry const *pEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); int rc = dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pEntry); AssertRCReturn(rc, rc); } pDevice->pImmediateContext->ClearUnorderedAccessViewUint(pDXView->u.pUnorderedAccessView, aValues); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXClearUAViewFloat(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId uaViewId, float const aValues[4]) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); DXVIEW *pDXView = &pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]; if (!pDXView->u.pUnorderedAccessView) { /* (Re-)create the view, because a creation of a view is deferred until a draw or a clear call. */ SVGACOTableDXUAViewEntry const *pEntry = &pDXContext->cot.paUAView[uaViewId]; int rc = dxDefineUnorderedAccessView(pThisCC, pDXContext, uaViewId, pEntry); AssertRCReturn(rc, rc); } pDevice->pImmediateContext->ClearUnorderedAccessViewFloat(pDXView->u.pUnorderedAccessView, aValues); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXCopyStructureCount(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dUAViewId srcUAViewId, SVGA3dSurfaceId destSid, uint32_t destByteOffset) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /* Get corresponding resource. Create the buffer if does not yet exist. */ ID3D11Buffer *pDstBuffer; if (destSid != SVGA3D_INVALID_ID) { PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, destSid, &pSurface); AssertRCReturn(rc, rc); if (pSurface->pBackendSurface == NULL) { /* Create the resource and initialize it with the current surface data. */ rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } pDstBuffer = pSurface->pBackendSurface->u.pBuffer; } else pDstBuffer = NULL; ID3D11UnorderedAccessView *pSrcView; if (srcUAViewId != SVGA3D_INVALID_ID) { DXVIEW *pDXView = &pDXContext->pBackendDXContext->paUnorderedAccessView[srcUAViewId]; AssertReturn(pDXView->u.pUnorderedAccessView, VERR_INVALID_STATE); pSrcView = pDXView->u.pUnorderedAccessView; } else pSrcView = NULL; pDevice->pImmediateContext->CopyStructureCount(pDstBuffer, destByteOffset, pSrcView); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetUAViews(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t uavSpliceIndex, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(uavSpliceIndex, cUAViewId, paUAViewId); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDrawIndexedInstancedIndirect(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId argsBufferSid, uint32_t byteOffsetForArgs) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /* Get corresponding resource. Create the buffer if does not yet exist. */ ID3D11Buffer *pBufferForArgs; if (argsBufferSid != SVGA_ID_INVALID) { PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, argsBufferSid, &pSurface); AssertRCReturn(rc, rc); if (pSurface->pBackendSurface == NULL) { /* Create the resource and initialize it with the current surface data. */ rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } pBufferForArgs = pSurface->pBackendSurface->u.pBuffer; } else pBufferForArgs = NULL; dxSetupPipeline(pThisCC, pDXContext); Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); pDevice->pImmediateContext->DrawIndexedInstancedIndirect(pBufferForArgs, byteOffsetForArgs); /* Note which surfaces are being drawn. */ dxTrackRenderTargets(pThisCC, pDXContext); #ifdef DX_FLUSH_AFTER_DRAW dxDeviceFlush(pDevice); #endif return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDrawInstancedIndirect(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, SVGA3dSurfaceId argsBufferSid, uint32_t byteOffsetForArgs) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); /* Get corresponding resource. Create the buffer if does not yet exist. */ ID3D11Buffer *pBufferForArgs; if (argsBufferSid != SVGA_ID_INVALID) { PVMSVGA3DSURFACE pSurface; int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, argsBufferSid, &pSurface); AssertRCReturn(rc, rc); if (pSurface->pBackendSurface == NULL) { /* Create the resource and initialize it with the current surface data. */ rc = vmsvga3dBackSurfaceCreateResource(pThisCC, pDXContext, pSurface); AssertRCReturn(rc, rc); } pBufferForArgs = pSurface->pBackendSurface->u.pBuffer; } else pBufferForArgs = NULL; dxSetupPipeline(pThisCC, pDXContext); Assert(pDXContext->svgaDXContext.inputAssembly.topology != SVGA3D_PRIMITIVE_TRIANGLEFAN); pDevice->pImmediateContext->DrawInstancedIndirect(pBufferForArgs, byteOffsetForArgs); /* Note which surfaces are being drawn. */ dxTrackRenderTargets(pThisCC, pDXContext); #ifdef DX_FLUSH_AFTER_DRAW dxDeviceFlush(pDevice); #endif return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDispatch(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); dxSetupPipeline(pThisCC, pDXContext); pDevice->pImmediateContext->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ); #ifdef DX_FLUSH_AFTER_DRAW dxDeviceFlush(pDevice); #endif return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXDispatchIndirect(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackWriteZeroSurface(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackHintZeroSurface(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXTransferToBuffer(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackLogicOpsBitBlt(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackLogicOpsTransBlt(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackLogicOpsStretchBlt(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackLogicOpsColorFill(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackLogicOpsAlphaBlend(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackLogicOpsClearTypeBlend(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static int dxSetCSUnorderedAccessViews(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); //DEBUG_BREAKPOINT_TEST(); uint32_t const *pUAIds = &pDXContext->svgaDXContext.csuaViewIds[0]; ID3D11UnorderedAccessView *papUnorderedAccessView[SVGA3D_DX11_1_MAX_UAVIEWS]; UINT aUAVInitialCounts[SVGA3D_DX11_1_MAX_UAVIEWS]; for (uint32_t i = 0; i < SVGA3D_DX11_1_MAX_UAVIEWS; ++i) { SVGA3dUAViewId const uaViewId = pUAIds[i]; if (uaViewId != SVGA3D_INVALID_ID) { ASSERT_GUEST_RETURN(uaViewId < pDXContext->pBackendDXContext->cUnorderedAccessView, VERR_INVALID_PARAMETER); DXVIEW *pDXView = &pDXContext->pBackendDXContext->paUnorderedAccessView[uaViewId]; Assert(pDXView->u.pUnorderedAccessView); papUnorderedAccessView[i] = pDXView->u.pUnorderedAccessView; SVGACOTableDXUAViewEntry const *pEntry = dxGetUnorderedAccessViewEntry(pDXContext, uaViewId); aUAVInitialCounts[i] = pEntry->structureCount; } else { papUnorderedAccessView[i] = NULL; aUAVInitialCounts[i] = (UINT)-1; } } dxCSUnorderedAccessViewSet(pDevice, 0, SVGA3D_DX11_1_MAX_UAVIEWS, papUnorderedAccessView, aUAVInitialCounts); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetCSUAViews(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, uint32_t startIndex, uint32_t cUAViewId, SVGA3dUAViewId const *paUAViewId) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend); DXDEVICE *pDevice = dxDeviceFromContext(pThisCC->svga.p3dState, pDXContext); AssertReturn(pDevice->pDevice, VERR_INVALID_STATE); RT_NOREF(startIndex, cUAViewId, paUAViewId); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSetMinLOD(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXSetShaderIface(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackSurfaceStretchBltNonMSToMS(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXBindShaderIface(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext) { PVMSVGA3DBACKEND pBackend = pThisCC->svga.p3dState->pBackend; RT_NOREF(pBackend, pDXContext); AssertFailed(); /** @todo Implement */ return VERR_NOT_IMPLEMENTED; } static DECLCALLBACK(int) vmsvga3dBackDXLoadState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM) { RT_NOREF(pThisCC); uint32_t u32; int rc; rc = pHlp->pfnSSMGetU32(pSSM, &u32); AssertLogRelRCReturn(rc, rc); AssertLogRelRCReturn(u32 == pDXContext->pBackendDXContext->cShader, VERR_INVALID_STATE); for (uint32_t i = 0; i < pDXContext->pBackendDXContext->cShader; ++i) { DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[i]; rc = pHlp->pfnSSMGetU32(pSSM, &u32); AssertLogRelRCReturn(rc, rc); AssertLogRelReturn((SVGA3dShaderType)u32 == pDXShader->enmShaderType, VERR_INVALID_STATE); if (pDXShader->enmShaderType == SVGA3D_SHADERTYPE_INVALID) continue; pHlp->pfnSSMGetU32(pSSM, &pDXShader->soid); pHlp->pfnSSMGetU32(pSSM, &u32); pDXShader->shaderInfo.enmProgramType = (VGPU10_PROGRAM_TYPE)u32; rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cbBytecode); AssertLogRelRCReturn(rc, rc); AssertLogRelReturn(pDXShader->shaderInfo.cbBytecode <= 2 * SVGA3D_MAX_SHADER_MEMORY_BYTES, VERR_INVALID_STATE); if (pDXShader->shaderInfo.cbBytecode) { pDXShader->shaderInfo.pvBytecode = RTMemAlloc(pDXShader->shaderInfo.cbBytecode); AssertPtrReturn(pDXShader->shaderInfo.pvBytecode, VERR_NO_MEMORY); pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.pvBytecode, pDXShader->shaderInfo.cbBytecode); } rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cInputSignature); AssertLogRelRCReturn(rc, rc); AssertLogRelReturn(pDXShader->shaderInfo.cInputSignature <= 32, VERR_INVALID_STATE); if (pDXShader->shaderInfo.cInputSignature) pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.aInputSignature, pDXShader->shaderInfo.cInputSignature * sizeof(SVGA3dDXSignatureEntry)); rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cOutputSignature); AssertLogRelRCReturn(rc, rc); AssertLogRelReturn(pDXShader->shaderInfo.cOutputSignature <= 32, VERR_INVALID_STATE); if (pDXShader->shaderInfo.cOutputSignature) pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.aOutputSignature, pDXShader->shaderInfo.cOutputSignature * sizeof(SVGA3dDXSignatureEntry)); rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cPatchConstantSignature); AssertLogRelRCReturn(rc, rc); AssertLogRelReturn(pDXShader->shaderInfo.cPatchConstantSignature <= 32, VERR_INVALID_STATE); if (pDXShader->shaderInfo.cPatchConstantSignature) pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.aPatchConstantSignature, pDXShader->shaderInfo.cPatchConstantSignature * sizeof(SVGA3dDXSignatureEntry)); rc = pHlp->pfnSSMGetU32(pSSM, &pDXShader->shaderInfo.cDclResource); AssertLogRelRCReturn(rc, rc); AssertLogRelReturn(pDXShader->shaderInfo.cDclResource <= SVGA3D_DX_MAX_SRVIEWS, VERR_INVALID_STATE); if (pDXShader->shaderInfo.cDclResource) pHlp->pfnSSMGetMem(pSSM, pDXShader->shaderInfo.aOffDclResource, pDXShader->shaderInfo.cDclResource * sizeof(uint32_t)); DXShaderGenerateSemantics(&pDXShader->shaderInfo); } rc = pHlp->pfnSSMGetU32(pSSM, &pDXContext->pBackendDXContext->cSOTarget); AssertLogRelRCReturn(rc, rc); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackDXSaveState(PVGASTATECC pThisCC, PVMSVGA3DDXCONTEXT pDXContext, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM) { RT_NOREF(pThisCC); int rc; pHlp->pfnSSMPutU32(pSSM, pDXContext->pBackendDXContext->cShader); for (uint32_t i = 0; i < pDXContext->pBackendDXContext->cShader; ++i) { DXSHADER *pDXShader = &pDXContext->pBackendDXContext->paShader[i]; pHlp->pfnSSMPutU32(pSSM, (uint32_t)pDXShader->enmShaderType); if (pDXShader->enmShaderType == SVGA3D_SHADERTYPE_INVALID) continue; pHlp->pfnSSMPutU32(pSSM, pDXShader->soid); pHlp->pfnSSMPutU32(pSSM, (uint32_t)pDXShader->shaderInfo.enmProgramType); pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cbBytecode); if (pDXShader->shaderInfo.cbBytecode) pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.pvBytecode, pDXShader->shaderInfo.cbBytecode); pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cInputSignature); if (pDXShader->shaderInfo.cInputSignature) pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.aInputSignature, pDXShader->shaderInfo.cInputSignature * sizeof(SVGA3dDXSignatureEntry)); pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cOutputSignature); if (pDXShader->shaderInfo.cOutputSignature) pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.aOutputSignature, pDXShader->shaderInfo.cOutputSignature * sizeof(SVGA3dDXSignatureEntry)); pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cPatchConstantSignature); if (pDXShader->shaderInfo.cPatchConstantSignature) pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.aPatchConstantSignature, pDXShader->shaderInfo.cPatchConstantSignature * sizeof(SVGA3dDXSignatureEntry)); pHlp->pfnSSMPutU32(pSSM, pDXShader->shaderInfo.cDclResource); if (pDXShader->shaderInfo.cDclResource) pHlp->pfnSSMPutMem(pSSM, pDXShader->shaderInfo.aOffDclResource, pDXShader->shaderInfo.cDclResource * sizeof(uint32_t)); } rc = pHlp->pfnSSMPutU32(pSSM, pDXContext->pBackendDXContext->cSOTarget); AssertLogRelRCReturn(rc, rc); return VINF_SUCCESS; } static DECLCALLBACK(int) vmsvga3dBackQueryInterface(PVGASTATECC pThisCC, char const *pszInterfaceName, void *pvInterfaceFuncs, size_t cbInterfaceFuncs) { RT_NOREF(pThisCC); int rc = VINF_SUCCESS; if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_DX) == 0) { if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSDX)) { if (pvInterfaceFuncs) { VMSVGA3DBACKENDFUNCSDX *p = (VMSVGA3DBACKENDFUNCSDX *)pvInterfaceFuncs; p->pfnDXSaveState = vmsvga3dBackDXSaveState; p->pfnDXLoadState = vmsvga3dBackDXLoadState; p->pfnDXDefineContext = vmsvga3dBackDXDefineContext; p->pfnDXDestroyContext = vmsvga3dBackDXDestroyContext; p->pfnDXBindContext = vmsvga3dBackDXBindContext; p->pfnDXSwitchContext = vmsvga3dBackDXSwitchContext; p->pfnDXReadbackContext = vmsvga3dBackDXReadbackContext; p->pfnDXInvalidateContext = vmsvga3dBackDXInvalidateContext; p->pfnDXSetSingleConstantBuffer = vmsvga3dBackDXSetSingleConstantBuffer; p->pfnDXSetShaderResources = vmsvga3dBackDXSetShaderResources; p->pfnDXSetShader = vmsvga3dBackDXSetShader; p->pfnDXSetSamplers = vmsvga3dBackDXSetSamplers; p->pfnDXDraw = vmsvga3dBackDXDraw; p->pfnDXDrawIndexed = vmsvga3dBackDXDrawIndexed; p->pfnDXDrawInstanced = vmsvga3dBackDXDrawInstanced; p->pfnDXDrawIndexedInstanced = vmsvga3dBackDXDrawIndexedInstanced; p->pfnDXDrawAuto = vmsvga3dBackDXDrawAuto; p->pfnDXSetInputLayout = vmsvga3dBackDXSetInputLayout; p->pfnDXSetVertexBuffers = vmsvga3dBackDXSetVertexBuffers; p->pfnDXSetIndexBuffer = vmsvga3dBackDXSetIndexBuffer; p->pfnDXSetTopology = vmsvga3dBackDXSetTopology; p->pfnDXSetRenderTargets = vmsvga3dBackDXSetRenderTargets; p->pfnDXSetBlendState = vmsvga3dBackDXSetBlendState; p->pfnDXSetDepthStencilState = vmsvga3dBackDXSetDepthStencilState; p->pfnDXSetRasterizerState = vmsvga3dBackDXSetRasterizerState; p->pfnDXDefineQuery = vmsvga3dBackDXDefineQuery; p->pfnDXDestroyQuery = vmsvga3dBackDXDestroyQuery; p->pfnDXBeginQuery = vmsvga3dBackDXBeginQuery; p->pfnDXEndQuery = vmsvga3dBackDXEndQuery; p->pfnDXSetPredication = vmsvga3dBackDXSetPredication; p->pfnDXSetSOTargets = vmsvga3dBackDXSetSOTargets; p->pfnDXSetViewports = vmsvga3dBackDXSetViewports; p->pfnDXSetScissorRects = vmsvga3dBackDXSetScissorRects; p->pfnDXClearRenderTargetView = vmsvga3dBackDXClearRenderTargetView; p->pfnDXClearDepthStencilView = vmsvga3dBackDXClearDepthStencilView; p->pfnDXPredCopyRegion = vmsvga3dBackDXPredCopyRegion; p->pfnDXPredCopy = vmsvga3dBackDXPredCopy; p->pfnDXPresentBlt = vmsvga3dBackDXPresentBlt; p->pfnDXGenMips = vmsvga3dBackDXGenMips; p->pfnDXDefineShaderResourceView = vmsvga3dBackDXDefineShaderResourceView; p->pfnDXDestroyShaderResourceView = vmsvga3dBackDXDestroyShaderResourceView; p->pfnDXDefineRenderTargetView = vmsvga3dBackDXDefineRenderTargetView; p->pfnDXDestroyRenderTargetView = vmsvga3dBackDXDestroyRenderTargetView; p->pfnDXDefineDepthStencilView = vmsvga3dBackDXDefineDepthStencilView; p->pfnDXDestroyDepthStencilView = vmsvga3dBackDXDestroyDepthStencilView; p->pfnDXDefineElementLayout = vmsvga3dBackDXDefineElementLayout; p->pfnDXDestroyElementLayout = vmsvga3dBackDXDestroyElementLayout; p->pfnDXDefineBlendState = vmsvga3dBackDXDefineBlendState; p->pfnDXDestroyBlendState = vmsvga3dBackDXDestroyBlendState; p->pfnDXDefineDepthStencilState = vmsvga3dBackDXDefineDepthStencilState; p->pfnDXDestroyDepthStencilState = vmsvga3dBackDXDestroyDepthStencilState; p->pfnDXDefineRasterizerState = vmsvga3dBackDXDefineRasterizerState; p->pfnDXDestroyRasterizerState = vmsvga3dBackDXDestroyRasterizerState; p->pfnDXDefineSamplerState = vmsvga3dBackDXDefineSamplerState; p->pfnDXDestroySamplerState = vmsvga3dBackDXDestroySamplerState; p->pfnDXDefineShader = vmsvga3dBackDXDefineShader; p->pfnDXDestroyShader = vmsvga3dBackDXDestroyShader; p->pfnDXBindShader = vmsvga3dBackDXBindShader; p->pfnDXDefineStreamOutput = vmsvga3dBackDXDefineStreamOutput; p->pfnDXDestroyStreamOutput = vmsvga3dBackDXDestroyStreamOutput; p->pfnDXSetStreamOutput = vmsvga3dBackDXSetStreamOutput; p->pfnDXSetCOTable = vmsvga3dBackDXSetCOTable; p->pfnDXBufferCopy = vmsvga3dBackDXBufferCopy; p->pfnDXSurfaceCopyAndReadback = vmsvga3dBackDXSurfaceCopyAndReadback; p->pfnDXMoveQuery = vmsvga3dBackDXMoveQuery; p->pfnDXBindAllShader = vmsvga3dBackDXBindAllShader; p->pfnDXHint = vmsvga3dBackDXHint; p->pfnDXBufferUpdate = vmsvga3dBackDXBufferUpdate; p->pfnDXCondBindAllShader = vmsvga3dBackDXCondBindAllShader; p->pfnScreenCopy = vmsvga3dBackScreenCopy; p->pfnIntraSurfaceCopy = vmsvga3dBackIntraSurfaceCopy; p->pfnDXResolveCopy = vmsvga3dBackDXResolveCopy; p->pfnDXPredResolveCopy = vmsvga3dBackDXPredResolveCopy; p->pfnDXPredConvertRegion = vmsvga3dBackDXPredConvertRegion; p->pfnDXPredConvert = vmsvga3dBackDXPredConvert; p->pfnWholeSurfaceCopy = vmsvga3dBackWholeSurfaceCopy; p->pfnDXDefineUAView = vmsvga3dBackDXDefineUAView; p->pfnDXDestroyUAView = vmsvga3dBackDXDestroyUAView; p->pfnDXClearUAViewUint = vmsvga3dBackDXClearUAViewUint; p->pfnDXClearUAViewFloat = vmsvga3dBackDXClearUAViewFloat; p->pfnDXCopyStructureCount = vmsvga3dBackDXCopyStructureCount; p->pfnDXSetUAViews = vmsvga3dBackDXSetUAViews; p->pfnDXDrawIndexedInstancedIndirect = vmsvga3dBackDXDrawIndexedInstancedIndirect; p->pfnDXDrawInstancedIndirect = vmsvga3dBackDXDrawInstancedIndirect; p->pfnDXDispatch = vmsvga3dBackDXDispatch; p->pfnDXDispatchIndirect = vmsvga3dBackDXDispatchIndirect; p->pfnWriteZeroSurface = vmsvga3dBackWriteZeroSurface; p->pfnHintZeroSurface = vmsvga3dBackHintZeroSurface; p->pfnDXTransferToBuffer = vmsvga3dBackDXTransferToBuffer; p->pfnLogicOpsBitBlt = vmsvga3dBackLogicOpsBitBlt; p->pfnLogicOpsTransBlt = vmsvga3dBackLogicOpsTransBlt; p->pfnLogicOpsStretchBlt = vmsvga3dBackLogicOpsStretchBlt; p->pfnLogicOpsColorFill = vmsvga3dBackLogicOpsColorFill; p->pfnLogicOpsAlphaBlend = vmsvga3dBackLogicOpsAlphaBlend; p->pfnLogicOpsClearTypeBlend = vmsvga3dBackLogicOpsClearTypeBlend; p->pfnDXSetCSUAViews = vmsvga3dBackDXSetCSUAViews; p->pfnDXSetMinLOD = vmsvga3dBackDXSetMinLOD; p->pfnDXSetShaderIface = vmsvga3dBackDXSetShaderIface; p->pfnSurfaceStretchBltNonMSToMS = vmsvga3dBackSurfaceStretchBltNonMSToMS; p->pfnDXBindShaderIface = vmsvga3dBackDXBindShaderIface; p->pfnVBDXClearRenderTargetViewRegion = vmsvga3dBackVBDXClearRenderTargetViewRegion; } } else { AssertFailed(); rc = VERR_INVALID_PARAMETER; } } else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_MAP) == 0) { if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSMAP)) { if (pvInterfaceFuncs) { VMSVGA3DBACKENDFUNCSMAP *p = (VMSVGA3DBACKENDFUNCSMAP *)pvInterfaceFuncs; p->pfnSurfaceMap = vmsvga3dBackSurfaceMap; p->pfnSurfaceUnmap = vmsvga3dBackSurfaceUnmap; } } else { AssertFailed(); rc = VERR_INVALID_PARAMETER; } } else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_GBO) == 0) { if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSGBO)) { if (pvInterfaceFuncs) { VMSVGA3DBACKENDFUNCSGBO *p = (VMSVGA3DBACKENDFUNCSGBO *)pvInterfaceFuncs; p->pfnScreenTargetBind = vmsvga3dScreenTargetBind; p->pfnScreenTargetUpdate = vmsvga3dScreenTargetUpdate; } } else { AssertFailed(); rc = VERR_INVALID_PARAMETER; } } else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_3D) == 0) { if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCS3D)) { if (pvInterfaceFuncs) { VMSVGA3DBACKENDFUNCS3D *p = (VMSVGA3DBACKENDFUNCS3D *)pvInterfaceFuncs; p->pfnInit = vmsvga3dBackInit; p->pfnPowerOn = vmsvga3dBackPowerOn; p->pfnTerminate = vmsvga3dBackTerminate; p->pfnReset = vmsvga3dBackReset; p->pfnQueryCaps = vmsvga3dBackQueryCaps; p->pfnChangeMode = vmsvga3dBackChangeMode; p->pfnCreateTexture = vmsvga3dBackCreateTexture; p->pfnSurfaceDestroy = vmsvga3dBackSurfaceDestroy; p->pfnSurfaceInvalidateImage = vmsvga3dBackSurfaceInvalidateImage; p->pfnSurfaceCopy = vmsvga3dBackSurfaceCopy; p->pfnSurfaceDMACopyBox = vmsvga3dBackSurfaceDMACopyBox; p->pfnSurfaceStretchBlt = vmsvga3dBackSurfaceStretchBlt; p->pfnUpdateHostScreenViewport = vmsvga3dBackUpdateHostScreenViewport; p->pfnDefineScreen = vmsvga3dBackDefineScreen; p->pfnDestroyScreen = vmsvga3dBackDestroyScreen; p->pfnSurfaceBlitToScreen = vmsvga3dBackSurfaceBlitToScreen; p->pfnSurfaceUpdateHeapBuffers = vmsvga3dBackSurfaceUpdateHeapBuffers; } } else { AssertFailed(); rc = VERR_INVALID_PARAMETER; } } else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_VGPU9) == 0) { if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSVGPU9)) { if (pvInterfaceFuncs) { VMSVGA3DBACKENDFUNCSVGPU9 *p = (VMSVGA3DBACKENDFUNCSVGPU9 *)pvInterfaceFuncs; p->pfnContextDefine = vmsvga3dBackContextDefine; p->pfnContextDestroy = vmsvga3dBackContextDestroy; p->pfnSetTransform = vmsvga3dBackSetTransform; p->pfnSetZRange = vmsvga3dBackSetZRange; p->pfnSetRenderState = vmsvga3dBackSetRenderState; p->pfnSetRenderTarget = vmsvga3dBackSetRenderTarget; p->pfnSetTextureState = vmsvga3dBackSetTextureState; p->pfnSetMaterial = vmsvga3dBackSetMaterial; p->pfnSetLightData = vmsvga3dBackSetLightData; p->pfnSetLightEnabled = vmsvga3dBackSetLightEnabled; p->pfnSetViewPort = vmsvga3dBackSetViewPort; p->pfnSetClipPlane = vmsvga3dBackSetClipPlane; p->pfnCommandClear = vmsvga3dBackCommandClear; p->pfnDrawPrimitives = vmsvga3dBackDrawPrimitives; p->pfnSetScissorRect = vmsvga3dBackSetScissorRect; p->pfnGenerateMipmaps = vmsvga3dBackGenerateMipmaps; p->pfnShaderDefine = vmsvga3dBackShaderDefine; p->pfnShaderDestroy = vmsvga3dBackShaderDestroy; p->pfnShaderSet = vmsvga3dBackShaderSet; p->pfnShaderSetConst = vmsvga3dBackShaderSetConst; p->pfnOcclusionQueryCreate = vmsvga3dBackOcclusionQueryCreate; p->pfnOcclusionQueryDelete = vmsvga3dBackOcclusionQueryDelete; p->pfnOcclusionQueryBegin = vmsvga3dBackOcclusionQueryBegin; p->pfnOcclusionQueryEnd = vmsvga3dBackOcclusionQueryEnd; p->pfnOcclusionQueryGetData = vmsvga3dBackOcclusionQueryGetData; } } else { AssertFailed(); rc = VERR_INVALID_PARAMETER; } } else rc = VERR_NOT_IMPLEMENTED; return rc; } extern VMSVGA3DBACKENDDESC const g_BackendDX = { "DX", vmsvga3dBackQueryInterface };