summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp')
-rw-r--r--src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp10277
1 files changed, 10277 insertions, 0 deletions
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp
new file mode 100644
index 00000000..9802b570
--- /dev/null
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp
@@ -0,0 +1,10277 @@
+/* $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 <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
+#include <VBox/AssertGuest.h>
+#include <VBox/log.h>
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/pgm.h>
+
+#include <iprt/assert.h>
+#include <iprt/avl.h>
+#include <iprt/errcore.h>
+#include <iprt/mem.h>
+
+#include <VBoxVideo.h> /* required by DevVGA.h */
+#include <VBoxVideo3D.h>
+
+/* 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 <d3d11_1.h>
+
+
+#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);
+ }
+ pDevice->pImmediateContext->ClearDepthStencilView(pDXView->u.pDepthStencilView, flags, 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
+};