diff --git a/include/winddk/.gitignore b/include/winddk/.gitignore new file mode 100644 index 00000000000..14e87aa12db --- /dev/null +++ b/include/winddk/.gitignore @@ -0,0 +1,13 @@ +d3d10tokenizedprogramformat.hpp +d3d10umddi.h +d3d11tokenizedprogramformat.hpp +d3dkmddi.h +d3dkmdt.h +d3dkmthk.h +d3dukmdt.h +d3dumddi.h +dxgiddi.h +dxgiformat.h +dxgitype.h +dxmini.h +wmidata.h diff --git a/include/winddk/README.txt b/include/winddk/README.txt new file mode 100644 index 00000000000..a4d4edab260 --- /dev/null +++ b/include/winddk/README.txt @@ -0,0 +1,16 @@ +The gallium d3d10umd statetracker depends upon the follow Windows DDK headers +being placed here: + + d3d10tokenizedprogramformat.hpp + d3d10umddi.h + d3d11tokenizedprogramformat.hpp + d3dkmddi.h + d3dkmdt.h + d3dkmthk.h + d3dukmdt.h + d3dumddi.h + dxgiddi.h + dxgiformat.h + dxgitype.h + dxmini.h + wmidata.h diff --git a/include/winddk/winddk_compat.h b/include/winddk/winddk_compat.h new file mode 100644 index 00000000000..6438a89f71e --- /dev/null +++ b/include/winddk/winddk_compat.h @@ -0,0 +1,236 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * SDK/DDK compatability. + * + * Different headers/defines on different Windows SDKs / DDKs, so define + * all used status here to keep the code portable. + * + * @author + */ + +#ifndef VMW_WDDM_COMPAT_H_ +#define VMW_WDDM_COMPAT_H_ + +#ifndef __in +#define __in /**/ +#endif + +#ifndef __out +#define __out /**/ +#endif + +#ifndef __inout +#define __inout /**/ +#endif + +#ifndef __in_opt +#define __in_opt /**/ +#endif + +#ifndef __inout_opt +#define __inout_opt /**/ +#endif + +#ifndef __ecount +#define __ecount(x) /**/ +#endif + +#ifndef __in_ecount +#define __in_ecount(x) /**/ +#endif + +#ifndef __deref_ecount +#define __deref_ecount(x) /**/ +#endif + +#ifndef __in_bcount +#define __in_bcount(x) /**/ +#endif + +#ifndef __out_bcount +#define __out_bcount(x) /**/ +#endif + +#ifndef __out_ecount_opt +#define __out_ecount_opt(x) /**/ +#endif + +#ifndef __deref_out +#define __deref_out /**/ +#endif + +#ifndef __in_range +#define __in_range(x,y) /**/ +#endif + +#ifndef __field_bcount +#define __field_bcount(x) /**/ +#endif + +#ifndef __out_bcount +#define __out_bcount(x) /**/ +#endif + +#ifndef __out_bcount_full_opt +#define __out_bcount_full_opt(x) /**/ +#endif + +#ifndef __out_ecount_part_z_opt +#define __out_ecount_part_z_opt(x, y) /**/ +#endif + +#ifndef __out_ecount_part_opt +#define __out_ecount_part_opt(x, y) /**/ +#endif + +#ifndef __field_ecount +#define __field_ecount(x) /**/ +#endif + +#ifndef __field_ecount_full +#define __field_ecount_full(x) /**/ +#endif + +#ifndef __checkReturn +#define __checkReturn /**/ +#endif + +#ifndef __drv_requiresIRQL +#define __drv_requiresIRQL(x) /**/ +#endif + +#ifndef __drv_minIRQL +#define __drv_minIRQL(x) /**/ +#endif + +#ifndef __drv_maxIRQL +#define __drv_maxIRQL(x) /**/ +#endif + +#ifdef __MINGW32__ +#define __inline static __inline__ +#endif + +#ifndef EXTERN_C +#define EXTERN_C /**/ +#endif + +#ifdef __MINGW32__ +typedef unsigned char UINT8; +#endif + + +#ifndef NTSTATUS +#define NTSTATUS LONG +#endif + +typedef LARGE_INTEGER PHYSICAL_ADDRESS; + +#ifndef NT_SUCCESS +#define NT_SUCCESS(_status) ((_status) >= 0) +#endif + +#ifndef STATUS_SUCCESS +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +#endif + +#ifndef STATUS_UNSUCCESSFUL +#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) +#endif + +#ifndef STATUS_INVALID_PARAMETER +#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL) +#endif + +#ifndef STATUS_NO_MEMORY +#define STATUS_NO_MEMORY ((NTSTATUS)0xC0000017L) +#endif + +#ifndef STATUS_ILLEGAL_INSTRUCTION +#define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS)0xC000001DL) +#endif + +#ifndef STATUS_BUFFER_TOO_SMALL +#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) +#endif + +#ifndef STATUS_PRIVILEGED_INSTRUCTION +#define STATUS_PRIVILEGED_INSTRUCTION ((NTSTATUS)0xC0000096L) +#endif + +#ifndef STATUS_NOT_SUPPORTED +#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL) +#endif + +#ifndef STATUS_DEVICE_REMOVED +#define STATUS_DEVICE_REMOVED ((NTSTATUS)0xC00002B6L) +#endif + +#ifndef STATUS_INVALID_USER_BUFFER +#define STATUS_INVALID_USER_BUFFER ((NTSTATUS)0xC00000E8L) +#endif + +#ifndef STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER +#define STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER ((NTSTATUS)0xC01E0000L) +#endif + +#ifndef STATUS_NO_VIDEO_MEMORY +#define STATUS_NO_VIDEO_MEMORY ((NTSTATUS)0xC01E0100L) +#endif + +#ifndef STATUS_GRAPHICS_ALLOCATION_BUSY +#define STATUS_GRAPHICS_ALLOCATION_BUSY ((NTSTATUS)0xC01E0102L) +#endif + +#ifndef STATUS_GRAPHICS_TOO_MANY_REFERENCES +#define STATUS_GRAPHICS_TOO_MANY_REFERENCES ((NTSTATUS)0xC01E0103L) +#endif + +#ifndef STATUS_GRAPHICS_ALLOCATION_INVALID +#define STATUS_GRAPHICS_ALLOCATION_INVALID ((NTSTATUS)0xC01E0106L) +#endif + +#ifndef STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION +#define STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION ((NTSTATUS)0xC01E0109L) +#endif + +#ifndef STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION +#define STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION ((NTSTATUS)0xC01E0111L) +#endif + +#ifndef STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE +#define STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE ((NTSTATUS)0xC01E0200L) +#endif + +#ifndef STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET +#define STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET ((NTSTATUS)0xC01E0333L) +#endif + +#endif /* VMW_WDDM_COMPAT_H_ */ diff --git a/meson.build b/meson.build index 78a763e2781..cfe011f0ca4 100644 --- a/meson.build +++ b/meson.build @@ -787,6 +787,12 @@ if with_gallium_st_nine error('Using nine with wine requires dri3') endif endif +with_gallium_st_d3d10umd = get_option('gallium-d3d10umd') +if with_gallium_st_d3d10umd + if not with_gallium_softpipe + error('The d3d10umd state tracker requires gallium softpipe/llvmpipe.') + endif +endif _power8 = get_option('power8') if _power8 == 'true' _power8 = 'enabled' diff --git a/meson_options.txt b/meson_options.txt index b5e51de5a14..fa6a9809e11 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -142,6 +142,12 @@ option( value : false, description : 'build gallium "nine" Direct3D 9.x frontend.', ) +option( + 'gallium-d3d10umd', + type : 'boolean', + value : false, + description : 'build gallium D3D10 WDDM UMD frontend.', +) option( 'gallium-opencl', type : 'combo', diff --git a/src/gallium/frontends/d3d10umd/Adapter.cpp b/src/gallium/frontends/d3d10umd/Adapter.cpp new file mode 100644 index 00000000000..510c3466832 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Adapter.cpp @@ -0,0 +1,274 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Adpater.cpp -- + * Driver entry point. + */ + + +#include "DriverIncludes.h" +#include "Device.h" +#include "State.h" + +#include "Debug.h" + +#include "util/u_memory.h" + + +EXTERN_C struct pipe_screen * +d3d10_create_screen(void); + + +static HRESULT APIENTRY CloseAdapter(D3D10DDI_HADAPTER hAdapter); + +static unsigned long numAdapters = 0; +#if 0 +static unsigned long memdbg_no = 0; +#endif + +/* + * ---------------------------------------------------------------------- + * + * OpenAdapterCommon -- + * + * Common code for OpenAdapter10 and OpenAdapter10_2 + * + * ---------------------------------------------------------------------- + */ + + +static HRESULT +OpenAdapterCommon(__inout D3D10DDIARG_OPENADAPTER *pOpenData) // IN +{ +#if 0 + if (numAdapters == 0) { + memdbg_no = debug_memory_begin(); + } +#endif + ++numAdapters; + + Adapter *pAdaptor = (Adapter *)calloc(sizeof *pAdaptor, 1); + if (!pAdaptor) { + --numAdapters; + return E_OUTOFMEMORY; + } + + pAdaptor->screen = d3d10_create_screen(); + if (!pAdaptor->screen) { + free(pAdaptor); + --numAdapters; + return E_OUTOFMEMORY; + } + + pOpenData->hAdapter.pDrvPrivate = pAdaptor; + + pOpenData->pAdapterFuncs->pfnCalcPrivateDeviceSize = CalcPrivateDeviceSize; + pOpenData->pAdapterFuncs->pfnCreateDevice = CreateDevice; + pOpenData->pAdapterFuncs->pfnCloseAdapter = CloseAdapter; + + return S_OK; +} + + +/* + * ---------------------------------------------------------------------- + * + * OpenAdapter10 -- + * + * The OpenAdapter10 function creates a graphics adapter object + * that is referenced in subsequent calls. + * + * ---------------------------------------------------------------------- + */ + + +EXTERN_C HRESULT APIENTRY +OpenAdapter10(__inout D3D10DDIARG_OPENADAPTER *pOpenData) // IN +{ + LOG_ENTRYPOINT(); + + /* + * This is checked here and not on the common code because MSDN docs + * state that it should be ignored on OpenAdapter10_2. + */ + switch (pOpenData->Interface) { + case D3D10_0_DDI_INTERFACE_VERSION: + case D3D10_0_x_DDI_INTERFACE_VERSION: + case D3D10_0_7_DDI_INTERFACE_VERSION: +#if SUPPORT_D3D10_1 + case D3D10_1_DDI_INTERFACE_VERSION: + case D3D10_1_x_DDI_INTERFACE_VERSION: + case D3D10_1_7_DDI_INTERFACE_VERSION: +#endif +#if SUPPORT_D3D11 + case D3D11_0_DDI_INTERFACE_VERSION: + case D3D11_0_7_DDI_INTERFACE_VERSION: +#endif + break; + default: + if (0) { + DebugPrintf("%s: unsupported interface version 0x%08x\n", + __FUNCTION__, pOpenData->Interface); + } + return E_FAIL; + } + + return OpenAdapterCommon(pOpenData); +} + + +static const UINT64 +SupportedDDIInterfaceVersions[] = { + D3D10_0_DDI_SUPPORTED, + D3D10_0_x_DDI_SUPPORTED, + D3D10_0_7_DDI_SUPPORTED, +#if SUPPORT_D3D10_1 + D3D10_1_DDI_SUPPORTED, + D3D10_1_x_DDI_SUPPORTED, + D3D10_1_7_DDI_SUPPORTED, +#endif +#if SUPPORT_D3D11 + D3D11_0_DDI_SUPPORTED, + D3D11_0_7_DDI_SUPPORTED, +#endif +}; + + +/* + * ---------------------------------------------------------------------- + * + * GetSupportedVersions -- + * + * Return a list of interface versions supported by the graphics + * adapter. + * + * ---------------------------------------------------------------------- + */ + +static HRESULT APIENTRY +GetSupportedVersions(D3D10DDI_HADAPTER hAdapter, + UINT32 *puEntries, + UINT64 *pSupportedDDIInterfaceVersions) +{ + LOG_ENTRYPOINT(); + + if (pSupportedDDIInterfaceVersions && + *puEntries < ARRAYSIZE(SupportedDDIInterfaceVersions)) { + return E_OUTOFMEMORY; + } + + *puEntries = ARRAYSIZE(SupportedDDIInterfaceVersions); + + if (pSupportedDDIInterfaceVersions) { + memcpy(pSupportedDDIInterfaceVersions, + SupportedDDIInterfaceVersions, + sizeof SupportedDDIInterfaceVersions); + } + + return S_OK; +} + + +/* + * ---------------------------------------------------------------------- + * + * GetCaps -- + * + * Return the capabilities of the graphics adapter. + * + * ---------------------------------------------------------------------- + */ + +static HRESULT APIENTRY +GetCaps(D3D10DDI_HADAPTER hAdapter, + const D3D10_2DDIARG_GETCAPS *pData) +{ + LOG_ENTRYPOINT(); + memset(pData->pData, 0, pData->DataSize); + return S_OK; +} + + +/* + * ---------------------------------------------------------------------- + * + * OpenAdapter10 -- + * + * The OpenAdapter10 function creates a graphics adapter object + * that is referenced in subsequent calls. + * + * ---------------------------------------------------------------------- + */ + + +EXTERN_C HRESULT APIENTRY +OpenAdapter10_2(__inout D3D10DDIARG_OPENADAPTER *pOpenData) // IN +{ + LOG_ENTRYPOINT(); + + HRESULT hr = OpenAdapterCommon(pOpenData); + + if (SUCCEEDED(hr)) { + pOpenData->pAdapterFuncs_2->pfnGetSupportedVersions = GetSupportedVersions; + pOpenData->pAdapterFuncs_2->pfnGetCaps = GetCaps; + } + + return hr; +} + + +/* + * ---------------------------------------------------------------------- + * + * CloseAdapter -- + * + * The CloseAdapter function releases resources for a + * graphics adapter object. + * + * ---------------------------------------------------------------------- + */ + +HRESULT APIENTRY +CloseAdapter(D3D10DDI_HADAPTER hAdapter) // IN +{ + LOG_ENTRYPOINT(); + + Adapter *pAdapter = CastAdapter(hAdapter); + struct pipe_screen *screen = pAdapter->screen; + screen->destroy(screen); + free(pAdapter); + + --numAdapters; +#if 0 + if (numAdapters == 0) { + debug_memory_end(memdbg_no); + } +#endif + + return S_OK; +} diff --git a/src/gallium/frontends/d3d10umd/D3DKMT.cpp b/src/gallium/frontends/d3d10umd/D3DKMT.cpp new file mode 100644 index 00000000000..1649eddc41e --- /dev/null +++ b/src/gallium/frontends/d3d10umd/D3DKMT.cpp @@ -0,0 +1,728 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * D3DKMT.cpp -- + * Implement kernel mode thunks, so that this can be loaded as a + * software DLL (D3D_DRIVER_TYPE_SOFTWARE). + */ + + +#include "DriverIncludes.h" + +#include "Debug.h" + + +#ifndef STATUS_NOT_IMPLEMENTED +#define STATUS_NOT_IMPLEMENTED 0xC0000002 +#endif + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCreateAllocation(D3DKMT_CREATEALLOCATION *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCreateAllocation2(D3DKMT_CREATEALLOCATION *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTQueryResourceInfo(D3DKMT_QUERYRESOURCEINFO *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTOpenResource(D3DKMT_OPENRESOURCE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTOpenResource2(D3DKMT_OPENRESOURCE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTDestroyAllocation(CONST D3DKMT_DESTROYALLOCATION *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSetAllocationPriority(CONST D3DKMT_SETALLOCATIONPRIORITY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTQueryAllocationResidency(CONST D3DKMT_QUERYALLOCATIONRESIDENCY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCreateDevice(D3DKMT_CREATEDEVICE *pData) +{ + LOG_ENTRYPOINT(); + pData->hDevice = 1; + return STATUS_SUCCESS; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTDestroyDevice(CONST D3DKMT_DESTROYDEVICE *pData) +{ + LOG_ENTRYPOINT(); + return STATUS_SUCCESS; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCreateContext(D3DKMT_CREATECONTEXT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTDestroyContext(CONST D3DKMT_DESTROYCONTEXT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCreateSynchronizationObject(D3DKMT_CREATESYNCHRONIZATIONOBJECT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCreateSynchronizationObject2(D3DKMT_CREATESYNCHRONIZATIONOBJECT2 *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTOpenSynchronizationObject(D3DKMT_OPENSYNCHRONIZATIONOBJECT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTDestroySynchronizationObject(CONST D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTWaitForSynchronizationObject(CONST D3DKMT_WAITFORSYNCHRONIZATIONOBJECT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTWaitForSynchronizationObject2(CONST D3DKMT_WAITFORSYNCHRONIZATIONOBJECT2 *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSignalSynchronizationObject(CONST D3DKMT_SIGNALSYNCHRONIZATIONOBJECT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSignalSynchronizationObject2(CONST D3DKMT_SIGNALSYNCHRONIZATIONOBJECT2 *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTLock(D3DKMT_LOCK *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTUnlock(CONST D3DKMT_UNLOCK *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetDisplayModeList(D3DKMT_GETDISPLAYMODELIST *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSetDisplayMode(CONST D3DKMT_SETDISPLAYMODE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetMultisampleMethodList(D3DKMT_GETMULTISAMPLEMETHODLIST *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTPresent(CONST D3DKMT_PRESENT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTRender(D3DKMT_RENDER *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetRuntimeData(CONST D3DKMT_GETRUNTIMEDATA *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTQueryAdapterInfo(CONST D3DKMT_QUERYADAPTERINFO *pData) +{ + LOG_ENTRYPOINT(); + + switch (pData->Type) { + case KMTQAITYPE_UMDRIVERNAME: + { + D3DKMT_UMDFILENAMEINFO *pResult = + (D3DKMT_UMDFILENAMEINFO *)pData->pPrivateDriverData; + if (pResult->Version != KMTUMDVERSION_DX10 && + pResult->Version != KMTUMDVERSION_DX11) { + DebugPrintf("%s: unsupported UMD version (%u)\n", + __FUNCTION__, pResult->Version); + return STATUS_INVALID_PARAMETER; + } + HMODULE hModule = 0; + BOOL bRet; + DWORD dwRet; + bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCTSTR)D3DKMTQueryAdapterInfo, + &hModule); + assert(bRet); + dwRet = GetModuleFileNameW(hModule, pResult->UmdFileName, MAX_PATH); + assert(dwRet); + return STATUS_SUCCESS; + } + break; + case KMTQAITYPE_GETSEGMENTSIZE: + { + D3DKMT_SEGMENTSIZEINFO *pResult = + (D3DKMT_SEGMENTSIZEINFO *)pData->pPrivateDriverData; + pResult->DedicatedVideoMemorySize = 0; + pResult->DedicatedSystemMemorySize = 0; + pResult->SharedSystemMemorySize = 3ULL*1024ULL*1024ULL*1024ULL; + return STATUS_SUCCESS; + } + break; + case KMTQAITYPE_CHECKDRIVERUPDATESTATUS: + { + BOOL *pResult = (BOOL *)pData->pPrivateDriverData; + *pResult = FALSE; + return STATUS_SUCCESS; + } + case KMTQAITYPE_DRIVERVERSION: + { + D3DKMT_DRIVERVERSION *pResult = (D3DKMT_DRIVERVERSION *)pData->pPrivateDriverData; + *pResult = KMT_DRIVERVERSION_WDDM_1_0; + return STATUS_SUCCESS; + } + case KMTQAITYPE_XBOX: + { + BOOL *pResult = (BOOL *)pData->pPrivateDriverData; + *pResult = FALSE; + return STATUS_SUCCESS; + } + case KMTQAITYPE_PHYSICALADAPTERCOUNT: + { + UINT *pResult = (UINT *)pData->pPrivateDriverData; + *pResult = 1; + return STATUS_SUCCESS; + } + case KMTQAITYPE_PHYSICALADAPTERDEVICEIDS: + ZeroMemory(pData->pPrivateDriverData, pData->PrivateDriverDataSize); + return STATUS_SUCCESS; + default: + DebugPrintf("%s: unsupported query type (Type=%u, PrivateDriverDataSize=%u)\n", + __FUNCTION__, pData->Type, pData->PrivateDriverDataSize); + ZeroMemory(pData->pPrivateDriverData, pData->PrivateDriverDataSize); + return STATUS_NOT_IMPLEMENTED; + } +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTOpenAdapterFromHdc(D3DKMT_OPENADAPTERFROMHDC *pData) +{ + LOG_ENTRYPOINT(); + pData->hAdapter = 1; + pData->AdapterLuid.LowPart = 0; + pData->AdapterLuid.HighPart = 0; + pData->VidPnSourceId = 1; + return STATUS_SUCCESS; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTOpenAdapterFromGdiDisplayName(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *pData) +{ + LOG_ENTRYPOINT(); + pData->hAdapter = 1; + pData->AdapterLuid.LowPart = 0; + pData->AdapterLuid.HighPart = 0; + pData->VidPnSourceId = 1; + return STATUS_SUCCESS; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTOpenAdapterFromDeviceName(D3DKMT_OPENADAPTERFROMDEVICENAME *pData) +{ + LOG_ENTRYPOINT(); + pData->hAdapter = 1; + pData->AdapterLuid.LowPart = 0; + pData->AdapterLuid.HighPart = 0; + return STATUS_SUCCESS; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCloseAdapter(CONST D3DKMT_CLOSEADAPTER *pData) +{ + LOG_ENTRYPOINT(); + return STATUS_SUCCESS; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetSharedPrimaryHandle(D3DKMT_GETSHAREDPRIMARYHANDLE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTEscape(CONST D3DKMT_ESCAPE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSetVidPnSourceOwner(CONST D3DKMT_SETVIDPNSOURCEOWNER *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSetVidPnSourceOwner1(const void *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetPresentHistory(D3DKMT_GETPRESENTHISTORY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetPresentQueueEvent(D3DKMT_HANDLE hAdapter, HANDLE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCreateOverlay(D3DKMT_CREATEOVERLAY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTUpdateOverlay(CONST D3DKMT_UPDATEOVERLAY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTFlipOverlay(CONST D3DKMT_FLIPOVERLAY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTDestroyOverlay(CONST D3DKMT_DESTROYOVERLAY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTWaitForVerticalBlankEvent(CONST D3DKMT_WAITFORVERTICALBLANKEVENT *pData) +{ + LOG_ENTRYPOINT(); + return STATUS_SUCCESS; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSetGammaRamp(CONST D3DKMT_SETGAMMARAMP *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetDeviceState(D3DKMT_GETDEVICESTATE *pData) +{ + LOG_ENTRYPOINT(); + switch (pData->StateType) { + case D3DKMT_DEVICESTATE_EXECUTION: + pData->ExecutionState = D3DKMT_DEVICEEXECUTION_ACTIVE; + return STATUS_SUCCESS; + case D3DKMT_DEVICESTATE_PRESENT: + pData->PresentState.PresentStats.PresentCount = 0; + pData->PresentState.PresentStats.PresentRefreshCount = 0; + pData->PresentState.PresentStats.SyncRefreshCount = 0; + pData->PresentState.PresentStats.SyncQPCTime.QuadPart = 0; + pData->PresentState.PresentStats.SyncGPUTime.QuadPart = 0; + return STATUS_SUCCESS; + case D3DKMT_DEVICESTATE_RESET: + pData->ResetState.Value = 0; + return STATUS_SUCCESS; + default: + return STATUS_INVALID_PARAMETER; + } +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCreateDCFromMemory(D3DKMT_CREATEDCFROMMEMORY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTDestroyDCFromMemory(CONST D3DKMT_DESTROYDCFROMMEMORY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSetContextSchedulingPriority(CONST D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetContextSchedulingPriority(D3DKMT_GETCONTEXTSCHEDULINGPRIORITY *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSetProcessSchedulingPriorityClass(HANDLE hProcess, D3DKMT_SCHEDULINGPRIORITYCLASS Priority) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetProcessSchedulingPriorityClass(HANDLE hProcess, D3DKMT_SCHEDULINGPRIORITYCLASS *pPriority) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTReleaseProcessVidPnSourceOwners(HANDLE hProcess) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetScanLine(D3DKMT_GETSCANLINE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTChangeSurfacePointer(CONST D3DKMT_CHANGESURFACEPOINTER *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSetQueuedLimit(CONST D3DKMT_SETQUEUEDLIMIT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTPollDisplayChildren(CONST D3DKMT_POLLDISPLAYCHILDREN *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTInvalidateActiveVidPn(CONST D3DKMT_INVALIDATEACTIVEVIDPN *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCheckOcclusion(CONST D3DKMT_CHECKOCCLUSION *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTWaitForIdle(CONST D3DKMT_WAITFORIDLE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCheckMonitorPowerState(CONST D3DKMT_CHECKMONITORPOWERSTATE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C BOOLEAN APIENTRY +D3DKMTCheckExclusiveOwnership(VOID) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return FALSE; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCheckVidPnExclusiveOwnership(CONST D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSetDisplayPrivateDriverFormat(CONST D3DKMT_SETDISPLAYPRIVATEDRIVERFORMAT *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSharedPrimaryLockNotification(CONST D3DKMT_SHAREDPRIMARYLOCKNOTIFICATION *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTSharedPrimaryUnLockNotification(CONST D3DKMT_SHAREDPRIMARYUNLOCKNOTIFICATION *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCreateKeyedMutex(D3DKMT_CREATEKEYEDMUTEX *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTOpenKeyedMutex(D3DKMT_OPENKEYEDMUTEX *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTDestroyKeyedMutex(CONST D3DKMT_DESTROYKEYEDMUTEX *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTAcquireKeyedMutex(D3DKMT_ACQUIREKEYEDMUTEX *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTReleaseKeyedMutex(D3DKMT_RELEASEKEYEDMUTEX *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTConfigureSharedResource(CONST D3DKMT_CONFIGURESHAREDRESOURCE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTGetOverlayState(D3DKMT_GETOVERLAYSTATE *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} + + +EXTERN_C NTSTATUS APIENTRY +D3DKMTCheckSharedResourceAccess(CONST D3DKMT_CHECKSHAREDRESOURCEACCESS *pData) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + return STATUS_NOT_IMPLEMENTED; +} diff --git a/src/gallium/frontends/d3d10umd/Debug.cpp b/src/gallium/frontends/d3d10umd/Debug.cpp new file mode 100644 index 00000000000..2b810f41d8f --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Debug.cpp @@ -0,0 +1,81 @@ +#include "Debug.h" + +#include +#include + + +#ifdef DEBUG + +unsigned st_debug = 0; + +static const +struct debug_named_value st_debug_flags[] = { + {"oldtexops", ST_DEBUG_OLD_TEX_OPS, "oldtexops"}, + {"tgsi", ST_DEBUG_TGSI, "tgsi"}, + {NULL, 0, NULL}, +}; +void +st_debug_parse(void) +{ + st_debug = debug_get_flags_option("ST_DEBUG", st_debug_flags, st_debug); +} + +#endif + + +void +DebugPrintf(const char *format, ...) +{ + char buf[4096]; + + va_list ap; + va_start(ap, format); + vsnprintf(buf, sizeof buf, format, ap); + va_end(ap); + + OutputDebugStringA(buf); +} + + +/** + * Produce a human readable message from HRESULT. + * + * @sa http://msdn.microsoft.com/en-us/library/ms679351(VS.85).aspx + */ +void +CheckHResult(HRESULT hr, const char *function, unsigned line) +{ + if (FAILED(hr)) { + LPSTR lpMessageBuffer = NULL; + + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&lpMessageBuffer, + 0, + NULL); + + DebugPrintf("%s: %u: 0x%08lX: %s", function, line, hr, lpMessageBuffer); + + LocalFree(lpMessageBuffer); + } +} + + +void +AssertFail(const char *expr, + const char *file, + unsigned line, + const char *function) +{ + DebugPrintf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr); +#if defined(__GNUC__) + __asm("int3"); +#elif defined(_MSC_VER) + __debugbreak(); +#else + DebugBreak(); +#endif +} diff --git a/src/gallium/frontends/d3d10umd/Debug.h b/src/gallium/frontends/d3d10umd/Debug.h new file mode 100644 index 00000000000..5972697c0dc --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Debug.h @@ -0,0 +1,72 @@ +#pragma once + +#include "DriverIncludes.h" +#include "util/u_debug.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ST_DEBUG_OLD_TEX_OPS (1 << 0) +#define ST_DEBUG_TGSI (1 << 1) + + +#ifdef DEBUG +extern unsigned st_debug; +#else +#define st_debug 0 +#endif + + +#ifdef DEBUG +void st_debug_parse(void); +#else +#define st_debug_parse() ((void)0) +#endif + + +void +DebugPrintf(const char *format, ...); + + +void +CheckHResult(HRESULT hr, const char *function, unsigned line); + + +#define CHECK_NTSTATUS(status) \ + CheckNTStatus(status, __FUNCTION__, __LINE__) + + +#define CHECK_HRESULT(hr) \ + CheckHResult(hr, __FUNCTION__, __LINE__) + + +void +AssertFail(const char *expr, const char *file, unsigned line, const char *function); + + +#ifndef NDEBUG +#define ASSERT(expr) ((expr) ? (void)0 : AssertFail(#expr, __FILE__, __LINE__, __FUNCTION__)) +#else +#define ASSERT(expr) do { } while (0 && (expr)) +#endif + + +#if 0 && !defined(NDEBUG) +#define LOG_ENTRYPOINT() DebugPrintf("%s\n", __FUNCTION__) +#else +#define LOG_ENTRYPOINT() (void)0 +#endif + +#define LOG_UNSUPPORTED_ENTRYPOINT() DebugPrintf("%s XXX\n", __FUNCTION__) + +#define LOG_UNSUPPORTED(expr) \ + do { if (expr) DebugPrintf("%s:%d XXX %s\n", __FUNCTION__, __LINE__, #expr); } while(0) + + +#ifdef __cplusplus +} +#endif + diff --git a/src/gallium/frontends/d3d10umd/Device.cpp b/src/gallium/frontends/d3d10umd/Device.cpp new file mode 100644 index 00000000000..ecb2578a672 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Device.cpp @@ -0,0 +1,725 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Device.cpp -- + * Functions that provide the 3D device functionality. + */ + + +#include "Draw.h" +#include "Dxgi.h" +#include "InputAssembly.h" +#include "OutputMerger.h" +#include "Query.h" +#include "Rasterizer.h" +#include "Resource.h" +#include "Shader.h" +#include "State.h" +#include "Format.h" + +#include "Debug.h" + +#include "util/u_sampler.h" + + +static void APIENTRY DestroyDevice(D3D10DDI_HDEVICE hDevice); +static void APIENTRY RelocateDeviceFuncs(D3D10DDI_HDEVICE hDevice, + __in struct D3D10DDI_DEVICEFUNCS *pDeviceFunctions); +static void APIENTRY RelocateDeviceFuncs1(D3D10DDI_HDEVICE hDevice, + __in struct D3D10_1DDI_DEVICEFUNCS *pDeviceFunctions); +static void APIENTRY Flush(D3D10DDI_HDEVICE hDevice); +static void APIENTRY CheckFormatSupport(D3D10DDI_HDEVICE hDevice, DXGI_FORMAT Format, + __out UINT *pFormatCaps); +static void APIENTRY CheckMultisampleQualityLevels(D3D10DDI_HDEVICE hDevice, + DXGI_FORMAT Format, + UINT SampleCount, + __out UINT *pNumQualityLevels); +static void APIENTRY SetTextFilterSize(D3D10DDI_HDEVICE hDevice, UINT Width, UINT Height); + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateDeviceSize -- + * + * The CalcPrivateDeviceSize function determines the size of a memory + * region that the user-mode display driver requires from the Microsoft + * Direct3D runtime to store frequently-accessed data. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateDeviceSize(D3D10DDI_HADAPTER hAdapter, // IN + __in const D3D10DDIARG_CALCPRIVATEDEVICESIZE *pData) // IN +{ + return sizeof(Device); +} + +/* + * ---------------------------------------------------------------------- + * + * CreateDevice -- + * + * The CreateDevice function creates a graphics context that is + * referenced in subsequent calls. + * + * ---------------------------------------------------------------------- + */ + +HRESULT APIENTRY +CreateDevice(D3D10DDI_HADAPTER hAdapter, // IN + __in D3D10DDIARG_CREATEDEVICE *pCreateData) // IN +{ + LOG_ENTRYPOINT(); + + if (0) { + DebugPrintf("hAdapter = %p\n", hAdapter); + DebugPrintf("pKTCallbacks = %p\n", pCreateData->pKTCallbacks); + DebugPrintf("p10_1DeviceFuncs = %p\n", pCreateData->p10_1DeviceFuncs); + DebugPrintf("hDrvDevice = %p\n", pCreateData->hDrvDevice); + DebugPrintf("DXGIBaseDDI = %p\n", pCreateData->DXGIBaseDDI); + DebugPrintf("hRTCoreLayer = %p\n", pCreateData->hRTCoreLayer); + DebugPrintf("pUMCallbacks = %p\n", pCreateData->pUMCallbacks); + } + + switch (pCreateData->Interface) { + case D3D10_0_DDI_INTERFACE_VERSION: + case D3D10_0_x_DDI_INTERFACE_VERSION: + case D3D10_0_7_DDI_INTERFACE_VERSION: +#if SUPPORT_D3D10_1 + case D3D10_1_DDI_INTERFACE_VERSION: + case D3D10_1_x_DDI_INTERFACE_VERSION: + case D3D10_1_7_DDI_INTERFACE_VERSION: +#endif + break; + default: + DebugPrintf("%s: unsupported interface version 0x%08x\n", + __FUNCTION__, pCreateData->Interface); + return E_FAIL; + } + + Adapter *pAdapter = CastAdapter(hAdapter); + + Device *pDevice = CastDevice(pCreateData->hDrvDevice); + memset(pDevice, 0, sizeof *pDevice); + + struct pipe_screen *screen = pAdapter->screen; + struct pipe_context *pipe = screen->context_create(screen, NULL, 0); + pDevice->pipe = pipe; + + pDevice->empty_vs = CreateEmptyShader(pDevice, PIPE_SHADER_VERTEX); + pDevice->empty_fs = CreateEmptyShader(pDevice, PIPE_SHADER_FRAGMENT); + + pipe->bind_vs_state(pipe, pDevice->empty_vs); + pipe->bind_fs_state(pipe, pDevice->empty_fs); + + pDevice->max_dual_source_render_targets = + screen->get_param(screen, PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS); + + pDevice->hRTCoreLayer = pCreateData->hRTCoreLayer; + pDevice->hDevice = (HANDLE)pCreateData->hRTDevice.handle; + pDevice->KTCallbacks = *pCreateData->pKTCallbacks; + pDevice->UMCallbacks = *pCreateData->pUMCallbacks; + pDevice->pDXGIBaseCallbacks = pCreateData->DXGIBaseDDI.pDXGIBaseCallbacks; + + pDevice->draw_so_target = NULL; + + if (0) { + DebugPrintf("pDevice = %p\n", pDevice); + } + + st_debug_parse(); + + /* + * Fill in the D3D10 DDI functions + */ + switch (pCreateData->Interface) { + case D3D10_0_DDI_INTERFACE_VERSION: + case D3D10_0_x_DDI_INTERFACE_VERSION: + case D3D10_0_7_DDI_INTERFACE_VERSION: + pCreateData->pDeviceFuncs->pfnDefaultConstantBufferUpdateSubresourceUP = + ResourceUpdateSubResourceUP; + pCreateData->pDeviceFuncs->pfnVsSetConstantBuffers = VsSetConstantBuffers; + pCreateData->pDeviceFuncs->pfnPsSetShaderResources = PsSetShaderResources; + pCreateData->pDeviceFuncs->pfnPsSetShader = PsSetShader; + pCreateData->pDeviceFuncs->pfnPsSetSamplers = PsSetSamplers; + pCreateData->pDeviceFuncs->pfnVsSetShader = VsSetShader; + pCreateData->pDeviceFuncs->pfnDrawIndexed = DrawIndexed; + pCreateData->pDeviceFuncs->pfnDraw = Draw; + pCreateData->pDeviceFuncs->pfnDynamicIABufferMapNoOverwrite = + ResourceMap; + pCreateData->pDeviceFuncs->pfnDynamicIABufferUnmap = ResourceUnmap; + pCreateData->pDeviceFuncs->pfnDynamicConstantBufferMapDiscard = + ResourceMap; + pCreateData->pDeviceFuncs->pfnDynamicIABufferMapDiscard = + ResourceMap; + pCreateData->pDeviceFuncs->pfnDynamicConstantBufferUnmap = + ResourceUnmap; + pCreateData->pDeviceFuncs->pfnPsSetConstantBuffers = PsSetConstantBuffers; + pCreateData->pDeviceFuncs->pfnIaSetInputLayout = IaSetInputLayout; + pCreateData->pDeviceFuncs->pfnIaSetVertexBuffers = IaSetVertexBuffers; + pCreateData->pDeviceFuncs->pfnIaSetIndexBuffer = IaSetIndexBuffer; + pCreateData->pDeviceFuncs->pfnDrawIndexedInstanced = DrawIndexedInstanced; + pCreateData->pDeviceFuncs->pfnDrawInstanced = DrawInstanced; + pCreateData->pDeviceFuncs->pfnDynamicResourceMapDiscard = + ResourceMap; + pCreateData->pDeviceFuncs->pfnDynamicResourceUnmap = ResourceUnmap; + pCreateData->pDeviceFuncs->pfnGsSetConstantBuffers = GsSetConstantBuffers; + pCreateData->pDeviceFuncs->pfnGsSetShader = GsSetShader; + pCreateData->pDeviceFuncs->pfnIaSetTopology = IaSetTopology; + pCreateData->pDeviceFuncs->pfnStagingResourceMap = ResourceMap; + pCreateData->pDeviceFuncs->pfnStagingResourceUnmap = ResourceUnmap; + pCreateData->pDeviceFuncs->pfnVsSetShaderResources = VsSetShaderResources; + pCreateData->pDeviceFuncs->pfnVsSetSamplers = VsSetSamplers; + pCreateData->pDeviceFuncs->pfnGsSetShaderResources = GsSetShaderResources; + pCreateData->pDeviceFuncs->pfnGsSetSamplers = GsSetSamplers; + pCreateData->pDeviceFuncs->pfnSetRenderTargets = SetRenderTargets; + pCreateData->pDeviceFuncs->pfnShaderResourceViewReadAfterWriteHazard = + ShaderResourceViewReadAfterWriteHazard; + pCreateData->pDeviceFuncs->pfnResourceReadAfterWriteHazard = + ResourceReadAfterWriteHazard; + pCreateData->pDeviceFuncs->pfnSetBlendState = SetBlendState; + pCreateData->pDeviceFuncs->pfnSetDepthStencilState = SetDepthStencilState; + pCreateData->pDeviceFuncs->pfnSetRasterizerState = SetRasterizerState; + pCreateData->pDeviceFuncs->pfnQueryEnd = QueryEnd; + pCreateData->pDeviceFuncs->pfnQueryBegin = QueryBegin; + pCreateData->pDeviceFuncs->pfnResourceCopyRegion = ResourceCopyRegion; + pCreateData->pDeviceFuncs->pfnResourceUpdateSubresourceUP = + ResourceUpdateSubResourceUP; + pCreateData->pDeviceFuncs->pfnSoSetTargets = SoSetTargets; + pCreateData->pDeviceFuncs->pfnDrawAuto = DrawAuto; + pCreateData->pDeviceFuncs->pfnSetViewports = SetViewports; + pCreateData->pDeviceFuncs->pfnSetScissorRects = SetScissorRects; + pCreateData->pDeviceFuncs->pfnClearRenderTargetView = ClearRenderTargetView; + pCreateData->pDeviceFuncs->pfnClearDepthStencilView = ClearDepthStencilView; + pCreateData->pDeviceFuncs->pfnSetPredication = SetPredication; + pCreateData->pDeviceFuncs->pfnQueryGetData = QueryGetData; + pCreateData->pDeviceFuncs->pfnFlush = Flush; + pCreateData->pDeviceFuncs->pfnGenMips = GenMips; + pCreateData->pDeviceFuncs->pfnResourceCopy = ResourceCopy; + pCreateData->pDeviceFuncs->pfnResourceResolveSubresource = + ResourceResolveSubResource; + pCreateData->pDeviceFuncs->pfnResourceMap = ResourceMap; + pCreateData->pDeviceFuncs->pfnResourceUnmap = ResourceUnmap; + pCreateData->pDeviceFuncs->pfnResourceIsStagingBusy = ResourceIsStagingBusy; + pCreateData->pDeviceFuncs->pfnRelocateDeviceFuncs = RelocateDeviceFuncs; + pCreateData->pDeviceFuncs->pfnCalcPrivateResourceSize = + CalcPrivateResourceSize; + pCreateData->pDeviceFuncs->pfnCalcPrivateOpenedResourceSize = + CalcPrivateOpenedResourceSize; + pCreateData->pDeviceFuncs->pfnCreateResource = CreateResource; + pCreateData->pDeviceFuncs->pfnOpenResource = OpenResource; + pCreateData->pDeviceFuncs->pfnDestroyResource = DestroyResource; + pCreateData->pDeviceFuncs->pfnCalcPrivateShaderResourceViewSize = + CalcPrivateShaderResourceViewSize; + pCreateData->pDeviceFuncs->pfnCreateShaderResourceView = + CreateShaderResourceView; + pCreateData->pDeviceFuncs->pfnDestroyShaderResourceView = + DestroyShaderResourceView; + pCreateData->pDeviceFuncs->pfnCalcPrivateRenderTargetViewSize = + CalcPrivateRenderTargetViewSize; + pCreateData->pDeviceFuncs->pfnCreateRenderTargetView = + CreateRenderTargetView; + pCreateData->pDeviceFuncs->pfnDestroyRenderTargetView = + DestroyRenderTargetView; + pCreateData->pDeviceFuncs->pfnCalcPrivateDepthStencilViewSize = + CalcPrivateDepthStencilViewSize; + pCreateData->pDeviceFuncs->pfnCreateDepthStencilView = + CreateDepthStencilView; + pCreateData->pDeviceFuncs->pfnDestroyDepthStencilView = + DestroyDepthStencilView; + pCreateData->pDeviceFuncs->pfnCalcPrivateElementLayoutSize = + CalcPrivateElementLayoutSize; + pCreateData->pDeviceFuncs->pfnCreateElementLayout = CreateElementLayout; + pCreateData->pDeviceFuncs->pfnDestroyElementLayout = DestroyElementLayout; + pCreateData->pDeviceFuncs->pfnCalcPrivateBlendStateSize = + CalcPrivateBlendStateSize; + pCreateData->pDeviceFuncs->pfnCreateBlendState = CreateBlendState; + pCreateData->pDeviceFuncs->pfnDestroyBlendState = DestroyBlendState; + pCreateData->pDeviceFuncs->pfnCalcPrivateDepthStencilStateSize = + CalcPrivateDepthStencilStateSize; + pCreateData->pDeviceFuncs->pfnCreateDepthStencilState = + CreateDepthStencilState; + pCreateData->pDeviceFuncs->pfnDestroyDepthStencilState = + DestroyDepthStencilState; + pCreateData->pDeviceFuncs->pfnCalcPrivateRasterizerStateSize = + CalcPrivateRasterizerStateSize; + pCreateData->pDeviceFuncs->pfnCreateRasterizerState = + CreateRasterizerState; + pCreateData->pDeviceFuncs->pfnDestroyRasterizerState = + DestroyRasterizerState; + pCreateData->pDeviceFuncs->pfnCalcPrivateShaderSize = CalcPrivateShaderSize; + pCreateData->pDeviceFuncs->pfnCreateVertexShader = CreateVertexShader; + pCreateData->pDeviceFuncs->pfnCreateGeometryShader = CreateGeometryShader; + pCreateData->pDeviceFuncs->pfnCreatePixelShader = CreatePixelShader; + pCreateData->pDeviceFuncs->pfnCalcPrivateGeometryShaderWithStreamOutput = + CalcPrivateGeometryShaderWithStreamOutput; + pCreateData->pDeviceFuncs->pfnCreateGeometryShaderWithStreamOutput = + CreateGeometryShaderWithStreamOutput; + pCreateData->pDeviceFuncs->pfnDestroyShader = DestroyShader; + pCreateData->pDeviceFuncs->pfnCalcPrivateSamplerSize = CalcPrivateSamplerSize; + pCreateData->pDeviceFuncs->pfnCreateSampler = CreateSampler; + pCreateData->pDeviceFuncs->pfnDestroySampler = DestroySampler; + pCreateData->pDeviceFuncs->pfnCalcPrivateQuerySize = CalcPrivateQuerySize; + pCreateData->pDeviceFuncs->pfnCreateQuery = CreateQuery; + pCreateData->pDeviceFuncs->pfnDestroyQuery = DestroyQuery; + pCreateData->pDeviceFuncs->pfnCheckFormatSupport = CheckFormatSupport; + pCreateData->pDeviceFuncs->pfnCheckMultisampleQualityLevels = + CheckMultisampleQualityLevels; + pCreateData->pDeviceFuncs->pfnCheckCounterInfo = CheckCounterInfo; + pCreateData->pDeviceFuncs->pfnCheckCounter = CheckCounter; + pCreateData->pDeviceFuncs->pfnDestroyDevice = DestroyDevice; + pCreateData->pDeviceFuncs->pfnSetTextFilterSize = SetTextFilterSize; + break; + case D3D10_1_DDI_INTERFACE_VERSION: + case D3D10_1_x_DDI_INTERFACE_VERSION: + case D3D10_1_7_DDI_INTERFACE_VERSION: + pCreateData->p10_1DeviceFuncs->pfnDefaultConstantBufferUpdateSubresourceUP = + ResourceUpdateSubResourceUP; + pCreateData->p10_1DeviceFuncs->pfnVsSetConstantBuffers = VsSetConstantBuffers; + pCreateData->p10_1DeviceFuncs->pfnPsSetShaderResources = PsSetShaderResources; + pCreateData->p10_1DeviceFuncs->pfnPsSetShader = PsSetShader; + pCreateData->p10_1DeviceFuncs->pfnPsSetSamplers = PsSetSamplers; + pCreateData->p10_1DeviceFuncs->pfnVsSetShader = VsSetShader; + pCreateData->p10_1DeviceFuncs->pfnDrawIndexed = DrawIndexed; + pCreateData->p10_1DeviceFuncs->pfnDraw = Draw; + pCreateData->p10_1DeviceFuncs->pfnDynamicIABufferMapNoOverwrite = + ResourceMap; + pCreateData->p10_1DeviceFuncs->pfnDynamicIABufferUnmap = ResourceUnmap; + pCreateData->p10_1DeviceFuncs->pfnDynamicConstantBufferMapDiscard = + ResourceMap; + pCreateData->p10_1DeviceFuncs->pfnDynamicIABufferMapDiscard = + ResourceMap; + pCreateData->p10_1DeviceFuncs->pfnDynamicConstantBufferUnmap = + ResourceUnmap; + pCreateData->p10_1DeviceFuncs->pfnPsSetConstantBuffers = PsSetConstantBuffers; + pCreateData->p10_1DeviceFuncs->pfnIaSetInputLayout = IaSetInputLayout; + pCreateData->p10_1DeviceFuncs->pfnIaSetVertexBuffers = IaSetVertexBuffers; + pCreateData->p10_1DeviceFuncs->pfnIaSetIndexBuffer = IaSetIndexBuffer; + pCreateData->p10_1DeviceFuncs->pfnDrawIndexedInstanced = DrawIndexedInstanced; + pCreateData->p10_1DeviceFuncs->pfnDrawInstanced = DrawInstanced; + pCreateData->p10_1DeviceFuncs->pfnDynamicResourceMapDiscard = + ResourceMap; + pCreateData->p10_1DeviceFuncs->pfnDynamicResourceUnmap = ResourceUnmap; + pCreateData->p10_1DeviceFuncs->pfnGsSetConstantBuffers = GsSetConstantBuffers; + pCreateData->p10_1DeviceFuncs->pfnGsSetShader = GsSetShader; + pCreateData->p10_1DeviceFuncs->pfnIaSetTopology = IaSetTopology; + pCreateData->p10_1DeviceFuncs->pfnStagingResourceMap = ResourceMap; + pCreateData->p10_1DeviceFuncs->pfnStagingResourceUnmap = ResourceUnmap; + pCreateData->p10_1DeviceFuncs->pfnVsSetShaderResources = VsSetShaderResources; + pCreateData->p10_1DeviceFuncs->pfnVsSetSamplers = VsSetSamplers; + pCreateData->p10_1DeviceFuncs->pfnGsSetShaderResources = GsSetShaderResources; + pCreateData->p10_1DeviceFuncs->pfnGsSetSamplers = GsSetSamplers; + pCreateData->p10_1DeviceFuncs->pfnSetRenderTargets = SetRenderTargets; + pCreateData->p10_1DeviceFuncs->pfnShaderResourceViewReadAfterWriteHazard = + ShaderResourceViewReadAfterWriteHazard; + pCreateData->p10_1DeviceFuncs->pfnResourceReadAfterWriteHazard = + ResourceReadAfterWriteHazard; + pCreateData->p10_1DeviceFuncs->pfnSetBlendState = SetBlendState; + pCreateData->p10_1DeviceFuncs->pfnSetDepthStencilState = SetDepthStencilState; + pCreateData->p10_1DeviceFuncs->pfnSetRasterizerState = SetRasterizerState; + pCreateData->p10_1DeviceFuncs->pfnQueryEnd = QueryEnd; + pCreateData->p10_1DeviceFuncs->pfnQueryBegin = QueryBegin; + pCreateData->p10_1DeviceFuncs->pfnResourceCopyRegion = ResourceCopyRegion; + pCreateData->p10_1DeviceFuncs->pfnResourceUpdateSubresourceUP = + ResourceUpdateSubResourceUP; + pCreateData->p10_1DeviceFuncs->pfnSoSetTargets = SoSetTargets; + pCreateData->p10_1DeviceFuncs->pfnDrawAuto = DrawAuto; + pCreateData->p10_1DeviceFuncs->pfnSetViewports = SetViewports; + pCreateData->p10_1DeviceFuncs->pfnSetScissorRects = SetScissorRects; + pCreateData->p10_1DeviceFuncs->pfnClearRenderTargetView = ClearRenderTargetView; + pCreateData->p10_1DeviceFuncs->pfnClearDepthStencilView = ClearDepthStencilView; + pCreateData->p10_1DeviceFuncs->pfnSetPredication = SetPredication; + pCreateData->p10_1DeviceFuncs->pfnQueryGetData = QueryGetData; + pCreateData->p10_1DeviceFuncs->pfnFlush = Flush; + pCreateData->p10_1DeviceFuncs->pfnGenMips = GenMips; + pCreateData->p10_1DeviceFuncs->pfnResourceCopy = ResourceCopy; + pCreateData->p10_1DeviceFuncs->pfnResourceResolveSubresource = + ResourceResolveSubResource; + pCreateData->p10_1DeviceFuncs->pfnResourceMap = ResourceMap; + pCreateData->p10_1DeviceFuncs->pfnResourceUnmap = ResourceUnmap; + pCreateData->p10_1DeviceFuncs->pfnResourceIsStagingBusy = ResourceIsStagingBusy; + pCreateData->p10_1DeviceFuncs->pfnRelocateDeviceFuncs = RelocateDeviceFuncs1; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateResourceSize = + CalcPrivateResourceSize; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateOpenedResourceSize = + CalcPrivateOpenedResourceSize; + pCreateData->p10_1DeviceFuncs->pfnCreateResource = CreateResource; + pCreateData->p10_1DeviceFuncs->pfnOpenResource = OpenResource; + pCreateData->p10_1DeviceFuncs->pfnDestroyResource = DestroyResource; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateShaderResourceViewSize = + CalcPrivateShaderResourceViewSize1; + pCreateData->p10_1DeviceFuncs->pfnCreateShaderResourceView = + CreateShaderResourceView1; + pCreateData->p10_1DeviceFuncs->pfnDestroyShaderResourceView = + DestroyShaderResourceView; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateRenderTargetViewSize = + CalcPrivateRenderTargetViewSize; + pCreateData->p10_1DeviceFuncs->pfnCreateRenderTargetView = + CreateRenderTargetView; + pCreateData->p10_1DeviceFuncs->pfnDestroyRenderTargetView = + DestroyRenderTargetView; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateDepthStencilViewSize = + CalcPrivateDepthStencilViewSize; + pCreateData->p10_1DeviceFuncs->pfnCreateDepthStencilView = + CreateDepthStencilView; + pCreateData->p10_1DeviceFuncs->pfnDestroyDepthStencilView = + DestroyDepthStencilView; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateElementLayoutSize = + CalcPrivateElementLayoutSize; + pCreateData->p10_1DeviceFuncs->pfnCreateElementLayout = CreateElementLayout; + pCreateData->p10_1DeviceFuncs->pfnDestroyElementLayout = DestroyElementLayout; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateBlendStateSize = + CalcPrivateBlendStateSize1; + pCreateData->p10_1DeviceFuncs->pfnCreateBlendState = CreateBlendState1; + pCreateData->p10_1DeviceFuncs->pfnDestroyBlendState = DestroyBlendState; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateDepthStencilStateSize = + CalcPrivateDepthStencilStateSize; + pCreateData->p10_1DeviceFuncs->pfnCreateDepthStencilState = + CreateDepthStencilState; + pCreateData->p10_1DeviceFuncs->pfnDestroyDepthStencilState = + DestroyDepthStencilState; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateRasterizerStateSize = + CalcPrivateRasterizerStateSize; + pCreateData->p10_1DeviceFuncs->pfnCreateRasterizerState = + CreateRasterizerState; + pCreateData->p10_1DeviceFuncs->pfnDestroyRasterizerState = + DestroyRasterizerState; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateShaderSize = CalcPrivateShaderSize; + pCreateData->p10_1DeviceFuncs->pfnCreateVertexShader = CreateVertexShader; + pCreateData->p10_1DeviceFuncs->pfnCreateGeometryShader = CreateGeometryShader; + pCreateData->p10_1DeviceFuncs->pfnCreatePixelShader = CreatePixelShader; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateGeometryShaderWithStreamOutput = + CalcPrivateGeometryShaderWithStreamOutput; + pCreateData->p10_1DeviceFuncs->pfnCreateGeometryShaderWithStreamOutput = + CreateGeometryShaderWithStreamOutput; + pCreateData->p10_1DeviceFuncs->pfnDestroyShader = DestroyShader; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateSamplerSize = CalcPrivateSamplerSize; + pCreateData->p10_1DeviceFuncs->pfnCreateSampler = CreateSampler; + pCreateData->p10_1DeviceFuncs->pfnDestroySampler = DestroySampler; + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateQuerySize = CalcPrivateQuerySize; + pCreateData->p10_1DeviceFuncs->pfnCreateQuery = CreateQuery; + pCreateData->p10_1DeviceFuncs->pfnDestroyQuery = DestroyQuery; + pCreateData->p10_1DeviceFuncs->pfnCheckFormatSupport = CheckFormatSupport; + pCreateData->p10_1DeviceFuncs->pfnCheckMultisampleQualityLevels = + CheckMultisampleQualityLevels; + pCreateData->p10_1DeviceFuncs->pfnCheckCounterInfo = CheckCounterInfo; + pCreateData->p10_1DeviceFuncs->pfnCheckCounter = CheckCounter; + pCreateData->p10_1DeviceFuncs->pfnDestroyDevice = DestroyDevice; + pCreateData->p10_1DeviceFuncs->pfnSetTextFilterSize = SetTextFilterSize; + + pCreateData->p10_1DeviceFuncs->pfnRelocateDeviceFuncs = RelocateDeviceFuncs1; + + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateShaderResourceViewSize = + CalcPrivateShaderResourceViewSize1; + pCreateData->p10_1DeviceFuncs->pfnCreateShaderResourceView = + CreateShaderResourceView1; + + pCreateData->p10_1DeviceFuncs->pfnCalcPrivateBlendStateSize = + CalcPrivateBlendStateSize1; + pCreateData->p10_1DeviceFuncs->pfnCreateBlendState = CreateBlendState1; + + pCreateData->p10_1DeviceFuncs->pfnResourceConvert = + pCreateData->p10_1DeviceFuncs->pfnResourceCopy; + pCreateData->p10_1DeviceFuncs->pfnResourceConvertRegion = + pCreateData->p10_1DeviceFuncs->pfnResourceCopyRegion; + + break; + default: + assert(0); + break; + } + + /* + * Fill in DXGI DDI functions + */ + pCreateData->DXGIBaseDDI.pDXGIDDIBaseFunctions->pfnPresent = + _Present; + pCreateData->DXGIBaseDDI.pDXGIDDIBaseFunctions->pfnGetGammaCaps = + _GetGammaCaps; + pCreateData->DXGIBaseDDI.pDXGIDDIBaseFunctions->pfnSetDisplayMode = + _SetDisplayMode; + pCreateData->DXGIBaseDDI.pDXGIDDIBaseFunctions->pfnSetResourcePriority = + _SetResourcePriority; + pCreateData->DXGIBaseDDI.pDXGIDDIBaseFunctions->pfnQueryResourceResidency = + _QueryResourceResidency; + pCreateData->DXGIBaseDDI.pDXGIDDIBaseFunctions->pfnRotateResourceIdentities = + _RotateResourceIdentities; + pCreateData->DXGIBaseDDI.pDXGIDDIBaseFunctions->pfnBlt = + _Blt; + + if (0) { + return S_OK; + } else { + // Tell DXGI to not use the shared resource presentation path when + // communicating with DWM: + // http://msdn.microsoft.com/en-us/library/windows/hardware/ff569887(v=vs.85).aspx + return DXGI_STATUS_NO_REDIRECTION; + } +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyDevice -- + * + * The DestroyDevice function destroys a graphics context. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyDevice(D3D10DDI_HDEVICE hDevice) // IN +{ + unsigned i; + + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + + pipe->flush(pipe, NULL, 0); + + for (i = 0; i < PIPE_MAX_SO_BUFFERS; ++i) { + pipe_so_target_reference(&pDevice->so_targets[i], NULL); + } + if (pDevice->draw_so_target) { + pipe_so_target_reference(&pDevice->draw_so_target, NULL); + } + + pipe->bind_fs_state(pipe, NULL); + pipe->bind_vs_state(pipe, NULL); + + DeleteEmptyShader(pDevice, PIPE_SHADER_FRAGMENT, pDevice->empty_fs); + DeleteEmptyShader(pDevice, PIPE_SHADER_VERTEX, pDevice->empty_vs); + + pipe_surface_reference(&pDevice->fb.zsbuf, NULL); + for (i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) { + pipe_surface_reference(&pDevice->fb.cbufs[i], NULL); + } + + for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) { + if (!pDevice->vertex_buffers[i].is_user_buffer) { + pipe_resource_reference(&pDevice->vertex_buffers[i].buffer.resource, NULL); + } + } + + pipe_resource_reference(&pDevice->index_buffer, NULL); + + static struct pipe_sampler_view * sampler_views[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + memset(sampler_views, 0, sizeof sampler_views); + pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, + PIPE_MAX_SHADER_SAMPLER_VIEWS, 0, sampler_views); + pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, + PIPE_MAX_SHADER_SAMPLER_VIEWS, 0, sampler_views); + pipe->set_sampler_views(pipe, PIPE_SHADER_GEOMETRY, 0, + PIPE_MAX_SHADER_SAMPLER_VIEWS, 0, sampler_views); + + pipe->destroy(pipe); +} + + +/* + * ---------------------------------------------------------------------- + * + * RelocateDeviceFuncs -- + * + * The RelocateDeviceFuncs function notifies the user-mode + * display driver about the new location of the driver function table. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +RelocateDeviceFuncs(D3D10DDI_HDEVICE hDevice, // IN + __in struct D3D10DDI_DEVICEFUNCS *pDeviceFunctions) // IN +{ + LOG_ENTRYPOINT(); + + /* + * Nothing to do as we don't store a pointer to this entity. + */ +} + + +/* + * ---------------------------------------------------------------------- + * + * RelocateDeviceFuncs1 -- + * + * The RelocateDeviceFuncs function notifies the user-mode + * display driver about the new location of the driver function table. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +RelocateDeviceFuncs1(D3D10DDI_HDEVICE hDevice, // IN + __in struct D3D10_1DDI_DEVICEFUNCS *pDeviceFunctions) // IN +{ + LOG_ENTRYPOINT(); + + /* + * Nothing to do as we don't store a pointer to this entity. + */ +} + + +/* + * ---------------------------------------------------------------------- + * + * Flush -- + * + * The Flush function submits outstanding hardware commands that + * are in the hardware command buffer to the display miniport driver. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +Flush(D3D10DDI_HDEVICE hDevice) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + + pipe->flush(pipe, NULL, 0); +} + + +/* + * ---------------------------------------------------------------------- + * + * CheckFormatSupport -- + * + * The CheckFormatSupport function retrieves the capabilites that + * the device has with the specified format. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CheckFormatSupport(D3D10DDI_HDEVICE hDevice, // IN + DXGI_FORMAT Format, // IN + __out UINT *pFormatCaps) // OUT +{ + //LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + struct pipe_screen *screen = pipe->screen; + + *pFormatCaps = 0; + + enum pipe_format format = FormatTranslate(Format, FALSE); + if (format == PIPE_FORMAT_NONE) { + *pFormatCaps = D3D10_DDI_FORMAT_SUPPORT_NOT_SUPPORTED; + return; + } + + if (Format == DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM) { + /* + * We only need to support creation. + * http://msdn.microsoft.com/en-us/library/windows/hardware/ff552818.aspx + */ + return; + } + + if (screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_RENDER_TARGET)) { + *pFormatCaps |= D3D10_DDI_FORMAT_SUPPORT_RENDERTARGET; + *pFormatCaps |= D3D10_DDI_FORMAT_SUPPORT_BLENDABLE; + +#if SUPPORT_MSAA + if (screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 4, 4, + PIPE_BIND_RENDER_TARGET)) { + *pFormatCaps |= D3D10_DDI_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET; + } +#endif + } + + if (screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_SAMPLER_VIEW)) { + *pFormatCaps |= D3D10_DDI_FORMAT_SUPPORT_SHADER_SAMPLE; + +#if SUPPORT_MSAA + if (screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 4, 4, + PIPE_BIND_RENDER_TARGET)) { + *pFormatCaps |= D3D10_DDI_FORMAT_SUPPORT_MULTISAMPLE_LOAD; + } +#endif + } +} + + +/* + * ---------------------------------------------------------------------- + * + * CheckMultisampleQualityLevels -- + * + * The CheckMultisampleQualityLevels function retrieves the number + * of quality levels that the device supports for the specified + * number of samples. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CheckMultisampleQualityLevels(D3D10DDI_HDEVICE hDevice, // IN + DXGI_FORMAT Format, // IN + UINT SampleCount, // IN + __out UINT *pNumQualityLevels) // OUT +{ + //LOG_ENTRYPOINT(); + + /* XXX: Disable MSAA */ + *pNumQualityLevels = 0; +} + + +/* + * ---------------------------------------------------------------------- + * + * SetTextFilterSize -- + * + * The SetTextFilterSize function sets the width and height + * of the monochrome convolution filter. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +SetTextFilterSize(D3D10DDI_HDEVICE hDevice, // IN + UINT Width, // IN + UINT Height) // IN +{ + LOG_ENTRYPOINT(); + + LOG_UNSUPPORTED(Width != 1 || Height != 1); +} diff --git a/src/gallium/frontends/d3d10umd/Device.h b/src/gallium/frontends/d3d10umd/Device.h new file mode 100644 index 00000000000..5edd76d92f9 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Device.h @@ -0,0 +1,44 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Device.h -- + * Functions that provide the 3D device functionality. + */ + +#ifndef DEVICE_H +#define DEVICE_H + +#include "DriverIncludes.h" + +SIZE_T APIENTRY CalcPrivateDeviceSize(D3D10DDI_HADAPTER hAdapter, + __in const D3D10DDIARG_CALCPRIVATEDEVICESIZE *pData); + +HRESULT APIENTRY CreateDevice(D3D10DDI_HADAPTER hAdapter, + __in D3D10DDIARG_CREATEDEVICE *pCreateData); + +#endif /* DEVICE_H */ diff --git a/src/gallium/frontends/d3d10umd/Draw.cpp b/src/gallium/frontends/d3d10umd/Draw.cpp new file mode 100644 index 00000000000..5036f76593c --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Draw.cpp @@ -0,0 +1,343 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Draw.h -- + * Functions that render 3D primitives. + */ + + +#include "Draw.h" +#include "State.h" +#include "Shader.h" + +#include "Debug.h" + +#include "util/u_draw.h" +#include "util/u_memory.h" + +static unsigned +ClampedUAdd(unsigned a, + unsigned b) +{ + unsigned c = a + b; + if (c < a) { + return 0xffffffff; + } + return c; +} + + +/* + * We have to resolve the stream output state for empty geometry shaders. + * In particular we've remapped the output indices when translating the + * shaders so now the register_index variables in the stream output + * state are incorrect and we need to remap them back to the correct + * state. + */ +static void +ResolveState(Device *pDevice) +{ + if (pDevice->bound_empty_gs && pDevice->bound_vs && + pDevice->bound_vs->state.tokens) { + Shader *gs = pDevice->bound_empty_gs; + Shader *vs = pDevice->bound_vs; + boolean remapped = FALSE; + struct pipe_context *pipe = pDevice->pipe; + if (!gs->output_resolved) { + for (unsigned i = 0; i < gs->state.stream_output.num_outputs; ++i) { + unsigned mapping = + ShaderFindOutputMapping(vs, gs->state.stream_output.output[i].register_index); + if (mapping != gs->state.stream_output.output[i].register_index) { + gs->state.stream_output.output[i].register_index = mapping; + remapped = TRUE; + } + } + if (remapped) { + pipe->delete_gs_state(pipe, gs->handle); + gs->handle = pipe->create_gs_state(pipe, &gs->state); + } + gs->output_resolved = TRUE; + } + pipe->bind_gs_state(pipe, gs->handle); + } +} + + +static struct pipe_resource * +create_null_index_buffer(struct pipe_context *ctx, uint num_indices, + unsigned *restart_index, unsigned *index_size, + unsigned *ib_offset) +{ + unsigned buf_size = num_indices * sizeof(unsigned); + unsigned *buf = (unsigned*)MALLOC(buf_size); + struct pipe_resource *ibuf; + + memset(buf, 0, buf_size); + + ibuf = pipe_buffer_create_with_data(ctx, + PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_IMMUTABLE, + buf_size, buf); + *index_size = 4; + *restart_index = 0xffffffff; + *ib_offset = 0; + + FREE(buf); + + return ibuf; +} + +/* + * ---------------------------------------------------------------------- + * + * Draw -- + * + * The Draw function draws nonindexed primitives. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +Draw(D3D10DDI_HDEVICE hDevice, // IN + UINT VertexCount, // IN + UINT StartVertexLocation) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + + ResolveState(pDevice); + + assert(pDevice->primitive < PIPE_PRIM_MAX); + util_draw_arrays(pDevice->pipe, + pDevice->primitive, + StartVertexLocation, + VertexCount); +} + + +/* + * ---------------------------------------------------------------------- + * + * DrawIndexed -- + * + * The DrawIndexed function draws indexed primitives. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DrawIndexed(D3D10DDI_HDEVICE hDevice, // IN + UINT IndexCount, // IN + UINT StartIndexLocation, // IN + INT BaseVertexLocation) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_draw_info info; + struct pipe_draw_start_count_bias draw; + struct pipe_resource *null_ib = NULL; + unsigned restart_index = pDevice->restart_index; + unsigned index_size = pDevice->index_size; + unsigned ib_offset = pDevice->ib_offset; + + assert(pDevice->primitive < PIPE_PRIM_MAX); + + /* XXX I don't think draw still needs this? */ + if (!pDevice->index_buffer) { + null_ib = + create_null_index_buffer(pDevice->pipe, + StartIndexLocation + IndexCount, + &restart_index, &index_size, &ib_offset); + } + + ResolveState(pDevice); + + util_draw_init_info(&info); + info.index_size = index_size; + info.mode = pDevice->primitive; + draw.start = ClampedUAdd(StartIndexLocation, ib_offset / index_size); + draw.count = IndexCount; + info.index.resource = null_ib ? null_ib : pDevice->index_buffer; + draw.index_bias = BaseVertexLocation; + info.primitive_restart = TRUE; + info.restart_index = restart_index; + + pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, NULL, &draw, 1); + + if (null_ib) { + pipe_resource_reference(&null_ib, NULL); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * DrawInstanced -- + * + * The DrawInstanced function draws particular instances + * of nonindexed primitives. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DrawInstanced(D3D10DDI_HDEVICE hDevice, // IN + UINT VertexCountPerInstance, // IN + UINT InstanceCount, // IN + UINT StartVertexLocation, // IN + UINT StartInstanceLocation) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + + if (!InstanceCount) { + return; + } + + ResolveState(pDevice); + + assert(pDevice->primitive < PIPE_PRIM_MAX); + util_draw_arrays_instanced(pDevice->pipe, + pDevice->primitive, + StartVertexLocation, + VertexCountPerInstance, + StartInstanceLocation, + InstanceCount); +} + + +/* + * ---------------------------------------------------------------------- + * + * DrawIndexedInstanced -- + * + * The DrawIndexedInstanced function draws particular + * instances of indexed primitives. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DrawIndexedInstanced(D3D10DDI_HDEVICE hDevice, // IN + UINT IndexCountPerInstance, // IN + UINT InstanceCount, // IN + UINT StartIndexLocation, // IN + INT BaseVertexLocation, // IN + UINT StartInstanceLocation) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_draw_info info; + struct pipe_draw_start_count_bias draw; + struct pipe_resource *null_ib = NULL; + unsigned restart_index = pDevice->restart_index; + unsigned index_size = pDevice->index_size; + unsigned ib_offset = pDevice->ib_offset; + + assert(pDevice->primitive < PIPE_PRIM_MAX); + + if (!InstanceCount) { + return; + } + + /* XXX I don't think draw still needs this? */ + if (!pDevice->index_buffer) { + null_ib = + create_null_index_buffer(pDevice->pipe, + StartIndexLocation + IndexCountPerInstance, + &restart_index, &index_size, &ib_offset); + } + + ResolveState(pDevice); + + util_draw_init_info(&info); + info.index_size = index_size; + info.mode = pDevice->primitive; + draw.start = ClampedUAdd(StartIndexLocation, ib_offset / index_size); + draw.count = IndexCountPerInstance; + info.index.resource = null_ib ? null_ib : pDevice->index_buffer; + draw.index_bias = BaseVertexLocation; + info.start_instance = StartInstanceLocation; + info.instance_count = InstanceCount; + info.primitive_restart = TRUE; + info.restart_index = restart_index; + + pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, NULL, &draw, 1); + + if (null_ib) { + pipe_resource_reference(&null_ib, NULL); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * DrawAuto -- + * + * The DrawAuto function works similarly to the Draw function, + * except DrawAuto is used for the special case where vertex + * data is written through the stream-output unit and then + * recycled as a vertex buffer. The driver determines the number + * of primitives, in part, by how much data was written to the + * buffer through stream output. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DrawAuto(D3D10DDI_HDEVICE hDevice) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_draw_info info; + struct pipe_draw_indirect_info indirect; + + + if (!pDevice->draw_so_target) { + LOG_UNSUPPORTED("DrawAuto without a set source buffer!"); + return; + } + + assert(pDevice->primitive < PIPE_PRIM_MAX); + + ResolveState(pDevice); + + util_draw_init_info(&info); + info.mode = pDevice->primitive; + memset(&indirect, 0, sizeof indirect); + indirect.count_from_stream_output = pDevice->draw_so_target; + + pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, &indirect, NULL, 1); +} diff --git a/src/gallium/frontends/d3d10umd/Draw.h b/src/gallium/frontends/d3d10umd/Draw.h new file mode 100644 index 00000000000..b0b7b7bab69 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Draw.h @@ -0,0 +1,52 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Draw.h -- + * Functions that render 3D primitives. + */ + +#ifndef DRAW_H +#define DRAW_H + +#include "DriverIncludes.h" + +void APIENTRY Draw(D3D10DDI_HDEVICE hDevice, UINT VertexCount, UINT StartVertexLocation); +void APIENTRY DrawIndexed(D3D10DDI_HDEVICE hDevice, UINT IndexCount, + UINT StartIndexLocation, INT BaseVertexLocation); + +void APIENTRY DrawInstanced(D3D10DDI_HDEVICE hDevice, UINT VertexCountPerInstance, + UINT InstanceCount, UINT StartVertexLocation, + UINT StartInstanceLocation); + +void APIENTRY DrawIndexedInstanced(D3D10DDI_HDEVICE hDevice, UINT IndexCountPerInstance, + UINT InstanceCount, UINT StartIndexLocation, + INT BaseVertexLocation, UINT StartInstanceLocation); + +void APIENTRY DrawAuto(D3D10DDI_HDEVICE hDevice); + +#endif diff --git a/src/gallium/frontends/d3d10umd/DriverIncludes.h b/src/gallium/frontends/d3d10umd/DriverIncludes.h new file mode 100644 index 00000000000..e78d46fafc5 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/DriverIncludes.h @@ -0,0 +1,65 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * DriverIncludes.h -- + * Basic DDK includes for building the client driver. + */ + +#ifndef DRIVER_INCLUDES_H +#define DRIVER_INCLUDES_H + +#ifdef __MINGW32__ +#undef WIN32_LEAN_AND_MEAN /* for DEFINE_GUID macro */ +#define _NO_OLDNAMES /* avoid defining ssize_t */ +#include /* for vsnprintf */ +#undef fileno /* we redefine this in vm_basic_defs.h */ +#endif + + +#include + +#include "winddk/winddk_compat.h" + +//typedef LARGE_INTEGER PHYSICAL_ADDRESS; +//typedef __success(return >= 0) LONG NTSTATUS; + +#define D3D10DDI_MINOR_HEADER_VERSION 1 +#include + +#include "Debug.h" + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_format.h" +#include "pipe/p_defines.h" + +#include "util/u_debug.h" +#include "util/u_inlines.h" + + +#endif /* DRIVER_INCLUDES_H */ diff --git a/src/gallium/frontends/d3d10umd/Dxgi.cpp b/src/gallium/frontends/d3d10umd/Dxgi.cpp new file mode 100644 index 00000000000..253f81ed283 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Dxgi.cpp @@ -0,0 +1,374 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Dxgi.cpp -- + * DXGI related functions. + */ + +#include + +#include "Dxgi.h" +#include "Format.h" +#include "State.h" + +#include "Debug.h" + +#include "util/format/u_format.h" + + +/* + * ---------------------------------------------------------------------- + * + * _Present -- + * + * This is turned into kernel callbacks rather than directly emitted + * as fifo packets. + * + * ---------------------------------------------------------------------- + */ + +HRESULT APIENTRY +_Present(DXGI_DDI_ARG_PRESENT *pPresentData) +{ + + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeDevice(pPresentData->hDevice); + Resource *pSrcResource = CastResource(pPresentData->hSurfaceToPresent); + + D3DKMT_PRESENT *pPresentInfo = (D3DKMT_PRESENT *)pPresentData->pDXGIContext; + + HWND hWnd = pPresentInfo->hWindow; + + if (0) { + DebugPrintf(" hWindow = 0x%08lx\n", pPresentInfo->hWindow); + if (pPresentInfo->Flags.SrcRectValid) { + DebugPrintf(" SrcRect.left = %li\n", pPresentInfo->SrcRect.left); + DebugPrintf(" SrcRect.top = %li\n", pPresentInfo->SrcRect.top); + DebugPrintf(" SrcRect.right = %li\n", pPresentInfo->SrcRect.right); + DebugPrintf(" SrcRect.bottom = %li\n", pPresentInfo->SrcRect.bottom); + } + if (pPresentInfo->Flags.DstRectValid) { + DebugPrintf(" DstRect.left = %li\n", pPresentInfo->DstRect.left); + DebugPrintf(" DstRect.top = %li\n", pPresentInfo->DstRect.top); + DebugPrintf(" DstRect.right = %li\n", pPresentInfo->DstRect.right); + DebugPrintf(" DstRect.bottom = %li\n", pPresentInfo->DstRect.bottom); + } + } + + RECT rect; + if (!GetClientRect(hWnd, &rect)) { + DebugPrintf("Invalid window.\n"); + return S_OK; + } + + int windowWidth = rect.right - rect.left; + int windowHeight = rect.bottom - rect.top; + + HDC hDC = GetDC(hWnd); + + unsigned w = pSrcResource->resource->width0; + unsigned h = pSrcResource->resource->height0; + + void *map; + struct pipe_transfer *transfer; + map = pipe_transfer_map(pipe, + pSrcResource->resource, + 0, 0, PIPE_MAP_READ, + 0, 0, w, h, + &transfer); + if (map) { + + BITMAPINFO bmi; + + memset(&bmi, 0, sizeof bmi); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = w; + bmi.bmiHeader.biHeight= -(long)h; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = 0; + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + DWORD *pixels = NULL; + + // http://www.daniweb.com/software-development/cpp/code/241875/fast-animation-with-the-windows-gdi + + HBITMAP hBmp = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&pixels, NULL, 0); + + util_format_translate( + PIPE_FORMAT_B8G8R8X8_UNORM, + (void *)pixels, w * 4, + 0, 0, + pSrcResource->resource->format, + map, transfer->stride, + 0, 0, w, h); + + if (0) { + /* + * Save a BMP for debugging. + */ + + FILE *fp = fopen("present.bmp", "wb"); + if (fp) { + BITMAPFILEHEADER bmf; + bmf.bfType = 0x4d42; + bmf.bfSize = sizeof bmf + sizeof bmi + h * w * 4; + bmf.bfReserved1 = 0; + bmf.bfReserved2 = 0; + bmf.bfOffBits = sizeof bmf + sizeof bmi; + + fwrite(&bmf, sizeof bmf, 1, fp); + fwrite(&bmi, sizeof bmi, 1, fp); + fwrite(pixels, h, w * 4, fp); + fclose(fp); + } + } + + HDC hdcMem; + hdcMem = CreateCompatibleDC(hDC); + HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hBmp); + + int iStretchMode = SetStretchBltMode(hDC, HALFTONE); + + StretchBlt(hDC, 0, 0, windowWidth, windowHeight, + hdcMem, 0, 0, w, h, + SRCCOPY); + + if (iStretchMode) { + SetStretchBltMode(hDC, iStretchMode); + } + + SelectObject(hdcMem, hbmOld); + DeleteDC(hdcMem); + DeleteObject(hBmp); + + pipe_transfer_unmap(pipe, transfer); + } + + ReleaseDC(hWnd, hDC); + + return S_OK; +} + + +/* + * ---------------------------------------------------------------------- + * + * _GetGammaCaps -- + * + * Return gamma capabilities. + * + * ---------------------------------------------------------------------- + */ + +HRESULT APIENTRY +_GetGammaCaps( DXGI_DDI_ARG_GET_GAMMA_CONTROL_CAPS *GetCaps ) +{ + LOG_ENTRYPOINT(); + + DXGI_GAMMA_CONTROL_CAPABILITIES *pCaps; + + pCaps = GetCaps->pGammaCapabilities; + + pCaps->ScaleAndOffsetSupported = FALSE; + pCaps->MinConvertedValue = 0.0; + pCaps->MaxConvertedValue = 1.0; + pCaps->NumGammaControlPoints = 17; + + for (UINT i = 0; i < pCaps->NumGammaControlPoints; i++) { + pCaps->ControlPointPositions[i] = (float)i / (float)(pCaps->NumGammaControlPoints - 1); + } + + return S_OK; +} + + +/* + * ---------------------------------------------------------------------- + * + * _SetDisplayMode -- + * + * Set the resource that is used to scan out to the display. + * + * ---------------------------------------------------------------------- + */ + +HRESULT APIENTRY +_SetDisplayMode( DXGI_DDI_ARG_SETDISPLAYMODE *SetDisplayMode ) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + + return S_OK; +} + + +/* + * ---------------------------------------------------------------------- + * + * _SetResourcePriority -- + * + * ---------------------------------------------------------------------- + */ + +HRESULT APIENTRY +_SetResourcePriority( DXGI_DDI_ARG_SETRESOURCEPRIORITY *SetResourcePriority ) +{ + LOG_ENTRYPOINT(); + + /* ignore */ + + return S_OK; +} + + +/* + * ---------------------------------------------------------------------- + * + * _QueryResourceResidency -- + * + * ---------------------------------------------------------------------- + */ + +HRESULT APIENTRY +_QueryResourceResidency( DXGI_DDI_ARG_QUERYRESOURCERESIDENCY *QueryResourceResidency ) +{ + LOG_ENTRYPOINT(); + + for (UINT i = 0; i < QueryResourceResidency->Resources; ++i) { + QueryResourceResidency->pStatus[i] = DXGI_DDI_RESIDENCY_FULLY_RESIDENT; + } + + return S_OK; +} + + +/* + * ---------------------------------------------------------------------- + * + * _RotateResourceIdentities -- + * + * Rotate a list of resources by recreating their views with + * the updated rotations. + * + * ---------------------------------------------------------------------- + */ + +HRESULT APIENTRY +_RotateResourceIdentities( DXGI_DDI_ARG_ROTATE_RESOURCE_IDENTITIES *RotateResourceIdentities ) +{ + LOG_ENTRYPOINT(); + + if (RotateResourceIdentities->Resources <= 1) { + return S_OK; + } + + struct pipe_context *pipe = CastPipeDevice(RotateResourceIdentities->hDevice); + struct pipe_screen *screen = pipe->screen; + + struct pipe_resource *resource0 = CastPipeResource(RotateResourceIdentities->pResources[0]); + + assert(resource0); + LOG_UNSUPPORTED(resource0->last_level); + + /* + * XXX: Copying is not very efficient, but it is much simpler than the + * alternative of recreating all views. + */ + + struct pipe_resource *temp_resource; + temp_resource = screen->resource_create(screen, resource0); + assert(temp_resource); + if (!temp_resource) { + return E_OUTOFMEMORY; + } + + struct pipe_box src_box; + src_box.x = 0; + src_box.y = 0; + src_box.z = 0; + src_box.width = resource0->width0; + src_box.height = resource0->height0; + src_box.depth = resource0->depth0; + + for (UINT i = 0; i < RotateResourceIdentities->Resources + 1; ++i) { + struct pipe_resource *src_resource; + struct pipe_resource *dst_resource; + + if (i < RotateResourceIdentities->Resources) { + src_resource = CastPipeResource(RotateResourceIdentities->pResources[i]); + } else { + src_resource = temp_resource; + } + + if (i > 0) { + dst_resource = CastPipeResource(RotateResourceIdentities->pResources[i - 1]); + } else { + dst_resource = temp_resource; + } + + assert(dst_resource); + assert(src_resource); + + pipe->resource_copy_region(pipe, + dst_resource, + 0, // dst_level + 0, 0, 0, // dst_x,y,z + src_resource, + 0, // src_level + &src_box); + } + + pipe_resource_reference(&temp_resource, NULL); + + return S_OK; +} + + +/* + * ---------------------------------------------------------------------- + * + * _Blt -- + * + * Do a blt between two subresources. Apply MSAA resolve, format + * conversion and stretching. + * + * ---------------------------------------------------------------------- + */ + +HRESULT APIENTRY +_Blt(DXGI_DDI_ARG_BLT *Blt) +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + + return S_OK; +} diff --git a/src/gallium/frontends/d3d10umd/Dxgi.h b/src/gallium/frontends/d3d10umd/Dxgi.h new file mode 100644 index 00000000000..dedc2542d6a --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Dxgi.h @@ -0,0 +1,46 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Dxgi.h -- + * Functions that manipulate GPU resources. + */ + +#ifndef WRAP_DXGI_H +#define WRAP_DXGI_H + +#include "DriverIncludes.h" + +HRESULT APIENTRY _Present( DXGI_DDI_ARG_PRESENT * ); +HRESULT APIENTRY _GetGammaCaps( DXGI_DDI_ARG_GET_GAMMA_CONTROL_CAPS * ); +HRESULT APIENTRY _SetDisplayMode( DXGI_DDI_ARG_SETDISPLAYMODE * ); +HRESULT APIENTRY _SetResourcePriority( DXGI_DDI_ARG_SETRESOURCEPRIORITY * ); +HRESULT APIENTRY _QueryResourceResidency( DXGI_DDI_ARG_QUERYRESOURCERESIDENCY * ); +HRESULT APIENTRY _RotateResourceIdentities( DXGI_DDI_ARG_ROTATE_RESOURCE_IDENTITIES * ); +HRESULT APIENTRY _Blt( DXGI_DDI_ARG_BLT * ); + +#endif diff --git a/src/gallium/frontends/d3d10umd/Format.cpp b/src/gallium/frontends/d3d10umd/Format.cpp new file mode 100644 index 00000000000..d30f8853369 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Format.cpp @@ -0,0 +1,389 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Format.h -- + * Functions for format manipulation. + */ + + +#include + +#include "Format.h" +#include "State.h" + +#include "Debug.h" + + +/* XXX: for a time llvmpipe didn't support SRGB */ +#define HAVE_SRGB 1 + + +enum pipe_format +FormatTranslate(DXGI_FORMAT Format, BOOL depth) +{ + switch (Format) { + + case DXGI_FORMAT_UNKNOWN: + return PIPE_FORMAT_NONE; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return PIPE_FORMAT_R32G32B32A32_FLOAT; + case DXGI_FORMAT_R32G32B32A32_UINT: + return PIPE_FORMAT_R32G32B32A32_UINT; + case DXGI_FORMAT_R32G32B32A32_SINT: + return PIPE_FORMAT_R32G32B32A32_SINT; + case DXGI_FORMAT_R32G32B32_FLOAT: + return PIPE_FORMAT_R32G32B32_FLOAT; + case DXGI_FORMAT_R32G32B32_UINT: + return PIPE_FORMAT_R32G32B32_UINT; + case DXGI_FORMAT_R32G32B32_SINT: + return PIPE_FORMAT_R32G32B32_SINT; + case DXGI_FORMAT_R16G16B16A16_UNORM: + return PIPE_FORMAT_R16G16B16A16_UNORM; + case DXGI_FORMAT_R16G16B16A16_UINT: + return PIPE_FORMAT_R16G16B16A16_UINT; + case DXGI_FORMAT_R16G16B16A16_SNORM: + return PIPE_FORMAT_R16G16B16A16_SNORM; + case DXGI_FORMAT_R16G16B16A16_SINT: + return PIPE_FORMAT_R16G16B16A16_SINT; + case DXGI_FORMAT_R32G32_FLOAT: + return PIPE_FORMAT_R32G32_FLOAT; + case DXGI_FORMAT_R32G32_UINT: + return PIPE_FORMAT_R32G32_UINT; + case DXGI_FORMAT_R32G32_SINT: + return PIPE_FORMAT_R32G32_SINT; + case DXGI_FORMAT_R8G8B8A8_UNORM: + return PIPE_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_R8G8B8A8_UINT: + return PIPE_FORMAT_R8G8B8A8_UINT; + case DXGI_FORMAT_R8G8B8A8_SNORM: + return PIPE_FORMAT_R8G8B8A8_SNORM; + case DXGI_FORMAT_R8G8B8A8_SINT: + return PIPE_FORMAT_R8G8B8A8_SINT; + case DXGI_FORMAT_R16G16_UNORM: + return PIPE_FORMAT_R16G16_UNORM; + case DXGI_FORMAT_R16G16_UINT: + return PIPE_FORMAT_R16G16_UINT; + case DXGI_FORMAT_R16G16_SNORM: + return PIPE_FORMAT_R16G16_SNORM; + case DXGI_FORMAT_R16G16_SINT: + return PIPE_FORMAT_R16G16_SINT; + case DXGI_FORMAT_D32_FLOAT: + return PIPE_FORMAT_Z32_FLOAT; + case DXGI_FORMAT_R32_FLOAT: + return PIPE_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R32_UINT: + return PIPE_FORMAT_R32_UINT; + case DXGI_FORMAT_R32_SINT: + return PIPE_FORMAT_R32_SINT; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return PIPE_FORMAT_Z24_UNORM_S8_UINT; + case DXGI_FORMAT_R8G8_UNORM: + return PIPE_FORMAT_R8G8_UNORM; + case DXGI_FORMAT_R8G8_UINT: + return PIPE_FORMAT_R8G8_UINT; + case DXGI_FORMAT_R8G8_SNORM: + return PIPE_FORMAT_R8G8_SNORM; + case DXGI_FORMAT_R8G8_SINT: + return PIPE_FORMAT_R8G8_SINT; + case DXGI_FORMAT_D16_UNORM: + return PIPE_FORMAT_Z16_UNORM; + case DXGI_FORMAT_R16_UNORM: + return PIPE_FORMAT_R16_UNORM; + case DXGI_FORMAT_R16_UINT: + return PIPE_FORMAT_R16_UINT; + case DXGI_FORMAT_R16_SNORM: + return PIPE_FORMAT_R16_SNORM; + case DXGI_FORMAT_R16_SINT: + return PIPE_FORMAT_R16_SINT; + case DXGI_FORMAT_R8_UNORM: + return PIPE_FORMAT_R8_UNORM; + case DXGI_FORMAT_R8_UINT: + return PIPE_FORMAT_R8_UINT; + case DXGI_FORMAT_R8_SNORM: + return PIPE_FORMAT_R8_SNORM; + case DXGI_FORMAT_R8_SINT: + return PIPE_FORMAT_R8_SINT; + case DXGI_FORMAT_A8_UNORM: + return PIPE_FORMAT_A8_UNORM; + case DXGI_FORMAT_BC1_UNORM: + return PIPE_FORMAT_DXT1_RGBA; + case DXGI_FORMAT_BC1_UNORM_SRGB: +#if HAVE_SRGB + return PIPE_FORMAT_DXT1_SRGBA; +#else + return PIPE_FORMAT_DXT1_RGBA; +#endif + case DXGI_FORMAT_BC2_UNORM: + return PIPE_FORMAT_DXT3_RGBA; + case DXGI_FORMAT_BC2_UNORM_SRGB: +#if HAVE_SRGB + return PIPE_FORMAT_DXT3_SRGBA; +#else + return PIPE_FORMAT_DXT3_RGBA; +#endif + case DXGI_FORMAT_BC3_UNORM: + return PIPE_FORMAT_DXT5_RGBA; + case DXGI_FORMAT_BC3_UNORM_SRGB: +#if HAVE_SRGB + return PIPE_FORMAT_DXT5_SRGBA; +#else + return PIPE_FORMAT_DXT5_RGBA; +#endif + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: +#if HAVE_SRGB + return PIPE_FORMAT_R8G8B8A8_SRGB; +#else + return PIPE_FORMAT_R8G8B8A8_UNORM; +#endif + + /* Gallium has no typeless formats. We simply use an equivalent + * typed format. + */ + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return PIPE_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_BC1_TYPELESS: + return PIPE_FORMAT_DXT1_RGBA; + case DXGI_FORMAT_BC2_TYPELESS: + return PIPE_FORMAT_DXT3_RGBA; + case DXGI_FORMAT_BC3_TYPELESS: + return PIPE_FORMAT_DXT5_RGBA; + case DXGI_FORMAT_R8_TYPELESS: + return PIPE_FORMAT_R8_UNORM; + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + return PIPE_FORMAT_R32G32B32A32_UNORM; + case DXGI_FORMAT_R32G32B32_TYPELESS: + return PIPE_FORMAT_R32G32B32_UNORM; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + return PIPE_FORMAT_R16G16B16A16_UNORM; + case DXGI_FORMAT_R32G32_TYPELESS: + return PIPE_FORMAT_R32G32_UNORM; + case DXGI_FORMAT_R8G8_TYPELESS: + return PIPE_FORMAT_R8G8_UNORM; + case DXGI_FORMAT_R16_TYPELESS: + return depth ? PIPE_FORMAT_Z16_UNORM : PIPE_FORMAT_R16_UNORM; + case DXGI_FORMAT_R16G16_TYPELESS: + return PIPE_FORMAT_R16G16_UNORM; + case DXGI_FORMAT_R32_TYPELESS: + return depth ? PIPE_FORMAT_Z32_FLOAT : PIPE_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R24G8_TYPELESS: + return PIPE_FORMAT_Z24_UNORM_S8_UINT; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + return PIPE_FORMAT_Z24X8_UNORM; + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + return PIPE_FORMAT_Z24_UNORM_S8_UINT; + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + return PIPE_FORMAT_R8G8_B8G8_UNORM; + case DXGI_FORMAT_G8R8_G8B8_UNORM: + return PIPE_FORMAT_G8R8_G8B8_UNORM; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return PIPE_FORMAT_R16G16B16A16_FLOAT; + case DXGI_FORMAT_R16G16_FLOAT: + return PIPE_FORMAT_R16G16_FLOAT; + case DXGI_FORMAT_R16_FLOAT: + return PIPE_FORMAT_R16_FLOAT; + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + return PIPE_FORMAT_R9G9B9E5_FLOAT; + case DXGI_FORMAT_R1_UNORM: + return PIPE_FORMAT_R1_UNORM; + + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return PIPE_FORMAT_Z32_FLOAT_S8X24_UINT; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + return PIPE_FORMAT_R10G10B10A2_UNORM; + case DXGI_FORMAT_R10G10B10A2_UINT: + return PIPE_FORMAT_R10G10B10A2_UINT; + case DXGI_FORMAT_R11G11B10_FLOAT: + return PIPE_FORMAT_R11G11B10_FLOAT; + + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + return PIPE_FORMAT_RGTC1_UNORM; + case DXGI_FORMAT_BC4_SNORM: + return PIPE_FORMAT_RGTC1_SNORM; + + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + return PIPE_FORMAT_RGTC2_UNORM; + case DXGI_FORMAT_BC5_SNORM: + return PIPE_FORMAT_RGTC2_SNORM; + + case DXGI_FORMAT_B5G6R5_UNORM: + return PIPE_FORMAT_B5G6R5_UNORM; + case DXGI_FORMAT_B5G5R5A1_UNORM: + return PIPE_FORMAT_B5G5R5A1_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM: + return PIPE_FORMAT_B8G8R8X8_UNORM; + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: +#if HAVE_SRGB + return PIPE_FORMAT_B8G8R8A8_SRGB; +#else + return PIPE_FORMAT_B8G8R8A8_UNORM; +#endif + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + return PIPE_FORMAT_B8G8R8X8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: +#if HAVE_SRGB + return PIPE_FORMAT_B8G8R8X8_SRGB; +#else + return PIPE_FORMAT_B8G8R8X8_UNORM; +#endif + + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + return PIPE_FORMAT_R10G10B10A2_UNORM; + + default: + DebugPrintf("%s: unsupported format %s\n", + __FUNCTION__, FormatToName(Format)); + return PIPE_FORMAT_NONE; + } +} + + + +#define CASE(fmt) case fmt: return #fmt + +const char * +FormatToName(DXGI_FORMAT Format) +{ + switch (Format) { + CASE(DXGI_FORMAT_UNKNOWN); + CASE(DXGI_FORMAT_R32G32B32A32_TYPELESS); + CASE(DXGI_FORMAT_R32G32B32A32_FLOAT); + CASE(DXGI_FORMAT_R32G32B32A32_UINT); + CASE(DXGI_FORMAT_R32G32B32A32_SINT); + CASE(DXGI_FORMAT_R32G32B32_TYPELESS); + CASE(DXGI_FORMAT_R32G32B32_FLOAT); + CASE(DXGI_FORMAT_R32G32B32_UINT); + CASE(DXGI_FORMAT_R32G32B32_SINT); + CASE(DXGI_FORMAT_R16G16B16A16_TYPELESS); + 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); + CASE(DXGI_FORMAT_R32G32_TYPELESS); + CASE(DXGI_FORMAT_R32G32_FLOAT); + CASE(DXGI_FORMAT_R32G32_UINT); + CASE(DXGI_FORMAT_R32G32_SINT); + CASE(DXGI_FORMAT_R32G8X24_TYPELESS); + CASE(DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + CASE(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS); + CASE(DXGI_FORMAT_X32_TYPELESS_G8X24_UINT); + CASE(DXGI_FORMAT_R10G10B10A2_TYPELESS); + CASE(DXGI_FORMAT_R10G10B10A2_UNORM); + CASE(DXGI_FORMAT_R10G10B10A2_UINT); + CASE(DXGI_FORMAT_R11G11B10_FLOAT); + CASE(DXGI_FORMAT_R8G8B8A8_TYPELESS); + 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); + CASE(DXGI_FORMAT_R16G16_TYPELESS); + 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); + CASE(DXGI_FORMAT_R32_TYPELESS); + CASE(DXGI_FORMAT_D32_FLOAT); + CASE(DXGI_FORMAT_R32_FLOAT); + CASE(DXGI_FORMAT_R32_UINT); + CASE(DXGI_FORMAT_R32_SINT); + CASE(DXGI_FORMAT_R24G8_TYPELESS); + CASE(DXGI_FORMAT_D24_UNORM_S8_UINT); + CASE(DXGI_FORMAT_R24_UNORM_X8_TYPELESS); + CASE(DXGI_FORMAT_X24_TYPELESS_G8_UINT); + CASE(DXGI_FORMAT_R8G8_TYPELESS); + CASE(DXGI_FORMAT_R8G8_UNORM); + CASE(DXGI_FORMAT_R8G8_UINT); + CASE(DXGI_FORMAT_R8G8_SNORM); + CASE(DXGI_FORMAT_R8G8_SINT); + CASE(DXGI_FORMAT_R16_TYPELESS); + 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); + CASE(DXGI_FORMAT_R8_TYPELESS); + CASE(DXGI_FORMAT_R8_UNORM); + CASE(DXGI_FORMAT_R8_UINT); + CASE(DXGI_FORMAT_R8_SNORM); + CASE(DXGI_FORMAT_R8_SINT); + CASE(DXGI_FORMAT_A8_UNORM); + CASE(DXGI_FORMAT_R1_UNORM); + CASE(DXGI_FORMAT_R9G9B9E5_SHAREDEXP); + CASE(DXGI_FORMAT_R8G8_B8G8_UNORM); + CASE(DXGI_FORMAT_G8R8_G8B8_UNORM); + CASE(DXGI_FORMAT_BC1_TYPELESS); + CASE(DXGI_FORMAT_BC1_UNORM); + CASE(DXGI_FORMAT_BC1_UNORM_SRGB); + CASE(DXGI_FORMAT_BC2_TYPELESS); + CASE(DXGI_FORMAT_BC2_UNORM); + CASE(DXGI_FORMAT_BC2_UNORM_SRGB); + CASE(DXGI_FORMAT_BC3_TYPELESS); + CASE(DXGI_FORMAT_BC3_UNORM); + CASE(DXGI_FORMAT_BC3_UNORM_SRGB); + CASE(DXGI_FORMAT_BC4_TYPELESS); + CASE(DXGI_FORMAT_BC4_UNORM); + CASE(DXGI_FORMAT_BC4_SNORM); + CASE(DXGI_FORMAT_BC5_TYPELESS); + CASE(DXGI_FORMAT_BC5_UNORM); + CASE(DXGI_FORMAT_BC5_SNORM); + CASE(DXGI_FORMAT_B5G6R5_UNORM); + CASE(DXGI_FORMAT_B5G5R5A1_UNORM); + CASE(DXGI_FORMAT_B8G8R8A8_UNORM); + CASE(DXGI_FORMAT_B8G8R8X8_UNORM); + CASE(DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM); + CASE(DXGI_FORMAT_B8G8R8A8_TYPELESS); + CASE(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); + CASE(DXGI_FORMAT_B8G8R8X8_TYPELESS); + CASE(DXGI_FORMAT_B8G8R8X8_UNORM_SRGB); + CASE(DXGI_FORMAT_BC6H_TYPELESS); + CASE(DXGI_FORMAT_BC6H_UF16); + CASE(DXGI_FORMAT_BC6H_SF16); + CASE(DXGI_FORMAT_BC7_TYPELESS); + CASE(DXGI_FORMAT_BC7_UNORM); + CASE(DXGI_FORMAT_BC7_UNORM_SRGB); + default: + return "???"; + } +} diff --git a/src/gallium/frontends/d3d10umd/Format.h b/src/gallium/frontends/d3d10umd/Format.h new file mode 100644 index 00000000000..2ee437107f5 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Format.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Format.h -- + * Functions for handling formats. + */ + +#ifndef FORMAT_H +#define FORMAT_H + +#include "DriverIncludes.h" + +enum pipe_format +FormatTranslate(DXGI_FORMAT Format, BOOL depth); + +const char * +FormatToName(DXGI_FORMAT Format); + + +#endif diff --git a/src/gallium/frontends/d3d10umd/InputAssembly.cpp b/src/gallium/frontends/d3d10umd/InputAssembly.cpp new file mode 100644 index 00000000000..ecbb90605a0 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/InputAssembly.cpp @@ -0,0 +1,370 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * InputAssembly.cpp -- + * Functions that manipulate the input assembly stage. + */ + + +#include +#if defined(_MSC_VER) && !defined(snprintf) +#define snprintf _snprintf +#endif + +#include "InputAssembly.h" +#include "State.h" + +#include "Debug.h" +#include "Format.h" + + +/* + * ---------------------------------------------------------------------- + * + * IaSetTopology -- + * + * The IaSetTopology function sets the primitive topology to + * enable drawing for the input assember. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +IaSetTopology(D3D10DDI_HDEVICE hDevice, // IN + D3D10_DDI_PRIMITIVE_TOPOLOGY PrimitiveTopology) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + + enum pipe_prim_type primitive; + switch (PrimitiveTopology) { + case D3D10_DDI_PRIMITIVE_TOPOLOGY_UNDEFINED: + /* Apps might set topology to UNDEFINED when cleaning up on exit. */ + primitive = PIPE_PRIM_MAX; + break; + case D3D10_DDI_PRIMITIVE_TOPOLOGY_POINTLIST: + primitive = PIPE_PRIM_POINTS; + break; + case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINELIST: + primitive = PIPE_PRIM_LINES; + break; + case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINESTRIP: + primitive = PIPE_PRIM_LINE_STRIP; + break; + case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLELIST: + primitive = PIPE_PRIM_TRIANGLES; + break; + case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: + primitive = PIPE_PRIM_TRIANGLE_STRIP; + break; + case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINELIST_ADJ: + primitive = PIPE_PRIM_LINES_ADJACENCY; + break; + case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ: + primitive = PIPE_PRIM_LINE_STRIP_ADJACENCY; + break; + case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ: + primitive = PIPE_PRIM_TRIANGLES_ADJACENCY; + break; + case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ: + primitive = PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY; + break; + default: + assert(0); + primitive = PIPE_PRIM_MAX; + break; + } + + pDevice->primitive = primitive; +} + + +/* + * ---------------------------------------------------------------------- + * + * IaSetVertexBuffers -- + * + * The IaSetVertexBuffers function sets vertex buffers + * for an input assembler. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +IaSetVertexBuffers(D3D10DDI_HDEVICE hDevice, // IN + UINT StartBuffer, // IN + UINT NumBuffers, // IN + __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers, // IN + __in_ecount (NumBuffers) const UINT *pStrides, // IN + __in_ecount (NumBuffers) const UINT *pOffsets) // IN +{ + static const float dummy[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + unsigned i; + + for (i = 0; i < NumBuffers; i++) { + struct pipe_vertex_buffer *vb = &pDevice->vertex_buffers[StartBuffer + i]; + struct pipe_resource *resource = CastPipeResource(phBuffers[i]); + Resource *res = CastResource(phBuffers[i]); + struct pipe_stream_output_target *so_target = + res ? res->so_target : NULL; + + if (so_target && pDevice->draw_so_target != so_target) { + if (pDevice->draw_so_target) { + pipe_so_target_reference(&pDevice->draw_so_target, NULL); + } + pipe_so_target_reference(&pDevice->draw_so_target, + so_target); + } + + if (resource) { + vb->stride = pStrides[i]; + vb->buffer_offset = pOffsets[i]; + if (vb->is_user_buffer) { + vb->buffer.resource = NULL; + vb->is_user_buffer = FALSE; + } + pipe_resource_reference(&vb->buffer.resource, resource); + } + else { + vb->stride = 0; + vb->buffer_offset = 0; + if (!vb->is_user_buffer) { + pipe_resource_reference(&vb->buffer.resource, NULL); + vb->is_user_buffer = TRUE; + } + vb->buffer.user = dummy; + } + } + + for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) { + struct pipe_vertex_buffer *vb = &pDevice->vertex_buffers[i]; + + /* XXX this is odd... */ + if (!vb->is_user_buffer && !vb->buffer.resource) { + vb->stride = 0; + vb->buffer_offset = 0; + vb->is_user_buffer = TRUE; + vb->buffer.user = dummy; + } + } + + /* Resubmit old and new vertex buffers. + */ + pipe->set_vertex_buffers(pipe, 0, PIPE_MAX_ATTRIBS, 0, FALSE, pDevice->vertex_buffers); +} + + +/* + * ---------------------------------------------------------------------- + * + * IaSetIndexBuffer -- + * + * The IaSetIndexBuffer function sets an index buffer for + * an input assembler. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +IaSetIndexBuffer(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hBuffer, // IN + DXGI_FORMAT Format, // IN + UINT Offset) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_resource *resource = CastPipeResource(hBuffer); + + if (resource) { + pDevice->ib_offset = Offset; + + switch (Format) { + case DXGI_FORMAT_R16_UINT: + pDevice->index_size = 2; + pDevice->restart_index = 0xffff; + break; + case DXGI_FORMAT_R32_UINT: + pDevice->restart_index = 0xffffffff; + pDevice->index_size = 4; + break; + default: + assert(0); /* should not happen */ + pDevice->index_size = 2; + break; + } + pipe_resource_reference(&pDevice->index_buffer, resource); + } else { + pipe_resource_reference(&pDevice->index_buffer, NULL); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateElementLayoutSize -- + * + * The CalcPrivateElementLayoutSize function determines the size + * of the user-mode display driver's private region of memory + * (that is, the size of internal driver structures, not the size + * of the resource video memory) for an element layout. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateElementLayoutSize( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout) // IN +{ + return sizeof(ElementLayout); +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateElementLayout -- + * + * The CreateElementLayout function creates an element layout. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateElementLayout( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout, // IN + D3D10DDI_HELEMENTLAYOUT hElementLayout, // IN + D3D10DDI_HRTELEMENTLAYOUT hRTElementLayout) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + ElementLayout *pElementLayout = CastElementLayout(hElementLayout); + + struct pipe_vertex_element elements[PIPE_MAX_ATTRIBS]; + memset(elements, 0, sizeof elements); + + unsigned num_elements = pCreateElementLayout->NumElements; + unsigned max_elements = 0; + for (unsigned i = 0; i < num_elements; i++) { + const D3D10DDIARG_INPUT_ELEMENT_DESC* pVertexElement = + &pCreateElementLayout->pVertexElements[i]; + struct pipe_vertex_element *ve = + &elements[pVertexElement->InputRegister]; + + ve->src_offset = pVertexElement->AlignedByteOffset; + ve->vertex_buffer_index = pVertexElement->InputSlot; + ve->src_format = FormatTranslate(pVertexElement->Format, FALSE); + + switch (pVertexElement->InputSlotClass) { + case D3D10_DDI_INPUT_PER_VERTEX_DATA: + ve->instance_divisor = 0; + break; + case D3D10_DDI_INPUT_PER_INSTANCE_DATA: + if (!pVertexElement->InstanceDataStepRate) { + LOG_UNSUPPORTED(!pVertexElement->InstanceDataStepRate); + ve->instance_divisor = ~0; + } else { + ve->instance_divisor = pVertexElement->InstanceDataStepRate; + } + break; + default: + assert(0); + break; + } + + max_elements = MAX2(max_elements, pVertexElement->InputRegister + 1); + } + + /* XXX: What do we do when there's a gap? */ + if (max_elements != num_elements) { + DebugPrintf("%s: gap\n", __FUNCTION__); + } + + pElementLayout->handle = + pipe->create_vertex_elements_state(pipe, max_elements, elements); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyElementLayout -- + * + * The DestroyElementLayout function destroys the specified + * element layout object. The element layout object can be + * destoyed only if it is not currently bound to a display device. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyElementLayout(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HELEMENTLAYOUT hElementLayout) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + ElementLayout *pElementLayout = CastElementLayout(hElementLayout); + + pipe->delete_vertex_elements_state(pipe, pElementLayout->handle);} + + +/* + * ---------------------------------------------------------------------- + * + * IaSetInputLayout -- + * + * The IaSetInputLayout function sets an input layout for + * the input assembler. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +IaSetInputLayout(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HELEMENTLAYOUT hInputLayout) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + void *state = CastPipeInputLayout(hInputLayout); + + pipe->bind_vertex_elements_state(pipe, state); +} + + diff --git a/src/gallium/frontends/d3d10umd/InputAssembly.h b/src/gallium/frontends/d3d10umd/InputAssembly.h new file mode 100644 index 00000000000..aaf49245bc9 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/InputAssembly.h @@ -0,0 +1,63 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * InputAssembly.h -- + * Functions that manipulate the input assembly stage. + */ + +#ifndef INPUT_ASSEMBLY_H +#define INPUT_ASSEMBLY_H + +#include "DriverIncludes.h" + +void APIENTRY IaSetTopology(D3D10DDI_HDEVICE hDevice, + D3D10_DDI_PRIMITIVE_TOPOLOGY PrimitiveTopology); + +void APIENTRY IaSetVertexBuffers(D3D10DDI_HDEVICE hDevice, UINT StartBuffer, UINT NumBuffers, + __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers, + __in_ecount (NumBuffers) const UINT *pStrides, + __in_ecount (NumBuffers) const UINT *pOffsets); + +void APIENTRY IaSetIndexBuffer(D3D10DDI_HDEVICE hDevice, D3D10DDI_HRESOURCE hBuffer, + DXGI_FORMAT Format, UINT Offset); +void APIENTRY IaSetInputLayout(D3D10DDI_HDEVICE hDevice, D3D10DDI_HELEMENTLAYOUT hInputLayout); + +SIZE_T APIENTRY CalcPrivateElementLayoutSize( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout); + +void APIENTRY CreateElementLayout( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout, + D3D10DDI_HELEMENTLAYOUT hElementLayout, + D3D10DDI_HRTELEMENTLAYOUT hRTElementLayout); + +void APIENTRY DestroyElementLayout(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HELEMENTLAYOUT hElementLayout); + +#endif /* INPUT_ASSEMBLY_H */ diff --git a/src/gallium/frontends/d3d10umd/OutputMerger.cpp b/src/gallium/frontends/d3d10umd/OutputMerger.cpp new file mode 100644 index 00000000000..f90ca542275 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/OutputMerger.cpp @@ -0,0 +1,998 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * OutputMerger.cpp -- + * Functions that manipulate the output merger state. + */ + + +#include "OutputMerger.h" +#include "State.h" + +#include "Debug.h" +#include "Format.h" + +#include "util/u_framebuffer.h" +#include "util/format/u_format.h" + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateRenderTargetViewSize -- + * + * The CalcPrivateRenderTargetViewSize function determines the size + * of the user-mode display driver's private region of memory + * (that is, the size of internal driver structures, not the size + * of the resource video memory) for a render target view. + * + * ---------------------------------------------------------------------- + */ + + +SIZE_T APIENTRY +CalcPrivateRenderTargetViewSize( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView) // IN +{ + return sizeof(RenderTargetView); +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateRenderTargetView -- + * + * The CreateRenderTargetView function creates a render target view. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateRenderTargetView( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView, // IN + D3D10DDI_HRENDERTARGETVIEW hRenderTargetView, // IN + D3D10DDI_HRTRENDERTARGETVIEW hRTRenderTargetView) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + struct pipe_resource *resource = CastPipeResource(pCreateRenderTargetView->hDrvResource); + RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView); + + struct pipe_surface desc; + + memset(&desc, 0, sizeof desc); + desc.format = FormatTranslate(pCreateRenderTargetView->Format, FALSE); + + switch (pCreateRenderTargetView->ResourceDimension) { + case D3D10DDIRESOURCE_BUFFER: + desc.u.buf.first_element = pCreateRenderTargetView->Buffer.FirstElement; + desc.u.buf.last_element = pCreateRenderTargetView->Buffer.NumElements - 1 + + desc.u.buf.first_element; + break; + case D3D10DDIRESOURCE_TEXTURE1D: + ASSERT(pCreateRenderTargetView->Tex1D.ArraySize != (UINT)-1); + desc.u.tex.level = pCreateRenderTargetView->Tex1D.MipSlice; + desc.u.tex.first_layer = pCreateRenderTargetView->Tex1D.FirstArraySlice; + desc.u.tex.last_layer = pCreateRenderTargetView->Tex1D.ArraySize - 1 + + desc.u.tex.first_layer; + break; + case D3D10DDIRESOURCE_TEXTURE2D: + ASSERT(pCreateRenderTargetView->Tex2D.ArraySize != (UINT)-1); + desc.u.tex.level = pCreateRenderTargetView->Tex2D.MipSlice; + desc.u.tex.first_layer = pCreateRenderTargetView->Tex2D.FirstArraySlice; + desc.u.tex.last_layer = pCreateRenderTargetView->Tex2D.ArraySize - 1 + + desc.u.tex.first_layer; + break; + case D3D10DDIRESOURCE_TEXTURE3D: + desc.u.tex.level = pCreateRenderTargetView->Tex3D.MipSlice; + desc.u.tex.first_layer = pCreateRenderTargetView->Tex3D.FirstW; + desc.u.tex.last_layer = pCreateRenderTargetView->Tex3D.WSize - 1 + + desc.u.tex.first_layer; + break; + case D3D10DDIRESOURCE_TEXTURECUBE: + ASSERT(pCreateRenderTargetView->TexCube.ArraySize != (UINT)-1); + desc.u.tex.level = pCreateRenderTargetView->TexCube.MipSlice; + desc.u.tex.first_layer = pCreateRenderTargetView->TexCube.FirstArraySlice; + desc.u.tex.last_layer = pCreateRenderTargetView->TexCube.ArraySize - 1 + + desc.u.tex.first_layer;; + break; + default: + ASSERT(0); + return; + } + + pRTView->surface = pipe->create_surface(pipe, resource, &desc); + assert(pRTView->surface); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyRenderTargetView -- + * + * The DestroyRenderTargetView function destroys the specified + * render target view object. The render target view object can + * be destoyed only if it is not currently bound to a display device. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyRenderTargetView(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRENDERTARGETVIEW hRenderTargetView) // IN +{ + LOG_ENTRYPOINT(); + + RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView); + + pipe_surface_reference(&pRTView->surface, NULL); +} + + +/* + * ---------------------------------------------------------------------- + * + * ClearRenderTargetView -- + * + * The ClearRenderTargetView function clears the specified + * render target view by setting it to a constant value. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ClearRenderTargetView(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRENDERTARGETVIEW hRenderTargetView, // IN + FLOAT pColorRGBA[4]) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + struct pipe_surface *surface = CastPipeRenderTargetView(hRenderTargetView); + union pipe_color_union clear_color; + + /* + * DX10 always uses float clear color but gallium does not. + * Conversion should just be ordinary conversion. Actual clamping will + * be done later but need to make sure values exceeding int/uint range + * are handled correctly. + */ + if (util_format_is_pure_integer(surface->format)) { + if (util_format_is_pure_sint(surface->format)) { + unsigned i; + /* If only MIN_INT/UINT32 in c++ code would work... */ + int min_int32 = 0x80000000; + int max_int32 = 0x7fffffff; + for (i = 0; i < 4; i++) { + float value = pColorRGBA[i]; + /* This is an expanded clamp to handle NaN and integer conversion. */ + if (util_is_nan(value)) { + clear_color.i[i] = 0; + } else if (value <= (float)min_int32) { + clear_color.i[i] = min_int32; + } else if (value >= (float)max_int32) { + clear_color.i[i] = max_int32; + } else { + clear_color.i[i] = value; + } + } + } + else { + assert(util_format_is_pure_uint(surface->format)); + unsigned i; + unsigned max_uint32 = 0xffffffffU; + for (i = 0; i < 4; i++) { + float value = pColorRGBA[i]; + /* This is an expanded clamp to handle NaN and integer conversion. */ + if (!(value >= 0.0f)) { + /* Handles NaN. */ + clear_color.ui[i] = 0; + } else if (value >= (float)max_uint32) { + clear_color.ui[i] = max_uint32; + } else { + clear_color.ui[i] = value; + } + } + } + } + else { + clear_color.f[0] = pColorRGBA[0]; + clear_color.f[1] = pColorRGBA[1]; + clear_color.f[2] = pColorRGBA[2]; + clear_color.f[3] = pColorRGBA[3]; + } + + pipe->clear_render_target(pipe, + surface, + &clear_color, + 0, 0, + surface->width, + surface->height, + TRUE); +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateDepthStencilViewSize -- + * + * The CalcPrivateDepthStencilViewSize function determines the size + * of the user-mode display driver's private region of memory + * (that is, the size of internal driver structures, not the size + * of the resource video memory) for a depth stencil view. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateDepthStencilViewSize( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView) // IN +{ + return sizeof(DepthStencilView); +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateDepthStencilView -- + * + * The CreateDepthStencilView function creates a depth stencil view. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateDepthStencilView( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView, // IN + D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView, // IN + D3D10DDI_HRTDEPTHSTENCILVIEW hRTDepthStencilView) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + struct pipe_resource *resource = CastPipeResource(pCreateDepthStencilView->hDrvResource); + DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView); + + struct pipe_surface desc; + + memset(&desc, 0, sizeof desc); + desc.format = FormatTranslate(pCreateDepthStencilView->Format, TRUE); + + switch (pCreateDepthStencilView->ResourceDimension) { + case D3D10DDIRESOURCE_TEXTURE1D: + ASSERT(pCreateDepthStencilView->Tex1D.ArraySize != (UINT)-1); + desc.u.tex.level = pCreateDepthStencilView->Tex1D.MipSlice; + desc.u.tex.first_layer = pCreateDepthStencilView->Tex1D.FirstArraySlice; + desc.u.tex.last_layer = pCreateDepthStencilView->Tex1D.ArraySize - 1 + + desc.u.tex.first_layer; + break; + case D3D10DDIRESOURCE_TEXTURE2D: + ASSERT(pCreateDepthStencilView->Tex2D.ArraySize != (UINT)-1); + desc.u.tex.level = pCreateDepthStencilView->Tex2D.MipSlice; + desc.u.tex.first_layer = pCreateDepthStencilView->Tex2D.FirstArraySlice; + desc.u.tex.last_layer = pCreateDepthStencilView->Tex2D.ArraySize - 1 + + desc.u.tex.first_layer; + break; + case D3D10DDIRESOURCE_TEXTURECUBE: + ASSERT(pCreateDepthStencilView->TexCube.ArraySize != (UINT)-1); + desc.u.tex.level = pCreateDepthStencilView->TexCube.MipSlice; + desc.u.tex.first_layer = pCreateDepthStencilView->TexCube.FirstArraySlice; + desc.u.tex.last_layer = pCreateDepthStencilView->TexCube.ArraySize - 1 + + desc.u.tex.first_layer; + break; + default: + ASSERT(0); + return; + } + + pDSView->surface = pipe->create_surface(pipe, resource, &desc); + assert(pDSView->surface); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyDepthStencilView -- + * + * The DestroyDepthStencilView function destroys the specified + * depth stencil view object. The depth stencil view object can + * be destoyed only if it is not currently bound to a display device. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyDepthStencilView(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView) // IN +{ + LOG_ENTRYPOINT(); + + DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView); + + pipe_surface_reference(&pDSView->surface, NULL); +} + + +/* + * ---------------------------------------------------------------------- + * + * ClearDepthStencilView -- + * + * The ClearDepthStencilView function clears the specified + * currently bound depth-stencil view. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ClearDepthStencilView(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView, // IN + UINT Flags, // IN + FLOAT Depth, // IN + UINT8 Stencil) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + struct pipe_surface *surface = CastPipeDepthStencilView(hDepthStencilView); + + unsigned flags = 0; + if (Flags & D3D10_DDI_CLEAR_DEPTH) { + flags |= PIPE_CLEAR_DEPTH; + } + if (Flags & D3D10_DDI_CLEAR_STENCIL) { + flags |= PIPE_CLEAR_STENCIL; + } + + pipe->clear_depth_stencil(pipe, + surface, + flags, + Depth, + Stencil, + 0, 0, + surface->width, + surface->height, + TRUE); +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateBlendStateSize -- + * + * The CalcPrivateBlendStateSize function determines the size of + * the user-mode display driver's private region of memory (that + * is, the size of internal driver structures, not the size of + * the resource video memory) for a blend state. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateBlendStateSize(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_DDI_BLEND_DESC *pBlendDesc) // IN +{ + return sizeof(BlendState); +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateBlendStateSize1 -- + * + * The CalcPrivateBlendStateSize function determines the size of + * the user-mode display driver's private region of memory (that + * is, the size of internal driver structures, not the size of + * the resource video memory) for a blend state. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateBlendStateSize1(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_1_DDI_BLEND_DESC *pBlendDesc) // IN +{ + return sizeof(BlendState); +} + + +/* + * ---------------------------------------------------------------------- + * + * translateBlend -- + * + * Translate blend function from svga3d to gallium representation. + * + * ---------------------------------------------------------------------- + */ +static uint +translateBlendOp(D3D10_DDI_BLEND_OP op) +{ + switch (op) { + case D3D10_DDI_BLEND_OP_ADD: + return PIPE_BLEND_ADD; + case D3D10_DDI_BLEND_OP_SUBTRACT: + return PIPE_BLEND_SUBTRACT; + case D3D10_DDI_BLEND_OP_REV_SUBTRACT: + return PIPE_BLEND_REVERSE_SUBTRACT; + case D3D10_DDI_BLEND_OP_MIN: + return PIPE_BLEND_MIN; + case D3D10_DDI_BLEND_OP_MAX: + return PIPE_BLEND_MAX; + default: + assert(0); + return PIPE_BLEND_ADD; + } +} + + +/* + * ---------------------------------------------------------------------- + * + * translateBlend -- + * + * Translate blend factor from svga3d to gallium representation. + * + * ---------------------------------------------------------------------- + */ +static uint +translateBlend(Device *pDevice, + D3D10_DDI_BLEND blend) +{ + if (!pDevice->max_dual_source_render_targets) { + switch (blend) { + case D3D10_DDI_BLEND_SRC1_COLOR: + case D3D10_DDI_BLEND_SRC1_ALPHA: + LOG_UNSUPPORTED(TRUE); + return D3D10_DDI_BLEND_ZERO; + case D3D10_DDI_BLEND_INV_SRC1_COLOR: + case D3D10_DDI_BLEND_INV_SRC1_ALPHA: + LOG_UNSUPPORTED(TRUE); + return D3D10_DDI_BLEND_ONE; + default: + break; + } + } + + switch (blend) { + case D3D10_DDI_BLEND_ZERO: + return PIPE_BLENDFACTOR_ZERO; + case D3D10_DDI_BLEND_ONE: + return PIPE_BLENDFACTOR_ONE; + case D3D10_DDI_BLEND_SRC_COLOR: + return PIPE_BLENDFACTOR_SRC_COLOR; + case D3D10_DDI_BLEND_INV_SRC_COLOR: + return PIPE_BLENDFACTOR_INV_SRC_COLOR; + case D3D10_DDI_BLEND_SRC_ALPHA: + return PIPE_BLENDFACTOR_SRC_ALPHA; + case D3D10_DDI_BLEND_INV_SRC_ALPHA: + return PIPE_BLENDFACTOR_INV_SRC_ALPHA; + case D3D10_DDI_BLEND_DEST_ALPHA: + return PIPE_BLENDFACTOR_DST_ALPHA; + case D3D10_DDI_BLEND_INV_DEST_ALPHA: + return PIPE_BLENDFACTOR_INV_DST_ALPHA; + case D3D10_DDI_BLEND_DEST_COLOR: + return PIPE_BLENDFACTOR_DST_COLOR; + case D3D10_DDI_BLEND_INV_DEST_COLOR: + return PIPE_BLENDFACTOR_INV_DST_COLOR; + case D3D10_DDI_BLEND_SRC_ALPHASAT: + return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; + case D3D10_DDI_BLEND_BLEND_FACTOR: + return PIPE_BLENDFACTOR_CONST_COLOR; + case D3D10_DDI_BLEND_INVBLEND_FACTOR: + return PIPE_BLENDFACTOR_INV_CONST_COLOR; + case D3D10_DDI_BLEND_SRC1_COLOR: + return PIPE_BLENDFACTOR_SRC1_COLOR; + case D3D10_DDI_BLEND_INV_SRC1_COLOR: + return PIPE_BLENDFACTOR_INV_SRC1_COLOR; + case D3D10_DDI_BLEND_SRC1_ALPHA: + return PIPE_BLENDFACTOR_SRC1_ALPHA; + case D3D10_DDI_BLEND_INV_SRC1_ALPHA: + return PIPE_BLENDFACTOR_INV_SRC1_ALPHA; + default: + assert(0); + return PIPE_BLENDFACTOR_ONE; + } +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateBlendState -- + * + * The CreateBlendState function creates a blend state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateBlendState(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_DDI_BLEND_DESC *pBlendDesc, // IN + D3D10DDI_HBLENDSTATE hBlendState, // IN + D3D10DDI_HRTBLENDSTATE hRTBlendState) // IN +{ + unsigned i; + + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + BlendState *pBlendState = CastBlendState(hBlendState); + + struct pipe_blend_state state; + memset(&state, 0, sizeof state); + + for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) { + state.rt[i].blend_enable = pBlendDesc->BlendEnable[i]; + state.rt[i].colormask = pBlendDesc->RenderTargetWriteMask[i]; + + if (pBlendDesc->BlendEnable[0] != pBlendDesc->BlendEnable[i] || + pBlendDesc->RenderTargetWriteMask[0] != pBlendDesc->RenderTargetWriteMask[i]) { + state.independent_blend_enable = 1; + } + } + + state.rt[0].rgb_func = translateBlendOp(pBlendDesc->BlendOp); + if (pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MIN || + pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MAX) { + state.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + state.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + } else { + state.rt[0].rgb_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlend); + state.rt[0].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlend); + } + + state.rt[0].alpha_func = translateBlendOp(pBlendDesc->BlendOpAlpha); + if (pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN || + pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) { + state.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + state.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + } else { + state.rt[0].alpha_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlendAlpha); + state.rt[0].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlendAlpha); + } + + /* + * Propagate to all the other rendertargets + */ + for (i = 1; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) { + state.rt[i].rgb_func = state.rt[0].rgb_func; + state.rt[i].rgb_src_factor = state.rt[0].rgb_src_factor; + state.rt[i].rgb_dst_factor = state.rt[0].rgb_dst_factor; + state.rt[i].alpha_func = state.rt[0].alpha_func; + state.rt[i].alpha_src_factor = state.rt[0].alpha_src_factor; + state.rt[i].alpha_dst_factor = state.rt[0].alpha_dst_factor; + } + + state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable; + + pBlendState->handle = pipe->create_blend_state(pipe, &state); +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateBlendState1 -- + * + * The CreateBlendState function creates a blend state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateBlendState1(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_1_DDI_BLEND_DESC *pBlendDesc, // IN + D3D10DDI_HBLENDSTATE hBlendState, // IN + D3D10DDI_HRTBLENDSTATE hRTBlendState) // IN +{ + unsigned i; + + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + BlendState *pBlendState = CastBlendState(hBlendState); + + struct pipe_blend_state state; + memset(&state, 0, sizeof state); + + state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable; + state.independent_blend_enable = pBlendDesc->IndependentBlendEnable; + + for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) { + state.rt[i].blend_enable = pBlendDesc->RenderTarget[i].BlendEnable; + state.rt[i].colormask = pBlendDesc->RenderTarget[i].RenderTargetWriteMask; + + state.rt[i].rgb_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOp); + if (pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MIN || + pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MAX) { + state.rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + state.rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + } else { + state.rt[i].rgb_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlend); + state.rt[i].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlend); + } + + state.rt[i].alpha_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOpAlpha); + if (pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN || + pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) { + state.rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + state.rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + } else { + state.rt[i].alpha_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlendAlpha); + state.rt[i].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlendAlpha); + } + } + + pBlendState->handle = pipe->create_blend_state(pipe, &state); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyBlendState -- + * + * The DestroyBlendState function destroys the specified blend + * state object. The blend state object can be destoyed only if + * it is not currently bound to a display device. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyBlendState(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HBLENDSTATE hBlendState) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + BlendState *pBlendState = CastBlendState(hBlendState); + + pipe->delete_blend_state(pipe, pBlendState->handle); +} + + +/* + * ---------------------------------------------------------------------- + * + * SetBlendState -- + * + * The SetBlendState function sets a blend state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +SetBlendState(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HBLENDSTATE hState, // IN + const FLOAT pBlendFactor[4], // IN + UINT SampleMask) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + void *state = CastPipeBlendState(hState); + + pipe->bind_blend_state(pipe, state); + + struct pipe_blend_color color; + color.color[0] = pBlendFactor[0]; + color.color[1] = pBlendFactor[1]; + color.color[2] = pBlendFactor[2]; + color.color[3] = pBlendFactor[3]; + + pipe->set_blend_color(pipe, &color); + + pipe->set_sample_mask(pipe, SampleMask); +} + + +/* + * ---------------------------------------------------------------------- + * + * SetRenderTargets -- + * + * Set the rendertargets. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +SetRenderTargets(D3D10DDI_HDEVICE hDevice, // IN + __in_ecount (NumViews) + const D3D10DDI_HRENDERTARGETVIEW *phRenderTargetView, // IN + UINT RTargets, // IN + UINT ClearTargets, // IN + D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + + struct pipe_context *pipe = pDevice->pipe; + + pDevice->fb.nr_cbufs = 0; + for (unsigned i = 0; i < RTargets; ++i) { + pipe_surface_reference(&pDevice->fb.cbufs[i], + CastPipeRenderTargetView(phRenderTargetView[i])); + if (pDevice->fb.cbufs[i]) { + pDevice->fb.nr_cbufs = i + 1; + } + } + + for (unsigned i = RTargets; i < PIPE_MAX_COLOR_BUFS; ++i) { + pipe_surface_reference(&pDevice->fb.cbufs[i], NULL); + } + + pipe_surface_reference(&pDevice->fb.zsbuf, + CastPipeDepthStencilView(hDepthStencilView)); + + /* + * Calculate the width/height fields for this framebuffer. D3D10 + * actually specifies that they be identical for all bound views. + */ + unsigned width, height; + util_framebuffer_min_size(&pDevice->fb, &width, &height); + pDevice->fb.width = width; + pDevice->fb.height = height; + + pipe->set_framebuffer_state(pipe, &pDevice->fb); +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateDepthStencilStateSize -- + * + * The CalcPrivateDepthStencilStateSize function determines the size + * of the user-mode display driver's private region of memory (that + * is, the size of internal driver structures, not the size of the + * resource video memory) for a depth stencil state. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateDepthStencilStateSize( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc) // IN +{ + return sizeof(DepthStencilState); +} + + +/* + * ---------------------------------------------------------------------- + * + * translateComparison -- + * + * Translate comparison function from DX10 to gallium representation. + * + * ---------------------------------------------------------------------- + */ +static uint +translateComparison(D3D10_DDI_COMPARISON_FUNC Func) +{ + switch (Func) { + case D3D10_DDI_COMPARISON_NEVER: + return PIPE_FUNC_NEVER; + case D3D10_DDI_COMPARISON_LESS: + return PIPE_FUNC_LESS; + case D3D10_DDI_COMPARISON_EQUAL: + return PIPE_FUNC_EQUAL; + case D3D10_DDI_COMPARISON_LESS_EQUAL: + return PIPE_FUNC_LEQUAL; + case D3D10_DDI_COMPARISON_GREATER: + return PIPE_FUNC_GREATER; + case D3D10_DDI_COMPARISON_NOT_EQUAL: + return PIPE_FUNC_NOTEQUAL; + case D3D10_DDI_COMPARISON_GREATER_EQUAL: + return PIPE_FUNC_GEQUAL; + case D3D10_DDI_COMPARISON_ALWAYS: + return PIPE_FUNC_ALWAYS; + default: + assert(0); + return PIPE_FUNC_ALWAYS; + } +} + + +/* + * ---------------------------------------------------------------------- + * + * translateStencilOp -- + * + * Translate stencil op from DX10 to gallium representation. + * + * ---------------------------------------------------------------------- + */ +static uint +translateStencilOp(D3D10_DDI_STENCIL_OP StencilOp) +{ + switch (StencilOp) { + case D3D10_DDI_STENCIL_OP_KEEP: + return PIPE_STENCIL_OP_KEEP; + case D3D10_DDI_STENCIL_OP_ZERO: + return PIPE_STENCIL_OP_ZERO; + case D3D10_DDI_STENCIL_OP_REPLACE: + return PIPE_STENCIL_OP_REPLACE; + case D3D10_DDI_STENCIL_OP_INCR_SAT: + return PIPE_STENCIL_OP_INCR; + case D3D10_DDI_STENCIL_OP_DECR_SAT: + return PIPE_STENCIL_OP_DECR; + case D3D10_DDI_STENCIL_OP_INVERT: + return PIPE_STENCIL_OP_INVERT; + case D3D10_DDI_STENCIL_OP_INCR: + return PIPE_STENCIL_OP_INCR_WRAP; + case D3D10_DDI_STENCIL_OP_DECR: + return PIPE_STENCIL_OP_DECR_WRAP; + default: + assert(0); + return PIPE_STENCIL_OP_KEEP; + } +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateDepthStencilState -- + * + * The CreateDepthStencilState function creates a depth stencil state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateDepthStencilState( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc, // IN + D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState, // IN + D3D10DDI_HRTDEPTHSTENCILSTATE hRTDepthStencilState) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState); + + struct pipe_depth_stencil_alpha_state state; + memset(&state, 0, sizeof state); + + /* Depth. */ + state.depth_enabled = (pDepthStencilDesc->DepthEnable ? 1 : 0); + state.depth_writemask = (pDepthStencilDesc->DepthWriteMask ? 1 : 0); + state.depth_func = translateComparison(pDepthStencilDesc->DepthFunc); + + /* Stencil. */ + if (pDepthStencilDesc->StencilEnable) { + struct pipe_stencil_state *face0 = &state.stencil[0]; + struct pipe_stencil_state *face1 = &state.stencil[1]; + + face0->enabled = 1; + face0->func = translateComparison(pDepthStencilDesc->FrontFace.StencilFunc); + face0->fail_op = translateStencilOp(pDepthStencilDesc->FrontFace.StencilFailOp); + face0->zpass_op = translateStencilOp(pDepthStencilDesc->FrontFace.StencilPassOp); + face0->zfail_op = translateStencilOp(pDepthStencilDesc->FrontFace.StencilDepthFailOp); + face0->valuemask = pDepthStencilDesc->StencilReadMask; + face0->writemask = pDepthStencilDesc->StencilWriteMask; + + face1->enabled = 1; + face1->func = translateComparison(pDepthStencilDesc->BackFace.StencilFunc); + face1->fail_op = translateStencilOp(pDepthStencilDesc->BackFace.StencilFailOp); + face1->zpass_op = translateStencilOp(pDepthStencilDesc->BackFace.StencilPassOp); + face1->zfail_op = translateStencilOp(pDepthStencilDesc->BackFace.StencilDepthFailOp); + face1->valuemask = pDepthStencilDesc->StencilReadMask; + face1->writemask = pDepthStencilDesc->StencilWriteMask; +#ifdef DEBUG + if (!pDepthStencilDesc->FrontEnable) { + ASSERT(face0->func == PIPE_FUNC_ALWAYS); + ASSERT(face0->fail_op == PIPE_STENCIL_OP_KEEP); + ASSERT(face0->zpass_op == PIPE_STENCIL_OP_KEEP); + ASSERT(face0->zfail_op == PIPE_STENCIL_OP_KEEP); + } + + if (!pDepthStencilDesc->BackEnable) { + ASSERT(face1->func == PIPE_FUNC_ALWAYS); + ASSERT(face1->fail_op == PIPE_STENCIL_OP_KEEP); + ASSERT(face1->zpass_op == PIPE_STENCIL_OP_KEEP); + ASSERT(face1->zfail_op == PIPE_STENCIL_OP_KEEP); + } +#endif + } + + pDepthStencilState->handle = + pipe->create_depth_stencil_alpha_state(pipe, &state); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyDepthStencilState -- + * + * The CreateDepthStencilState function creates a depth stencil state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyDepthStencilState(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState); + + pipe->delete_depth_stencil_alpha_state(pipe, pDepthStencilState->handle); +} + + +/* + * ---------------------------------------------------------------------- + * + * SetDepthStencilState -- + * + * The SetDepthStencilState function sets a depth-stencil state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +SetDepthStencilState(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HDEPTHSTENCILSTATE hState, // IN + UINT StencilRef) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + void *state = CastPipeDepthStencilState(hState); + struct pipe_stencil_ref psr; + + psr.ref_value[0] = StencilRef; + psr.ref_value[1] = StencilRef; + + pipe->bind_depth_stencil_alpha_state(pipe, state); + pipe->set_stencil_ref(pipe, psr); +} diff --git a/src/gallium/frontends/d3d10umd/OutputMerger.h b/src/gallium/frontends/d3d10umd/OutputMerger.h new file mode 100644 index 00000000000..381c49b837a --- /dev/null +++ b/src/gallium/frontends/d3d10umd/OutputMerger.h @@ -0,0 +1,114 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * OutputMerger.h -- + * Functions that manipulate the output merger state. + */ + +#ifndef OUTPUT_MERGER_H +#define OUTPUT_MERGER_H + +#include "DriverIncludes.h" + +SIZE_T APIENTRY CalcPrivateRenderTargetViewSize( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView); + +void APIENTRY CreateRenderTargetView( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView, + D3D10DDI_HRENDERTARGETVIEW hRenderTargetView, + D3D10DDI_HRTRENDERTARGETVIEW hRTRenderTargetView); + +void APIENTRY DestroyRenderTargetView(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HRENDERTARGETVIEW hRenderTargetView); + +void APIENTRY ClearRenderTargetView(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HRENDERTARGETVIEW hRenderTargetView, + FLOAT pColorRGBA[4]); + +SIZE_T APIENTRY CalcPrivateDepthStencilViewSize( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView); + +void APIENTRY CreateDepthStencilView( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView, + D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView, + D3D10DDI_HRTDEPTHSTENCILVIEW hRTDepthStencilView); + +void APIENTRY DestroyDepthStencilView(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView); + +void APIENTRY ClearDepthStencilView(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView, + UINT Flags, FLOAT Depth, UINT8 Stencil); + +SIZE_T APIENTRY CalcPrivateBlendStateSize(D3D10DDI_HDEVICE hDevice, + __in const D3D10_DDI_BLEND_DESC *pBlendDesc); + +SIZE_T APIENTRY CalcPrivateBlendStateSize1(D3D10DDI_HDEVICE hDevice, + __in const D3D10_1_DDI_BLEND_DESC *pBlendDesc); + +void APIENTRY CreateBlendState(D3D10DDI_HDEVICE hDevice, + __in const D3D10_DDI_BLEND_DESC *pBlendDesc, + D3D10DDI_HBLENDSTATE hBlendState, + D3D10DDI_HRTBLENDSTATE hRTBlendState); + +void APIENTRY CreateBlendState1(D3D10DDI_HDEVICE hDevice, + __in const D3D10_1_DDI_BLEND_DESC *pBlendDesc, + D3D10DDI_HBLENDSTATE hBlendState, + D3D10DDI_HRTBLENDSTATE hRTBlendState); + +void APIENTRY DestroyBlendState(D3D10DDI_HDEVICE hDevice, D3D10DDI_HBLENDSTATE hBlendState); + +void APIENTRY SetBlendState(D3D10DDI_HDEVICE hDevice, D3D10DDI_HBLENDSTATE hState, + const FLOAT pBlendFactor[4], UINT SampleMask); + +void APIENTRY SetRenderTargets( + D3D10DDI_HDEVICE hDevice, + __in_ecount (NumViews) const D3D10DDI_HRENDERTARGETVIEW *phRenderTargetView, + UINT RTargets, UINT ClearTargets, D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView); + +SIZE_T APIENTRY CalcPrivateDepthStencilStateSize( + D3D10DDI_HDEVICE hDevice, + __in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc); + +void APIENTRY CreateDepthStencilState( + D3D10DDI_HDEVICE hDevice, + __in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc, + D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState, + D3D10DDI_HRTDEPTHSTENCILSTATE hRTDepthStencilState); + +void APIENTRY DestroyDepthStencilState(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState); + +void APIENTRY SetDepthStencilState(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HDEPTHSTENCILSTATE hState, UINT StencilRef); + +#endif /* OUTPUT_MERGER_H */ diff --git a/src/gallium/frontends/d3d10umd/Query.cpp b/src/gallium/frontends/d3d10umd/Query.cpp new file mode 100644 index 00000000000..50e35af0428 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Query.cpp @@ -0,0 +1,454 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Query.cpp -- + * Functions that manipulate query resources. + */ + + +#include "Query.h" +#include "State.h" + +#include "Debug.h" + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateQuerySize -- + * + * The CalcPrivateQuerySize function determines the size of the + * user-mode display driver's private region of memory (that is, + * the size of internal driver structures, not the size of the + * resource video memory) for a query. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateQuerySize(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATEQUERY *pCreateQuery) // IN +{ + return sizeof(Query); +} + + +static uint +TranslateQueryType(D3D10DDI_QUERY query) +{ + switch (query) { + case D3D10DDI_QUERY_EVENT: + return PIPE_QUERY_GPU_FINISHED; + case D3D10DDI_QUERY_OCCLUSION: + return PIPE_QUERY_OCCLUSION_COUNTER; + case D3D10DDI_QUERY_TIMESTAMP: + return PIPE_QUERY_TIMESTAMP; + case D3D10DDI_QUERY_TIMESTAMPDISJOINT: + return PIPE_QUERY_TIMESTAMP_DISJOINT; + case D3D10DDI_QUERY_PIPELINESTATS: + return PIPE_QUERY_PIPELINE_STATISTICS; + case D3D10DDI_QUERY_OCCLUSIONPREDICATE: + return PIPE_QUERY_OCCLUSION_PREDICATE; + case D3D10DDI_QUERY_STREAMOUTPUTSTATS: + return PIPE_QUERY_SO_STATISTICS; + case D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE: + return PIPE_QUERY_SO_OVERFLOW_PREDICATE; + default: + LOG_UNSUPPORTED(TRUE); + return PIPE_QUERY_TYPES; + } +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateQuery -- + * + * The CreateQuery function creates driver-side resources for a + * query that the Microsoft Direct3D runtime subsequently issues + * for processing. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateQuery(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATEQUERY *pCreateQuery, // IN + D3D10DDI_HQUERY hQuery, // IN + D3D10DDI_HRTQUERY hRTQuery) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + + Query *pQuery = CastQuery(hQuery); + memset(pQuery, 0, sizeof *pQuery); + + pQuery->Type = pCreateQuery->Query; + pQuery->Flags = pCreateQuery->MiscFlags; + + pQuery->pipe_type = TranslateQueryType(pCreateQuery->Query); + if (pQuery->pipe_type < PIPE_QUERY_TYPES) { + pQuery->handle = pipe->create_query(pipe, pQuery->pipe_type, 0); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyQuery -- + * + * The DestroyQuery function releases resources for a query. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyQuery(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HQUERY hQuery) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + Query *pQuery = CastQuery(hQuery); + + if (pQuery->handle) { + pipe->destroy_query(pipe, pQuery->handle); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * QueryBegin -- + * + * The QueryBegin function marks the beginning of a sequence of + * graphics commands for a query and transitions the query to the + * "building" state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +QueryBegin(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HQUERY hQuery) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + + Query *pQuery = CastQuery(hQuery); + struct pipe_query *state = CastPipeQuery(hQuery); + + if (state) { + assert(pQuery->pipe_type < PIPE_QUERY_TYPES); + pipe->begin_query(pipe, state); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * QueryEnd -- + * + * The QueryEnd function marks the end of a sequence of graphics + * commands for a query and transitions the query to the + * "issued" state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +QueryEnd(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HQUERY hQuery) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + Query *pQuery = CastQuery(hQuery); + struct pipe_query *state = pQuery->handle; + + pQuery->SeqNo = ++pDevice->LastEmittedQuerySeqNo; + pQuery->GetDataCount = 0; + + if (state) { + pipe->end_query(pipe, state); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * QueryGetData -- + * + * The QueryGetData function polls for the state of a query operation. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +QueryGetData(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HQUERY hQuery, // IN + __out_bcount_full_opt (DataSize) void *pData, // OUT + UINT DataSize, // IN + UINT Flags) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + Query *pQuery = CastQuery(hQuery); + struct pipe_query *state = pQuery->handle; + + /* + * Never return data for recently emitted queries immediately, to make + * wgfasync happy. + */ + if (DataSize == 0 && + (pQuery->SeqNo - pDevice->LastFinishedQuerySeqNo) > 0 && + (pQuery->GetDataCount++) == 0) { + SetError(hDevice, DXGI_DDI_ERR_WASSTILLDRAWING); + return; + } + + boolean wait = !!(Flags & D3D10_DDI_GET_DATA_DO_NOT_FLUSH); + union pipe_query_result result; + + memset(&result, 0, sizeof result); + + boolean ret; + + if (state) { + ret = pipe->get_query_result(pipe, state, wait, &result); + } else { + LOG_UNSUPPORTED(TRUE); + ret = TRUE; + } + + if (!ret) { + SetError(hDevice, DXGI_DDI_ERR_WASSTILLDRAWING); + return; + } + + if (pData) { + switch (pQuery->Type) { + case D3D10DDI_QUERY_EVENT: + case D3D10DDI_QUERY_OCCLUSIONPREDICATE: + case D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE: + *(BOOL *)pData = result.b; + break; + case D3D10DDI_QUERY_OCCLUSION: + case D3D10DDI_QUERY_TIMESTAMP: + *(UINT64 *)pData = result.u64; + break; + case D3D10DDI_QUERY_TIMESTAMPDISJOINT: + { + D3D10_DDI_QUERY_DATA_TIMESTAMP_DISJOINT *pResult = + (D3D10_DDI_QUERY_DATA_TIMESTAMP_DISJOINT *)pData; + pResult->Frequency = result.timestamp_disjoint.frequency; + pResult->Disjoint = result.timestamp_disjoint.disjoint; + } + break; + case D3D10DDI_QUERY_PIPELINESTATS: + { + D3D10_DDI_QUERY_DATA_PIPELINE_STATISTICS *pResult = + (D3D10_DDI_QUERY_DATA_PIPELINE_STATISTICS *)pData; + pResult->IAVertices = result.pipeline_statistics.ia_vertices; + pResult->IAPrimitives = result.pipeline_statistics.ia_primitives; + pResult->VSInvocations = result.pipeline_statistics.vs_invocations; + pResult->GSInvocations = result.pipeline_statistics.gs_invocations; + pResult->GSPrimitives = result.pipeline_statistics.gs_primitives; + pResult->CInvocations = result.pipeline_statistics.c_invocations; + pResult->CPrimitives = result.pipeline_statistics.c_primitives; + pResult->PSInvocations = result.pipeline_statistics.ps_invocations; + //pResult->HSInvocations = result.pipeline_statistics.hs_invocations; + //pResult->DSInvocations = result.pipeline_statistics.ds_invocations; + //pResult->CSInvocations = result.pipeline_statistics.cs_invocations; + } + break; + case D3D10DDI_QUERY_STREAMOUTPUTSTATS: + { + D3D10_DDI_QUERY_DATA_SO_STATISTICS *pResult = + (D3D10_DDI_QUERY_DATA_SO_STATISTICS *)pData; + pResult->NumPrimitivesWritten = result.so_statistics.num_primitives_written; + pResult->PrimitivesStorageNeeded = result.so_statistics.primitives_storage_needed; + } + break; + default: + assert(0); + break; + } + } + + /* + * Keep track of the last finished query, as wgfasync checks that queries + * are completed in order. + */ + if ((pQuery->SeqNo - pDevice->LastFinishedQuerySeqNo) > 0) { + pDevice->LastFinishedQuerySeqNo = pQuery->SeqNo; + } + pQuery->GetDataCount = 0x80000000; +} + + +/* + * ---------------------------------------------------------------------- + * + * SetPredication -- + * + * The SetPredication function specifies whether rendering and + * resource-manipulation commands that follow are actually performed. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +SetPredication(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HQUERY hQuery, // IN + BOOL PredicateValue) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + Query *pQuery = CastQuery(hQuery); + struct pipe_query *state = CastPipeQuery(hQuery); + enum pipe_render_cond_flag wait; + + wait = (pQuery && pQuery->Flags & D3D10DDI_QUERY_MISCFLAG_PREDICATEHINT) ? + PIPE_RENDER_COND_NO_WAIT : PIPE_RENDER_COND_WAIT; + + pipe->render_condition(pipe, state, PredicateValue, wait); + + pDevice->pPredicate = pQuery; + pDevice->PredicateValue = PredicateValue; +} + + +/* + * ---------------------------------------------------------------------- + * + * CheckPredicate -- + * + * Check predicate value and whether to draw or not. + * + * ---------------------------------------------------------------------- + */ + +BOOL +CheckPredicate(Device *pDevice) +{ + Query *pQuery = pDevice->pPredicate; + if (!pQuery) { + return TRUE; + } + + assert(pQuery->Type == D3D10DDI_QUERY_OCCLUSIONPREDICATE || + pQuery->Type == D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE); + + struct pipe_context *pipe = pDevice->pipe; + struct pipe_query *query = pQuery->handle; + assert(query); + + union pipe_query_result result; + memset(&result, 0, sizeof result); + + boolean ret; + ret = pipe->get_query_result(pipe, query, TRUE, &result); + assert(ret == TRUE); + if (!ret) { + return TRUE; + } + + if (!!result.b == !!pDevice->PredicateValue) { + return FALSE; + } + + return TRUE; +} + + +/* + * ---------------------------------------------------------------------- + * + * CheckCounterInfo -- + * + * The CheckCounterInfo function determines global information that + * is related to manipulating counters. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CheckCounterInfo(D3D10DDI_HDEVICE hDevice, // IN + __out D3D10DDI_COUNTER_INFO *pCounterInfo) // OUT +{ + //LOG_ENTRYPOINT(); + + pCounterInfo->LastDeviceDependentCounter = (D3D10DDI_QUERY)0; + pCounterInfo->NumSimultaneousCounters = 0; + pCounterInfo->NumDetectableParallelUnits = 0; +} + + +/* + * ---------------------------------------------------------------------- + * + * CheckCounter -- + * + * The CheckCounter function retrieves information that + * describes a counter. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CheckCounter( + D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_QUERY Query, // IN + __out D3D10DDI_COUNTER_TYPE *pCounterType, // OUT + __out UINT *pActiveCounters, // OUT + __out_ecount_part_z_opt (*pNameLength, *pNameLength) LPSTR pName, // OUT + __inout_opt UINT *pNameLength, // OUT + __out_ecount_part_z_opt (*pUnitsLength, *pUnitsLength) LPSTR pUnits, // OUT + __inout_opt UINT *pUnitsLength, // OUT + __out_ecount_part_z_opt (*pDescriptionLength, *pDescriptionLength) LPSTR pDescription, // OUT + __inout_opt UINT* pDescriptionLength) // OUT +{ + LOG_ENTRYPOINT(); + + SetError(hDevice, DXGI_DDI_ERR_UNSUPPORTED); +} diff --git a/src/gallium/frontends/d3d10umd/Query.h b/src/gallium/frontends/d3d10umd/Query.h new file mode 100644 index 00000000000..d71c130193c --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Query.h @@ -0,0 +1,76 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Query.h -- + * Functions that manipulate query resources. + */ + +#ifndef QUERY_H +#define QUERY_H + +#include "DriverIncludes.h" + +struct Device; + +SIZE_T APIENTRY CalcPrivateQuerySize(D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATEQUERY *pCreateQuery); + +void APIENTRY CreateQuery(D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATEQUERY *pCreateQuery, + D3D10DDI_HQUERY hQuery, D3D10DDI_HRTQUERY hRTQuery); + +void APIENTRY APIENTRY DestroyQuery(D3D10DDI_HDEVICE hDevice, D3D10DDI_HQUERY hQuery); + +void APIENTRY QueryBegin(D3D10DDI_HDEVICE hDevice, D3D10DDI_HQUERY hQuery); + +void APIENTRY QueryEnd(D3D10DDI_HDEVICE hDevice, D3D10DDI_HQUERY hQuery); + +void APIENTRY QueryGetData(D3D10DDI_HDEVICE hDevice, D3D10DDI_HQUERY hQuery, + __out_bcount_full_opt (DataSize) void *pData, + UINT DataSize, UINT Flags); + +void APIENTRY SetPredication(D3D10DDI_HDEVICE hDevice, D3D10DDI_HQUERY hQuery, + BOOL PredicateValue); + +void APIENTRY CheckCounterInfo(D3D10DDI_HDEVICE hDevice, + __out D3D10DDI_COUNTER_INFO *pCounterInfo); + +void APIENTRY CheckCounter(D3D10DDI_HDEVICE hDevice, + D3D10DDI_QUERY Query, + __out D3D10DDI_COUNTER_TYPE *pCounterType, + __out UINT *pActiveCounters, + __out_ecount_part_z_opt (*pNameLength, *pNameLength) LPSTR pName, + __inout_opt UINT *pNameLength, + __out_ecount_part_z_opt (*pUnitsLength, *pUnitsLength) LPSTR pUnits, + __inout_opt UINT *pUnitsLength, + __out_ecount_part_z_opt (*pDescriptionLength, *pDescriptionLength) LPSTR pDescription, + __inout_opt UINT* pDescriptionLength); + +BOOL CheckPredicate(Device *pDevice); + +#endif /* QUERY_H */ diff --git a/src/gallium/frontends/d3d10umd/README.md b/src/gallium/frontends/d3d10umd/README.md new file mode 100644 index 00000000000..ebd408d4558 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/README.md @@ -0,0 +1,6 @@ +This directory has a Gallium state tracker for D3D10 UMD DDI. + +It still uses TGSI, not not NIR. + +Currently it only supports SW rasterizers. See +src/gallium/targets/d3d10sw/README.md for further details. diff --git a/src/gallium/frontends/d3d10umd/Rasterizer.cpp b/src/gallium/frontends/d3d10umd/Rasterizer.cpp new file mode 100644 index 00000000000..9402f383b31 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Rasterizer.cpp @@ -0,0 +1,285 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Rasterizer.cpp -- + * Functions that manipulate rasterizer state. + */ + + +#include "Rasterizer.h" +#include "State.h" + +#include "Debug.h" + + +/* + * ---------------------------------------------------------------------- + * + * SetViewports -- + * + * The SetViewports function sets viewports. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +SetViewports(D3D10DDI_HDEVICE hDevice, // IN + UINT NumViewports, // IN + UINT ClearViewports, // IN + __in_ecount (NumViewports) const D3D10_DDI_VIEWPORT *pViewports) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + struct pipe_viewport_state states[PIPE_MAX_VIEWPORTS]; + + ASSERT(NumViewports + ClearViewports <= + D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE); + + for (UINT i = 0; i < NumViewports; ++i) { + const D3D10_DDI_VIEWPORT *pViewport = &pViewports[i]; + float width = pViewport->Width; + float height = pViewport->Height; + float x = pViewport->TopLeftX; + float y = pViewport->TopLeftY; + float z = pViewport->MinDepth; + float half_width = width / 2.0f; + float half_height = height / 2.0f; + float depth = pViewport->MaxDepth - z; + + states[i].scale[0] = half_width; + states[i].scale[1] = -half_height; + states[i].scale[2] = depth; + + states[i].translate[0] = half_width + x; + states[i].translate[1] = half_height + y; + states[i].translate[2] = z; + } + if (ClearViewports) { + memset(states + NumViewports, 0, + sizeof(struct pipe_viewport_state) * ClearViewports); + } + pipe->set_viewport_states(pipe, 0, NumViewports + ClearViewports, + states); +} + + +/* + * ---------------------------------------------------------------------- + * + * SetScissorRects -- + * + * The SetScissorRects function marks portions of render targets + * that rendering is confined to. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +SetScissorRects(D3D10DDI_HDEVICE hDevice, // IN + UINT NumScissorRects, // IN + UINT ClearScissorRects, // IN + __in_ecount (NumRects) const D3D10_DDI_RECT *pRects) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + struct pipe_scissor_state states[PIPE_MAX_VIEWPORTS]; + + ASSERT(NumScissorRects + ClearScissorRects <= + D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE); + + for (UINT i = 0; i < NumScissorRects; ++i) { + const D3D10_DDI_RECT *pRect = &pRects[i]; + /* gallium scissor values are unsigned so lets make + * sure that we don't overflow */ + states[i].minx = pRect->left < 0 ? 0 : pRect->left; + states[i].miny = pRect->top < 0 ? 0 : pRect->top; + states[i].maxx = pRect->right < 0 ? 0 : pRect->right; + states[i].maxy = pRect->bottom < 0 ? 0 : pRect->bottom; + } + if (ClearScissorRects) { + memset(states + NumScissorRects, 0, + sizeof(struct pipe_scissor_state) * ClearScissorRects); + } + pipe->set_scissor_states(pipe, 0, NumScissorRects + ClearScissorRects, + states); +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateRasterizerStateSize -- + * + * The CalcPrivateRasterizerStateSize function determines the size + * of the user-mode display driver's private region of memory + * (that is, the size of internal driver structures, not the size + * of the resource video memory) for a rasterizer state. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateRasterizerStateSize( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_DDI_RASTERIZER_DESC *pRasterizerDesc) // IN +{ + return sizeof(RasterizerState); +} + + +static uint +translate_cull_mode(D3D10_DDI_CULL_MODE CullMode) +{ + switch (CullMode) { + case D3D10_DDI_CULL_NONE: + return PIPE_FACE_NONE; + case D3D10_DDI_CULL_FRONT: + return PIPE_FACE_FRONT; + case D3D10_DDI_CULL_BACK: + return PIPE_FACE_BACK; + default: + assert(0); + return PIPE_FACE_NONE; + } +} + +static uint +translate_fill_mode(D3D10_DDI_FILL_MODE FillMode) +{ + switch (FillMode) { + case D3D10_DDI_FILL_WIREFRAME: + return PIPE_POLYGON_MODE_LINE; + case D3D10_DDI_FILL_SOLID: + return PIPE_POLYGON_MODE_FILL; + default: + assert(0); + return PIPE_POLYGON_MODE_FILL; + } +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateRasterizerState -- + * + * The CreateRasterizerState function creates a rasterizer state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateRasterizerState( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_DDI_RASTERIZER_DESC *pRasterizerDesc, // IN + D3D10DDI_HRASTERIZERSTATE hRasterizerState, // IN + D3D10DDI_HRTRASTERIZERSTATE hRTRasterizerState) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + RasterizerState *pRasterizerState = CastRasterizerState(hRasterizerState); + + struct pipe_rasterizer_state state; + memset(&state, 0, sizeof state); + + state.flatshade_first = 1; + state.front_ccw = (pRasterizerDesc->FrontCounterClockwise ? 1 : 0); + state.cull_face = translate_cull_mode(pRasterizerDesc->CullMode); + state.fill_front = translate_fill_mode(pRasterizerDesc->FillMode); + state.fill_back = state.fill_front; + state.scissor = (pRasterizerDesc->ScissorEnable ? 1 : 0); + state.line_smooth = (pRasterizerDesc->AntialiasedLineEnable ? 1 : 0); + state.offset_units = (float)pRasterizerDesc->DepthBias; + state.offset_scale = pRasterizerDesc->SlopeScaledDepthBias; + state.offset_clamp = pRasterizerDesc->DepthBiasClamp; + state.multisample = /* pRasterizerDesc->MultisampleEnable */ 0; + state.half_pixel_center = 1; + state.bottom_edge_rule = 0; + state.clip_halfz = 1; + state.depth_clip_near = pRasterizerDesc->DepthClipEnable ? 1 : 0; + state.depth_clip_far = pRasterizerDesc->DepthClipEnable ? 1 : 0; + + state.point_quad_rasterization = 1; + state.point_size = 1.0f; + state.point_tri_clip = 1; + + state.line_width = 1.0f; + + pRasterizerState->handle = pipe->create_rasterizer_state(pipe, &state); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyRasterizerState -- + * + * The DestroyRasterizerState function destroys the specified + * rasterizer state object. The rasterizer state object can be + * destoyed only if it is not currently bound to a display device. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyRasterizerState(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRASTERIZERSTATE hRasterizerState) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + RasterizerState *pRasterizerState = CastRasterizerState(hRasterizerState); + + pipe->delete_rasterizer_state(pipe, pRasterizerState->handle); +} + + +/* + * ---------------------------------------------------------------------- + * + * SetRasterizerState -- + * + * The SetRasterizerState function sets the rasterizer state. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +SetRasterizerState(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRASTERIZERSTATE hRasterizerState) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + void *state = CastPipeRasterizerState(hRasterizerState); + + pipe->bind_rasterizer_state(pipe, state); +} diff --git a/src/gallium/frontends/d3d10umd/Rasterizer.h b/src/gallium/frontends/d3d10umd/Rasterizer.h new file mode 100644 index 00000000000..d78646b3e16 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Rasterizer.h @@ -0,0 +1,62 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Rasterizer.h -- + * Functions that manipulate rasterizer state. + */ + +#ifndef RASTERIZER_H +#define RASTERIZER_H + +#include "DriverIncludes.h" + +void APIENTRY SetViewports( + D3D10DDI_HDEVICE hDevice, UINT NumViewports, UINT ClearViewports, + __in_ecount (NumViewports) const D3D10_DDI_VIEWPORT *pViewports); + +void APIENTRY SetScissorRects( + D3D10DDI_HDEVICE hDevice, UINT NumScissorRects, UINT ClearScissorRects, + __in_ecount (NumRects) const D3D10_DDI_RECT *pRects); + +SIZE_T APIENTRY CalcPrivateRasterizerStateSize( + D3D10DDI_HDEVICE hDevice, + __in const D3D10_DDI_RASTERIZER_DESC *pRasterizerDesc); + +void APIENTRY CreateRasterizerState( + D3D10DDI_HDEVICE hDevice, + __in const D3D10_DDI_RASTERIZER_DESC *pRasterizerDesc, + D3D10DDI_HRASTERIZERSTATE hRasterizerState, + D3D10DDI_HRTRASTERIZERSTATE hRTRasterizerState); + +void APIENTRY DestroyRasterizerState(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HRASTERIZERSTATE hRasterizerState); + +void APIENTRY SetRasterizerState(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HRASTERIZERSTATE hRasterizerState); + +#endif /* RASTERIZER_H */ diff --git a/src/gallium/frontends/d3d10umd/Resource.cpp b/src/gallium/frontends/d3d10umd/Resource.cpp new file mode 100644 index 00000000000..a7910d2e3cf --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Resource.cpp @@ -0,0 +1,880 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Resource.cpp -- + * Functions that manipulate GPU resources. + */ + + +#include "Resource.h" +#include "Format.h" +#include "State.h" +#include "Query.h" + +#include "Debug.h" + +#include "util/u_math.h" +#include "util/u_rect.h" +#include "util/u_surface.h" + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateResourceSize -- + * + * The CalcPrivateResourceSize function determines the size of + * the user-mode display driver's private region of memory + * (that is, the size of internal driver structures, not the + * size of the resource video memory). + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateResourceSize(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATERESOURCE *pCreateResource) // IN +{ + LOG_ENTRYPOINT(); + return sizeof(Resource); +} + + +static unsigned +translate_resource_usage( unsigned usage ) +{ + unsigned resource_usage = 0; + + switch (usage) { + case D3D10_DDI_USAGE_DEFAULT: + resource_usage = PIPE_USAGE_DEFAULT; + break; + case D3D10_DDI_USAGE_IMMUTABLE: + resource_usage = PIPE_USAGE_IMMUTABLE; + break; + case D3D10_DDI_USAGE_DYNAMIC: + resource_usage = PIPE_USAGE_DYNAMIC; + break; + case D3D10_DDI_USAGE_STAGING: + resource_usage = PIPE_USAGE_STAGING; + break; + default: + assert(0); + break; + } + + return resource_usage; +} + + +static unsigned +translate_resource_flags(UINT flags) +{ + unsigned bind = 0; + + if (flags & D3D10_DDI_BIND_VERTEX_BUFFER) + bind |= PIPE_BIND_VERTEX_BUFFER; + + if (flags & D3D10_DDI_BIND_INDEX_BUFFER) + bind |= PIPE_BIND_INDEX_BUFFER; + + if (flags & D3D10_DDI_BIND_CONSTANT_BUFFER) + bind |= PIPE_BIND_CONSTANT_BUFFER; + + if (flags & D3D10_DDI_BIND_SHADER_RESOURCE) + bind |= PIPE_BIND_SAMPLER_VIEW; + + if (flags & D3D10_DDI_BIND_RENDER_TARGET) + bind |= PIPE_BIND_RENDER_TARGET; + + if (flags & D3D10_DDI_BIND_DEPTH_STENCIL) + bind |= PIPE_BIND_DEPTH_STENCIL; + + if (flags & D3D10_DDI_BIND_STREAM_OUTPUT) + bind |= PIPE_BIND_STREAM_OUTPUT; + + return bind; +} + + +static enum pipe_texture_target +translate_texture_target( D3D10DDIRESOURCE_TYPE ResourceDimension, + UINT ArraySize) +{ + assert(ArraySize >= 1); + switch(ResourceDimension) { + case D3D10DDIRESOURCE_BUFFER: + assert(ArraySize == 1); + return PIPE_BUFFER; + case D3D10DDIRESOURCE_TEXTURE1D: + return ArraySize > 1 ? PIPE_TEXTURE_1D_ARRAY : PIPE_TEXTURE_1D; + case D3D10DDIRESOURCE_TEXTURE2D: + return ArraySize > 1 ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D; + case D3D10DDIRESOURCE_TEXTURE3D: + assert(ArraySize == 1); + return PIPE_TEXTURE_3D; + case D3D10DDIRESOURCE_TEXTURECUBE: + assert(ArraySize % 6 == 0); + return ArraySize > 6 ? PIPE_TEXTURE_CUBE_ARRAY : PIPE_TEXTURE_CUBE; + default: + assert(0); + return PIPE_TEXTURE_1D; + } +} + + +static void +subResourceBox(struct pipe_resource *resource, // IN + UINT SubResource, // IN + unsigned *pLevel, // OUT + struct pipe_box *pBox) // OUT +{ + UINT MipLevels = resource->last_level + 1; + unsigned layer; + unsigned width; + unsigned height; + unsigned depth; + + *pLevel = SubResource % MipLevels; + layer = SubResource / MipLevels; + + width = u_minify(resource->width0, *pLevel); + height = u_minify(resource->height0, *pLevel); + depth = u_minify(resource->depth0, *pLevel); + + pBox->x = 0; + pBox->y = 0; + pBox->z = 0 + layer; + pBox->width = width; + pBox->height = height; + pBox->depth = depth; +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateResource -- + * + * The CreateResource function creates a resource. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateResource(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATERESOURCE *pCreateResource, // IN + D3D10DDI_HRESOURCE hResource, // IN + D3D10DDI_HRTRESOURCE hRTResource) // IN +{ + LOG_ENTRYPOINT(); + + if ((pCreateResource->MiscFlags & D3D10_DDI_RESOURCE_MISC_SHARED) || + (pCreateResource->pPrimaryDesc && + pCreateResource->pPrimaryDesc->DriverFlags & DXGI_DDI_PRIMARY_OPTIONAL)) { + + DebugPrintf("%s(%dx%dx%d hResource=%p)\n", + __FUNCTION__, + pCreateResource->pMipInfoList[0].TexelWidth, + pCreateResource->pMipInfoList[0].TexelHeight, + pCreateResource->pMipInfoList[0].TexelDepth, + hResource.pDrvPrivate); + DebugPrintf(" ResourceDimension = %u\n", + pCreateResource->ResourceDimension); + DebugPrintf(" Usage = %u\n", + pCreateResource->Usage); + DebugPrintf(" BindFlags = 0x%x\n", + pCreateResource->BindFlags); + DebugPrintf(" MapFlags = 0x%x\n", + pCreateResource->MapFlags); + DebugPrintf(" MiscFlags = 0x%x\n", + pCreateResource->MiscFlags); + DebugPrintf(" Format = %s\n", + FormatToName(pCreateResource->Format)); + DebugPrintf(" SampleDesc.Count = %u\n", pCreateResource->SampleDesc.Count); + DebugPrintf(" SampleDesc.Quality = %u\n", pCreateResource->SampleDesc.Quality); + DebugPrintf(" MipLevels = %u\n", pCreateResource->MipLevels); + DebugPrintf(" ArraySize = %u\n", pCreateResource->ArraySize); + DebugPrintf(" pPrimaryDesc = %p\n", pCreateResource->pPrimaryDesc); + if (pCreateResource->pPrimaryDesc) { + DebugPrintf(" Flags = 0x%x\n", + pCreateResource->pPrimaryDesc->Flags); + DebugPrintf(" VidPnSourceId = %u\n", pCreateResource->pPrimaryDesc->VidPnSourceId); + DebugPrintf(" ModeDesc.Width = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Width); + DebugPrintf(" ModeDesc.Height = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Height); + DebugPrintf(" ModeDesc.Format = %u)\n", + pCreateResource->pPrimaryDesc->ModeDesc.Format); + DebugPrintf(" ModeDesc.RefreshRate.Numerator = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.RefreshRate.Numerator); + DebugPrintf(" ModeDesc.RefreshRate.Denominator = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.RefreshRate.Denominator); + DebugPrintf(" ModeDesc.ScanlineOrdering = %u\n", + pCreateResource->pPrimaryDesc->ModeDesc.ScanlineOrdering); + DebugPrintf(" ModeDesc.Rotation = %u\n", + pCreateResource->pPrimaryDesc->ModeDesc.Rotation); + DebugPrintf(" ModeDesc.Scaling = %u\n", + pCreateResource->pPrimaryDesc->ModeDesc.Scaling); + DebugPrintf(" DriverFlags = 0x%x\n", + pCreateResource->pPrimaryDesc->DriverFlags); + } + + } + + struct pipe_context *pipe = CastPipeContext(hDevice); + struct pipe_screen *screen = pipe->screen; + + Resource *pResource = CastResource(hResource); + + memset(pResource, 0, sizeof *pResource); + +#if 0 + if (pCreateResource->pPrimaryDesc) { + pCreateResource->pPrimaryDesc->DriverFlags = DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT; + if (!(pCreateResource->pPrimaryDesc->DriverFlags & DXGI_DDI_PRIMARY_OPTIONAL)) { + // http://msdn.microsoft.com/en-us/library/windows/hardware/ff568846.aspx + SetError(hDevice, DXGI_DDI_ERR_UNSUPPORTED); + return; + } + } +#endif + + pResource->Format = pCreateResource->Format; + pResource->MipLevels = pCreateResource->MipLevels; + + struct pipe_resource templat; + + memset(&templat, 0, sizeof templat); + + templat.target = translate_texture_target( pCreateResource->ResourceDimension, + pCreateResource->ArraySize ); + + if (pCreateResource->Format == DXGI_FORMAT_UNKNOWN) { + assert(pCreateResource->ResourceDimension == D3D10DDIRESOURCE_BUFFER); + templat.format = PIPE_FORMAT_R8_UINT; + } else { + BOOL bindDepthStencil = !!(pCreateResource->BindFlags & D3D10_DDI_BIND_DEPTH_STENCIL); + templat.format = FormatTranslate(pCreateResource->Format, bindDepthStencil); + } + + templat.width0 = pCreateResource->pMipInfoList[0].TexelWidth; + templat.height0 = pCreateResource->pMipInfoList[0].TexelHeight; + templat.depth0 = pCreateResource->pMipInfoList[0].TexelDepth; + templat.array_size = pCreateResource->ArraySize; + templat.last_level = pCreateResource->MipLevels - 1; + templat.nr_samples = pCreateResource->SampleDesc.Count; + templat.nr_storage_samples = pCreateResource->SampleDesc.Count; + templat.bind = translate_resource_flags(pCreateResource->BindFlags); + templat.usage = translate_resource_usage(pCreateResource->Usage); + + if (templat.target != PIPE_BUFFER) { + if (!screen->is_format_supported(screen, + templat.format, + templat.target, + templat.nr_samples, + templat.nr_storage_samples, + templat.bind)) { + debug_printf("%s: unsupported format %s\n", + __FUNCTION__, util_format_name(templat.format)); + SetError(hDevice, E_OUTOFMEMORY); + return; + } + } + + pResource->resource = screen->resource_create(screen, &templat); + if (!pResource) { + DebugPrintf("%s: failed to create resource\n", __FUNCTION__); + SetError(hDevice, E_OUTOFMEMORY); + return; + } + + pResource->NumSubResources = pCreateResource->MipLevels * pCreateResource->ArraySize; + pResource->transfers = (struct pipe_transfer **)calloc(pResource->NumSubResources, + sizeof *pResource->transfers); + + if (pCreateResource->pInitialDataUP) { + for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) { + const D3D10_DDIARG_SUBRESOURCE_UP* pInitialDataUP = + &pCreateResource->pInitialDataUP[SubResource]; + + unsigned level; + struct pipe_box box; + subResourceBox(pResource->resource, SubResource, &level, &box); + + struct pipe_transfer *transfer; + void *map; + map = pipe->transfer_map(pipe, + pResource->resource, + level, + PIPE_MAP_WRITE | + PIPE_MAP_UNSYNCHRONIZED, + &box, + &transfer); + assert(map); + if (map) { + for (int z = 0; z < box.depth; ++z) { + ubyte *dst = (ubyte*)map + z*transfer->layer_stride; + const ubyte *src = (const ubyte*)pInitialDataUP->pSysMem + z*pInitialDataUP->SysMemSlicePitch; + util_copy_rect(dst, + templat.format, + transfer->stride, + 0, 0, box.width, box.height, + src, + pInitialDataUP->SysMemPitch, + 0, 0); + } + pipe_transfer_unmap(pipe, transfer); + } + } + } +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateOpenedResourceSize -- + * + * The CalcPrivateOpenedResourceSize function determines the size + * of the user-mode display driver's private shared region of memory + * (that is, the size of internal driver structures, not the size + * of the resource video memory) for an opened resource. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateOpenedResourceSize(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_OPENRESOURCE *pOpenResource) // IN +{ + return sizeof(Resource); +} + + +/* + * ---------------------------------------------------------------------- + * + * OpenResource -- + * + * The OpenResource function opens a shared resource. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +OpenResource(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_OPENRESOURCE *pOpenResource, // IN + D3D10DDI_HRESOURCE hResource, // IN + D3D10DDI_HRTRESOURCE hRTResource) // IN +{ + LOG_UNSUPPORTED_ENTRYPOINT(); + SetError(hDevice, E_OUTOFMEMORY); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyResource -- + * + * The DestroyResource function destroys the specified resource + * object. The resource object can be destoyed only if it is not + * currently bound to a display device, and if all views that + * refer to the resource are also destroyed. + * + * ---------------------------------------------------------------------- + */ + + +void APIENTRY +DestroyResource(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hResource) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + Resource *pResource = CastResource(hResource); + + if (pResource->so_target) { + pipe_so_target_reference(&pResource->so_target, NULL); + } + + for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) { + if (pResource->transfers[SubResource]) { + pipe_transfer_unmap(pipe, pResource->transfers[SubResource]); + pResource->transfers[SubResource] = NULL; + } + } + free(pResource->transfers); + + pipe_resource_reference(&pResource->resource, NULL); +} + + +/* + * ---------------------------------------------------------------------- + * + * ResourceMap -- + * + * The ResourceMap function maps a subresource of a resource. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ResourceMap(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hResource, // IN + UINT SubResource, // IN + D3D10_DDI_MAP DDIMap, // IN + UINT Flags, // IN + __out D3D10DDI_MAPPED_SUBRESOURCE *pMappedSubResource) // OUT +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + Resource *pResource = CastResource(hResource); + struct pipe_resource *resource = pResource->resource; + + unsigned usage; + switch (DDIMap) { + case D3D10_DDI_MAP_READ: + usage = PIPE_MAP_READ; + break; + case D3D10_DDI_MAP_READWRITE: + usage = PIPE_MAP_READ | PIPE_MAP_WRITE; + break; + case D3D10_DDI_MAP_WRITE: + usage = PIPE_MAP_WRITE; + break; + case D3D10_DDI_MAP_WRITE_DISCARD: + usage = PIPE_MAP_WRITE; + if (resource->last_level == 0 && resource->array_size == 1) { + usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE; + } else { + usage |= PIPE_MAP_DISCARD_RANGE; + } + break; + case D3D10_DDI_MAP_WRITE_NOOVERWRITE: + usage = PIPE_MAP_WRITE | PIPE_MAP_UNSYNCHRONIZED; + break; + default: + assert(0); + return; + } + + assert(SubResource < pResource->NumSubResources); + + unsigned level; + struct pipe_box box; + subResourceBox(resource, SubResource, &level, &box); + + assert(!pResource->transfers[SubResource]); + + void *map; + map = pipe->transfer_map(pipe, + resource, + level, + usage, + &box, + &pResource->transfers[SubResource]); + if (!map) { + DebugPrintf("%s: failed to map resource\n", __FUNCTION__); + SetError(hDevice, E_FAIL); + return; + } + + pMappedSubResource->pData = map; + pMappedSubResource->RowPitch = pResource->transfers[SubResource]->stride; + pMappedSubResource->DepthPitch = pResource->transfers[SubResource]->layer_stride; +} + + +/* + * ---------------------------------------------------------------------- + * + * ResourceUnmap -- + * + * The ResourceUnmap function unmaps a subresource of a resource. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ResourceUnmap(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hResource, // IN + UINT SubResource) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + Resource *pResource = CastResource(hResource); + + assert(SubResource < pResource->NumSubResources); + + if (pResource->transfers[SubResource]) { + pipe_transfer_unmap(pipe, pResource->transfers[SubResource]); + pResource->transfers[SubResource] = NULL; + } +} + + +/* + *---------------------------------------------------------------------- + * + * areResourcesCompatible -- + * + * Check whether two resources can be safely passed to + * pipe_context::resource_copy_region method. + * + * Results: + * As above. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static bool +areResourcesCompatible(const struct pipe_resource *src_resource, // IN + const struct pipe_resource *dst_resource) // IN +{ + if (src_resource->format == dst_resource->format) { + /* + * Trivial. + */ + + return TRUE; + } else if (src_resource->target == PIPE_BUFFER && + dst_resource->target == PIPE_BUFFER) { + /* + * Buffer resources are merely a collection of bytes. + */ + + return TRUE; + } else { + /* + * Check whether the formats are supported by + * the resource_copy_region method. + */ + + const struct util_format_description *src_format_desc; + const struct util_format_description *dst_format_desc; + + src_format_desc = util_format_description(src_resource->format); + dst_format_desc = util_format_description(dst_resource->format); + + assert(src_format_desc->block.width == dst_format_desc->block.width); + assert(src_format_desc->block.height == dst_format_desc->block.height); + assert(src_format_desc->block.bits == dst_format_desc->block.bits); + + return util_is_format_compatible(src_format_desc, dst_format_desc); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * ResourceCopy -- + * + * The ResourceCopy function copies an entire source + * resource to a destination resource. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ResourceCopy(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hDstResource, // IN + D3D10DDI_HRESOURCE hSrcResource) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + if (!CheckPredicate(pDevice)) { + return; + } + + struct pipe_context *pipe = pDevice->pipe; + Resource *pDstResource = CastResource(hDstResource); + Resource *pSrcResource = CastResource(hSrcResource); + struct pipe_resource *dst_resource = pDstResource->resource; + struct pipe_resource *src_resource = pSrcResource->resource; + bool compatible; + + assert(dst_resource->target == src_resource->target); + assert(dst_resource->width0 == src_resource->width0); + assert(dst_resource->height0 == src_resource->height0); + assert(dst_resource->depth0 == src_resource->depth0); + assert(dst_resource->last_level == src_resource->last_level); + assert(dst_resource->array_size == src_resource->array_size); + + compatible = areResourcesCompatible(src_resource, dst_resource); + + /* could also use one 3d copy for arrays */ + for (unsigned layer = 0; layer < dst_resource->array_size; ++layer) { + for (unsigned level = 0; level <= dst_resource->last_level; ++level) { + struct pipe_box box; + box.x = 0; + box.y = 0; + box.z = 0 + layer; + box.width = u_minify(dst_resource->width0, level); + box.height = u_minify(dst_resource->height0, level); + box.depth = u_minify(dst_resource->depth0, level); + + if (compatible) { + pipe->resource_copy_region(pipe, + dst_resource, level, + 0, 0, layer, + src_resource, level, + &box); + } else { + util_resource_copy_region(pipe, + dst_resource, level, + 0, 0, layer, + src_resource, level, + &box); + } + } + } +} + + +/* + * ---------------------------------------------------------------------- + * + * ResourceCopyRegion -- + * + * The ResourceCopyRegion function copies a source subresource + * region to a location on a destination subresource. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ResourceCopyRegion(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hDstResource, // IN + UINT DstSubResource, // IN + UINT DstX, // IN + UINT DstY, // IN + UINT DstZ, // IN + D3D10DDI_HRESOURCE hSrcResource, // IN + UINT SrcSubResource, // IN + __in_opt const D3D10_DDI_BOX *pSrcBox) // IN (optional) +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + if (!CheckPredicate(pDevice)) { + return; + } + + struct pipe_context *pipe = pDevice->pipe; + Resource *pDstResource = CastResource(hDstResource); + Resource *pSrcResource = CastResource(hSrcResource); + struct pipe_resource *dst_resource = pDstResource->resource; + struct pipe_resource *src_resource = pSrcResource->resource; + + unsigned dst_level = DstSubResource % (dst_resource->last_level + 1); + unsigned dst_layer = DstSubResource / (dst_resource->last_level + 1); + unsigned src_level = SrcSubResource % (src_resource->last_level + 1); + unsigned src_layer = SrcSubResource / (src_resource->last_level + 1); + + struct pipe_box src_box; + if (pSrcBox) { + src_box.x = pSrcBox->left; + src_box.y = pSrcBox->top; + src_box.z = pSrcBox->front + src_layer; + src_box.width = pSrcBox->right - pSrcBox->left; + src_box.height = pSrcBox->bottom - pSrcBox->top; + src_box.depth = pSrcBox->back - pSrcBox->front; + } else { + src_box.x = 0; + src_box.y = 0; + src_box.z = 0 + src_layer; + src_box.width = u_minify(src_resource->width0, src_level); + src_box.height = u_minify(src_resource->height0, src_level); + src_box.depth = u_minify(src_resource->depth0, src_level); + } + + if (areResourcesCompatible(src_resource, dst_resource)) { + pipe->resource_copy_region(pipe, + dst_resource, dst_level, + DstX, DstY, DstZ + dst_layer, + src_resource, src_level, + &src_box); + } else { + util_resource_copy_region(pipe, + dst_resource, dst_level, + DstX, DstY, DstZ + dst_layer, + src_resource, src_level, + &src_box); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * ResourceResolveSubResource -- + * + * The ResourceResolveSubResource function resolves + * multiple samples to one pixel. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ResourceResolveSubResource(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hDstResource, // IN + UINT DstSubResource, // IN + D3D10DDI_HRESOURCE hSrcResource, // IN + UINT SrcSubResource, // IN + DXGI_FORMAT ResolveFormat) // IN +{ + LOG_UNSUPPORTED_ENTRYPOINT(); +} + + +/* + * ---------------------------------------------------------------------- + * + * ResourceIsStagingBusy -- + * + * The ResourceIsStagingBusy function determines whether a + * resource is currently being used by the graphics pipeline. + * + * ---------------------------------------------------------------------- + */ + +BOOL APIENTRY +ResourceIsStagingBusy(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hResource) // IN +{ + LOG_ENTRYPOINT(); + + /* ignore */ + + return FALSE; +} + + +/* + * ---------------------------------------------------------------------- + * + * ResourceReadAfterWriteHazard -- + * + * The ResourceReadAfterWriteHazard function informs the user-mode + * display driver that the specified resource was used as an output + * from the graphics processing unit (GPU) and that the resource + * will be used as an input to the GPU. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ResourceReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hResource) // IN +{ + LOG_ENTRYPOINT(); + + /* Not actually necessary */ +} + + +/* + * ---------------------------------------------------------------------- + * + * ResourceUpdateSubResourceUP -- + * + * The ResourceUpdateSubresourceUP function updates a + * destination subresource region from a source + * system memory region. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ResourceUpdateSubResourceUP(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HRESOURCE hDstResource, // IN + UINT DstSubResource, // IN + __in_opt const D3D10_DDI_BOX *pDstBox, // IN + __in const void *pSysMemUP, // IN + UINT RowPitch, // IN + UINT DepthPitch) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + if (!CheckPredicate(pDevice)) { + return; + } + + struct pipe_context *pipe = pDevice->pipe; + struct pipe_resource *dst_resource = CastPipeResource(hDstResource); + + unsigned level; + struct pipe_box box; + + if (pDstBox) { + UINT DstMipLevels = dst_resource->last_level + 1; + level = DstSubResource % DstMipLevels; + unsigned dst_layer = DstSubResource / DstMipLevels; + box.x = pDstBox->left; + box.y = pDstBox->top; + box.z = pDstBox->front + dst_layer; + box.width = pDstBox->right - pDstBox->left; + box.height = pDstBox->bottom - pDstBox->top; + box.depth = pDstBox->back - pDstBox->front; + } else { + subResourceBox(dst_resource, DstSubResource, &level, &box); + } + + struct pipe_transfer *transfer; + void *map; + map = pipe->transfer_map(pipe, + dst_resource, + level, + PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE, + &box, + &transfer); + assert(map); + if (map) { + for (int z = 0; z < box.depth; ++z) { + ubyte *dst = (ubyte*)map + z*transfer->layer_stride; + const ubyte *src = (const ubyte*)pSysMemUP + z*DepthPitch; + util_copy_rect(dst, + dst_resource->format, + transfer->stride, + 0, 0, box.width, box.height, + src, + RowPitch, + 0, 0); + } + pipe_transfer_unmap(pipe, transfer); + } +} + diff --git a/src/gallium/frontends/d3d10umd/Resource.h b/src/gallium/frontends/d3d10umd/Resource.h new file mode 100644 index 00000000000..2cd2ff3d294 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Resource.h @@ -0,0 +1,93 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Resource.h -- + * Functions that manipulate GPU resources. + */ + +#ifndef RESOURCE_H +#define RESOURCE_H + +#include "DriverIncludes.h" + +SIZE_T APIENTRY CalcPrivateResourceSize( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATERESOURCE *pCreateResource); + +void APIENTRY CreateResource( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATERESOURCE *pCreateResource, + D3D10DDI_HRESOURCE hResource, + D3D10DDI_HRTRESOURCE hRTResource); + +SIZE_T APIENTRY CalcPrivateOpenedResourceSize( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_OPENRESOURCE *pOpenResource); + +void APIENTRY OpenResource( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_OPENRESOURCE *pOpenResource, + D3D10DDI_HRESOURCE hResource, + D3D10DDI_HRTRESOURCE hRTResource); + +void APIENTRY DestroyResource(D3D10DDI_HDEVICE hDevice, D3D10DDI_HRESOURCE hResource); + +void APIENTRY ResourceMap(D3D10DDI_HDEVICE hDevice, D3D10DDI_HRESOURCE hResource, + UINT SubResource, D3D10_DDI_MAP DDIMap, UINT Flags, + __out D3D10DDI_MAPPED_SUBRESOURCE *pMappedSubResource); + +void APIENTRY ResourceUnmap(D3D10DDI_HDEVICE hDevice, D3D10DDI_HRESOURCE hResource, + UINT SubResource); + +void APIENTRY ResourceCopy(D3D10DDI_HDEVICE hDevice, D3D10DDI_HRESOURCE hDstResource, + D3D10DDI_HRESOURCE hSrcResource); + +void APIENTRY ResourceCopyRegion(D3D10DDI_HDEVICE hDevice, D3D10DDI_HRESOURCE hResource, + UINT DstSubResource, UINT DstX, UINT DstY, UINT DstZ, + D3D10DDI_HRESOURCE hSrcResource, UINT SrcSubResource, + __in_opt const D3D10_DDI_BOX *pSrcBox); + +void APIENTRY ResourceResolveSubResource(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HRESOURCE hDstResource, + UINT DstSubResource, + D3D10DDI_HRESOURCE hSrcResource, + UINT SrcSubResource, + DXGI_FORMAT ResolveFormat); + +BOOL APIENTRY ResourceIsStagingBusy(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HRESOURCE hResource); + +void APIENTRY ResourceReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HRESOURCE hResource); + +void APIENTRY ResourceUpdateSubResourceUP( + D3D10DDI_HDEVICE hDevice, D3D10DDI_HRESOURCE hResource, + UINT DstSubResource, __in_opt const D3D10_DDI_BOX *pDstBox, + __in const void *pSysMemUP, UINT RowPitch, UINT DepthPitch); + +#endif /* RESOURCE_H */ diff --git a/src/gallium/frontends/d3d10umd/Shader.cpp b/src/gallium/frontends/d3d10umd/Shader.cpp new file mode 100644 index 00000000000..ce5d0edd335 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Shader.cpp @@ -0,0 +1,1414 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Shader.cpp -- + * Functions that manipulate shader resources. + */ + + +#include "Shader.h" +#include "ShaderParse.h" +#include "State.h" +#include "Query.h" + +#include "Debug.h" +#include "Format.h" + +#include "tgsi/tgsi_ureg.h" +#include "util/u_gen_mipmap.h" +#include "util/u_sampler.h" +#include "util/format/u_format.h" + + +/* + * ---------------------------------------------------------------------- + * + * CreateEmptyShader -- + * + * Update the driver's currently bound constant buffers. + * + * ---------------------------------------------------------------------- + */ + +void * +CreateEmptyShader(Device *pDevice, + enum pipe_shader_type processor) +{ + struct pipe_context *pipe = pDevice->pipe; + struct ureg_program *ureg; + const struct tgsi_token *tokens; + uint nr_tokens; + + if (processor == PIPE_SHADER_GEOMETRY) { + return NULL; + } + + ureg = ureg_create(processor); + if (!ureg) + return NULL; + + ureg_END(ureg); + + tokens = ureg_get_tokens(ureg, &nr_tokens); + if (!tokens) + return NULL; + + ureg_destroy(ureg); + + struct pipe_shader_state state; + memset(&state, 0, sizeof state); + state.tokens = tokens; + + void *handle; + switch (processor) { + case PIPE_SHADER_FRAGMENT: + handle = pipe->create_fs_state(pipe, &state); + break; + case PIPE_SHADER_VERTEX: + handle = pipe->create_vs_state(pipe, &state); + break; + case PIPE_SHADER_GEOMETRY: + handle = pipe->create_gs_state(pipe, &state); + break; + default: + handle = NULL; + assert(0); + } + assert(handle); + + ureg_free_tokens(tokens); + + return handle; +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateEmptyShader -- + * + * Update the driver's currently bound constant buffers. + * + * ---------------------------------------------------------------------- + */ + +void +DeleteEmptyShader(Device *pDevice, + enum pipe_shader_type processor, void *handle) +{ + struct pipe_context *pipe = pDevice->pipe; + + if (processor == PIPE_SHADER_GEOMETRY) { + assert(handle == NULL); + return; + } + + assert(handle != NULL); + switch (processor) { + case PIPE_SHADER_FRAGMENT: + pipe->delete_fs_state(pipe, handle); + break; + case PIPE_SHADER_VERTEX: + pipe->delete_vs_state(pipe, handle); + break; + case PIPE_SHADER_GEOMETRY: + pipe->delete_gs_state(pipe, handle); + break; + default: + assert(0); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * SetConstantBuffers -- + * + * Update the driver's currently bound constant buffers. + * + * ---------------------------------------------------------------------- + */ + +static void +SetConstantBuffers(enum pipe_shader_type shader_type, // IN + D3D10DDI_HDEVICE hDevice, // IN + UINT StartBuffer, // IN + UINT NumBuffers, // IN + const D3D10DDI_HRESOURCE *phBuffers) // IN +{ + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + + for (UINT i = 0; i < NumBuffers; i++) { + struct pipe_constant_buffer cb; + memset(&cb, 0, sizeof cb); + cb.buffer = CastPipeResource(phBuffers[i]); + cb.buffer_offset = 0; + cb.buffer_size = cb.buffer ? cb.buffer->width0 : 0; + pipe->set_constant_buffer(pipe, + shader_type, + StartBuffer + i, + FALSE, + &cb); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * SetSamplers -- + * + * Update the driver's currently bound sampler state. + * + * ---------------------------------------------------------------------- + */ + +static void +SetSamplers(enum pipe_shader_type shader_type, // IN + D3D10DDI_HDEVICE hDevice, // IN + UINT Offset, // IN + UINT NumSamplers, // IN + const D3D10DDI_HSAMPLER *phSamplers) // IN +{ + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + + void **samplers = pDevice->samplers[shader_type]; + for (UINT i = 0; i < NumSamplers; i++) { + assert(Offset + i < PIPE_MAX_SAMPLERS); + samplers[Offset + i] = CastPipeSamplerState(phSamplers[i]); + } + + pipe->bind_sampler_states(pipe, shader_type, 0, PIPE_MAX_SAMPLERS, samplers); +} + + +/* + * ---------------------------------------------------------------------- + * + * SetSamplers -- + * + * Update the driver's currently bound sampler state. + * + * ---------------------------------------------------------------------- + */ + +static void +SetShaderResources(enum pipe_shader_type shader_type, // IN + D3D10DDI_HDEVICE hDevice, // IN + UINT Offset, // IN + UINT NumViews, // IN + const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews) // IN +{ + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + + assert(Offset + NumViews <= D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT); + + struct pipe_sampler_view **sampler_views = pDevice->sampler_views[shader_type]; + for (UINT i = 0; i < NumViews; i++) { + struct pipe_sampler_view *sampler_view = + CastPipeShaderResourceView(phShaderResourceViews[i]); + if (Offset + i < PIPE_MAX_SHADER_SAMPLER_VIEWS) { + sampler_views[Offset + i] = sampler_view; + } else { + if (sampler_view) { + LOG_UNSUPPORTED(TRUE); + break; + } + } + } + + /* + * XXX: Now that the semantics are actually the same in gallium, should + * probably think about not updating all always... It should just work. + */ + pipe->set_sampler_views(pipe, shader_type, 0, PIPE_MAX_SHADER_SAMPLER_VIEWS, + 0, sampler_views); +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateShaderSize -- + * + * The CalcPrivateShaderSize function determines the size of + * the user-mode display driver's private region of memory + * (that is, the size of internal driver structures, not the + * size of the resource video memory) for a shader. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateShaderSize(D3D10DDI_HDEVICE hDevice, // IN + __in_ecount (pShaderCode[1]) const UINT *pShaderCode, // IN + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN +{ + return sizeof(Shader); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyShader -- + * + * The DestroyShader function destroys the specified shader object. + * The shader object can be destoyed only if it is not currently + * bound to a display device. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyShader(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HSHADER hShader) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + Shader *pShader = CastShader(hShader); + + if (pShader->handle) { + switch (pShader->type) { + case PIPE_SHADER_FRAGMENT: + pipe->delete_fs_state(pipe, pShader->handle); + break; + case PIPE_SHADER_VERTEX: + pipe->delete_vs_state(pipe, pShader->handle); + break; + case PIPE_SHADER_GEOMETRY: + pipe->delete_gs_state(pipe, pShader->handle); + break; + default: + assert(0); + } + } + + if (pShader->state.tokens) { + ureg_free_tokens(pShader->state.tokens); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateSamplerSize -- + * + * The CalcPrivateSamplerSize function determines the size of the + * user-mode display driver's private region of memory (that is, + * the size of internal driver structures, not the size of the + * resource video memory) for a sampler. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateSamplerSize(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_DDI_SAMPLER_DESC *pSamplerDesc) // IN +{ + return sizeof(SamplerState); +} + + +static uint +translate_address_mode(D3D10_DDI_TEXTURE_ADDRESS_MODE AddressMode) +{ + switch (AddressMode) { + case D3D10_DDI_TEXTURE_ADDRESS_WRAP: + return PIPE_TEX_WRAP_REPEAT; + case D3D10_DDI_TEXTURE_ADDRESS_MIRROR: + return PIPE_TEX_WRAP_MIRROR_REPEAT; + case D3D10_DDI_TEXTURE_ADDRESS_CLAMP: + return PIPE_TEX_WRAP_CLAMP_TO_EDGE; + case D3D10_DDI_TEXTURE_ADDRESS_BORDER: + return PIPE_TEX_WRAP_CLAMP_TO_BORDER; + case D3D10_DDI_TEXTURE_ADDRESS_MIRRORONCE: + return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; + default: + assert(0); + return PIPE_TEX_WRAP_REPEAT; + } +} + +static uint +translate_comparison(D3D10_DDI_COMPARISON_FUNC Func) +{ + switch (Func) { + case D3D10_DDI_COMPARISON_NEVER: + return PIPE_FUNC_NEVER; + case D3D10_DDI_COMPARISON_LESS: + return PIPE_FUNC_LESS; + case D3D10_DDI_COMPARISON_EQUAL: + return PIPE_FUNC_EQUAL; + case D3D10_DDI_COMPARISON_LESS_EQUAL: + return PIPE_FUNC_LEQUAL; + case D3D10_DDI_COMPARISON_GREATER: + return PIPE_FUNC_GREATER; + case D3D10_DDI_COMPARISON_NOT_EQUAL: + return PIPE_FUNC_NOTEQUAL; + case D3D10_DDI_COMPARISON_GREATER_EQUAL: + return PIPE_FUNC_GEQUAL; + case D3D10_DDI_COMPARISON_ALWAYS: + return PIPE_FUNC_ALWAYS; + default: + assert(0); + return PIPE_FUNC_ALWAYS; + } +} + +static uint +translate_filter(D3D10_DDI_FILTER_TYPE Filter) +{ + switch (Filter) { + case D3D10_DDI_FILTER_TYPE_POINT: + return PIPE_TEX_FILTER_NEAREST; + case D3D10_DDI_FILTER_TYPE_LINEAR: + return PIPE_TEX_FILTER_LINEAR; + default: + assert(0); + return PIPE_TEX_FILTER_NEAREST; + } +} + +static uint +translate_min_filter(D3D10_DDI_FILTER Filter) +{ + return translate_filter(D3D10_DDI_DECODE_MIN_FILTER(Filter)); +} + +static uint +translate_mag_filter(D3D10_DDI_FILTER Filter) +{ + return translate_filter(D3D10_DDI_DECODE_MAG_FILTER(Filter)); +} + +/* Gallium uses a different enum for mipfilters, to accomodate the GL + * MIPFILTER_NONE mode. + */ +static uint +translate_mip_filter(D3D10_DDI_FILTER Filter) +{ + switch (D3D10_DDI_DECODE_MIP_FILTER(Filter)) { + case D3D10_DDI_FILTER_TYPE_POINT: + return PIPE_TEX_MIPFILTER_NEAREST; + case D3D10_DDI_FILTER_TYPE_LINEAR: + return PIPE_TEX_MIPFILTER_LINEAR; + default: + assert(0); + return PIPE_TEX_MIPFILTER_NEAREST; + } +} + +/* + * ---------------------------------------------------------------------- + * + * CreateSampler -- + * + * The CreateSampler function creates a sampler. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateSampler(D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_DDI_SAMPLER_DESC *pSamplerDesc, // IN + D3D10DDI_HSAMPLER hSampler, // IN + D3D10DDI_HRTSAMPLER hRTSampler) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + SamplerState *pSamplerState = CastSamplerState(hSampler); + + struct pipe_sampler_state state; + + memset(&state, 0, sizeof state); + + /* d3d10 has seamless cube filtering always enabled */ + state.seamless_cube_map = 1; + + /* Wrapping modes. */ + state.wrap_s = translate_address_mode(pSamplerDesc->AddressU); + state.wrap_t = translate_address_mode(pSamplerDesc->AddressV); + state.wrap_r = translate_address_mode(pSamplerDesc->AddressW); + + /* Filtering */ + state.min_img_filter = translate_min_filter(pSamplerDesc->Filter); + state.mag_img_filter = translate_mag_filter(pSamplerDesc->Filter); + state.min_mip_filter = translate_mip_filter(pSamplerDesc->Filter); + + if (D3D10_DDI_DECODE_IS_ANISOTROPIC_FILTER(pSamplerDesc->Filter)) { + state.max_anisotropy = pSamplerDesc->MaxAnisotropy; + } + + /* XXX: Handle the following bit. + */ + LOG_UNSUPPORTED(D3D10_DDI_DECODE_IS_TEXT_1BIT_FILTER(pSamplerDesc->Filter)); + + /* Comparison. */ + if (D3D10_DDI_DECODE_IS_COMPARISON_FILTER(pSamplerDesc->Filter)) { + state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; + state.compare_func = translate_comparison(pSamplerDesc->ComparisonFunc); + } + + state.normalized_coords = 1; + + /* Level of detail. */ + state.lod_bias = pSamplerDesc->MipLODBias; + state.min_lod = pSamplerDesc->MinLOD; + state.max_lod = pSamplerDesc->MaxLOD; + + /* Border color. */ + state.border_color.f[0] = pSamplerDesc->BorderColor[0]; + state.border_color.f[1] = pSamplerDesc->BorderColor[1]; + state.border_color.f[2] = pSamplerDesc->BorderColor[2]; + state.border_color.f[3] = pSamplerDesc->BorderColor[3]; + + pSamplerState->handle = pipe->create_sampler_state(pipe, &state); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroySampler -- + * + * The DestroySampler function destroys the specified sampler object. + * The sampler object can be destoyed only if it is not currently + * bound to a display device. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroySampler(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HSAMPLER hSampler) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + SamplerState *pSamplerState = CastSamplerState(hSampler); + + pipe->delete_sampler_state(pipe, pSamplerState->handle); +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateVertexShader -- + * + * The CreateVertexShader function creates a vertex shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateVertexShader(D3D10DDI_HDEVICE hDevice, // IN + __in_ecount (pShaderCode[1]) const UINT *pCode, // IN + D3D10DDI_HSHADER hShader, // IN + D3D10DDI_HRTSHADER hRTShader, // IN + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + Shader *pShader = CastShader(hShader); + + pShader->type = PIPE_SHADER_VERTEX; + pShader->output_resolved = TRUE; + + memset(&pShader->state, 0, sizeof pShader->state); + pShader->state.tokens = Shader_tgsi_translate(pCode, pShader->output_mapping); + + pShader->handle = pipe->create_vs_state(pipe, &pShader->state); + +} + + +/* + * ---------------------------------------------------------------------- + * + * VsSetShader -- + * + * The VsSetShader function sets the vertex shader code so that all + * of the subsequent drawing operations use that code. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +VsSetShader(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HSHADER hShader) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + Shader *pShader = CastShader(hShader); + void *state = CastPipeShader(hShader); + + pDevice->bound_vs = pShader; + if (!state) { + state = pDevice->empty_vs; + } + + pipe->bind_vs_state(pipe, state); +} + + +/* + * ---------------------------------------------------------------------- + * + * VsSetShaderResources -- + * + * The VsSetShaderResources function sets resources for a + * vertex shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +VsSetShaderResources(D3D10DDI_HDEVICE hDevice, // IN + UINT Offset, // IN + UINT NumViews, // IN + __in_ecount (NumViews) + const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews) // IN +{ + LOG_ENTRYPOINT(); + + SetShaderResources(PIPE_SHADER_VERTEX, hDevice, Offset, NumViews, phShaderResourceViews); + +} + + +/* + * ---------------------------------------------------------------------- + * + * VsSetConstantBuffers -- + * + * The VsSetConstantBuffers function sets constant buffers + * for a vertex shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +VsSetConstantBuffers(D3D10DDI_HDEVICE hDevice, // IN + UINT StartBuffer, // IN + UINT NumBuffers, // IN + __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers) // IN +{ + LOG_ENTRYPOINT(); + + SetConstantBuffers(PIPE_SHADER_VERTEX, + hDevice, StartBuffer, NumBuffers, phBuffers); +} + + +/* + * ---------------------------------------------------------------------- + * + * VsSetSamplers -- + * + * The VsSetSamplers function sets samplers for a vertex shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +VsSetSamplers(D3D10DDI_HDEVICE hDevice, // IN + UINT Offset, // IN + UINT NumSamplers, // IN + __in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers) // IN +{ + LOG_ENTRYPOINT(); + + SetSamplers(PIPE_SHADER_VERTEX, hDevice, Offset, NumSamplers, phSamplers); + +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateGeometryShader -- + * + * The CreateGeometryShader function creates a geometry shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateGeometryShader(D3D10DDI_HDEVICE hDevice, // IN + __in_ecount (pShaderCode[1]) const UINT *pShaderCode, // IN + D3D10DDI_HSHADER hShader, // IN + D3D10DDI_HRTSHADER hRTShader, // IN + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + Shader *pShader = CastShader(hShader); + + pShader->type = PIPE_SHADER_GEOMETRY; + pShader->output_resolved = TRUE; + + memset(&pShader->state, 0, sizeof pShader->state); + pShader->state.tokens = Shader_tgsi_translate(pShaderCode, pShader->output_mapping); + + pShader->handle = pipe->create_gs_state(pipe, &pShader->state); +} + + +/* + * ---------------------------------------------------------------------- + * + * GsSetShader -- + * + * The GsSetShader function sets the geometry shader code so that + * all of the subsequent drawing operations use that code. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +GsSetShader(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HSHADER hShader) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = CastPipeContext(hDevice); + void *state = CastPipeShader(hShader); + Shader *pShader = CastShader(hShader); + + assert(pipe->bind_gs_state); + + if (pShader && !pShader->state.tokens) { + pDevice->bound_empty_gs = pShader; + } else { + pDevice->bound_empty_gs = NULL; + pipe->bind_gs_state(pipe, state); + } +} + + +/* + * ---------------------------------------------------------------------- + * + * GsSetShaderResources -- + * + * The GsSetShaderResources function sets resources for a + * geometry shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +GsSetShaderResources(D3D10DDI_HDEVICE hDevice, // IN + UINT Offset, // IN + UINT NumViews, // IN + __in_ecount (NumViews) + const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews) // IN +{ + LOG_ENTRYPOINT(); + + SetShaderResources(PIPE_SHADER_GEOMETRY, hDevice, Offset, NumViews, phShaderResourceViews); +} + + +/* + * ---------------------------------------------------------------------- + * + * GsSetConstantBuffers -- + * + * The GsSetConstantBuffers function sets constant buffers for + * a geometry shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +GsSetConstantBuffers(D3D10DDI_HDEVICE hDevice, // IN + UINT StartBuffer, // IN + UINT NumBuffers, // IN + __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers) // IN +{ + LOG_ENTRYPOINT(); + + SetConstantBuffers(PIPE_SHADER_GEOMETRY, + hDevice, StartBuffer, NumBuffers, phBuffers); +} + + +/* + * ---------------------------------------------------------------------- + * + * GsSetSamplers -- + * + * The GsSetSamplers function sets samplers for a geometry shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +GsSetSamplers(D3D10DDI_HDEVICE hDevice, // IN + UINT Offset, // IN + UINT NumSamplers, // IN + __in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers) // IN +{ + LOG_ENTRYPOINT(); + + SetSamplers(PIPE_SHADER_GEOMETRY, hDevice, Offset, NumSamplers, phSamplers); +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateGeometryShaderWithStreamOutput -- + * + * The CalcPrivateGeometryShaderWithStreamOutput function determines + * the size of the user-mode display driver's private region of memory + * (that is, the size of internal driver structures, not the size of + * the resource video memory) for a geometry shader with stream output. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateGeometryShaderWithStreamOutput( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATEGEOMETRYSHADERWITHSTREAMOUTPUT *pCreateGeometryShaderWithStreamOutput, // IN + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN +{ + LOG_ENTRYPOINT(); + return sizeof(Shader); +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateGeometryShaderWithStreamOutput -- + * + * The CreateGeometryShaderWithStreamOutput function creates a + * geometry shader with stream output. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateGeometryShaderWithStreamOutput( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATEGEOMETRYSHADERWITHSTREAMOUTPUT *pData, // IN + D3D10DDI_HSHADER hShader, // IN + D3D10DDI_HRTSHADER hRTShader, // IN + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + Shader *pShader = CastShader(hShader); + int total_components[PIPE_MAX_SO_BUFFERS] = {0}; + unsigned num_holes = 0; + boolean all_slot_zero = TRUE; + + pShader->type = PIPE_SHADER_GEOMETRY; + + memset(&pShader->state, 0, sizeof pShader->state); + if (pData->pShaderCode) { + pShader->state.tokens = Shader_tgsi_translate(pData->pShaderCode, + pShader->output_mapping); + } + pShader->output_resolved = (pShader->state.tokens != NULL); + + for (unsigned i = 0; i < pData->NumEntries; ++i) { + CONST D3D10DDIARG_STREAM_OUTPUT_DECLARATION_ENTRY* pOutputStreamDecl = + &pData->pOutputStreamDecl[i]; + BYTE RegisterMask = pOutputStreamDecl->RegisterMask; + unsigned start_component = 0; + unsigned num_components = 0; + if (RegisterMask) { + while ((RegisterMask & 1) == 0) { + ++start_component; + RegisterMask >>= 1; + } + while (RegisterMask) { + ++num_components; + RegisterMask >>= 1; + } + assert(start_component < 4); + assert(1 <= num_components && num_components <= 4); + LOG_UNSUPPORTED(((1 << num_components) - 1) << start_component != + pOutputStreamDecl->RegisterMask); + } + + if (pOutputStreamDecl->RegisterIndex == 0xffffffff) { + ++num_holes; + } else { + unsigned idx = i - num_holes; + pShader->state.stream_output.output[idx].start_component = + start_component; + pShader->state.stream_output.output[idx].num_components = + num_components; + pShader->state.stream_output.output[idx].output_buffer = + pOutputStreamDecl->OutputSlot; + pShader->state.stream_output.output[idx].register_index = + ShaderFindOutputMapping(pShader, pOutputStreamDecl->RegisterIndex); + pShader->state.stream_output.output[idx].dst_offset = + total_components[pOutputStreamDecl->OutputSlot]; + if (pOutputStreamDecl->OutputSlot != 0) + all_slot_zero = FALSE; + } + total_components[pOutputStreamDecl->OutputSlot] += num_components; + } + pShader->state.stream_output.num_outputs = pData->NumEntries - num_holes; + for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; ++i) { + /* stream_output.stride[i] is in dwords */ + if (all_slot_zero) { + pShader->state.stream_output.stride[i] = + pData->StreamOutputStrideInBytes / sizeof(float); + } else { + pShader->state.stream_output.stride[i] = total_components[i]; + } + } + + pShader->handle = pipe->create_gs_state(pipe, &pShader->state); +} + + +/* + * ---------------------------------------------------------------------- + * + * SoSetTargets -- + * + * The SoSetTargets function sets stream output target resources. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +SoSetTargets(D3D10DDI_HDEVICE hDevice, // IN + UINT SOTargets, // IN + UINT ClearTargets, // IN + __in_ecount (SOTargets) const D3D10DDI_HRESOURCE *phResource, // IN + __in_ecount (SOTargets) const UINT *pOffsets) // IN +{ + unsigned i; + + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + + assert(SOTargets + ClearTargets <= PIPE_MAX_SO_BUFFERS); + + for (i = 0; i < SOTargets; ++i) { + Resource *resource = CastResource(phResource[i]); + struct pipe_resource *buffer = CastPipeResource(phResource[i]); + struct pipe_stream_output_target *so_target = + resource ? resource->so_target : NULL; + + if (buffer) { + unsigned buffer_size = buffer->width0; + + if (!so_target || + so_target->buffer != buffer || + so_target->buffer_size != buffer_size) { + if (so_target) { + pipe_so_target_reference(&so_target, NULL); + } + so_target = pipe->create_stream_output_target(pipe, buffer, + 0,/*buffer offset*/ + buffer_size); + resource->so_target = so_target; + } + } + pDevice->so_targets[i] = so_target; + } + + for (i = 0; i < ClearTargets; ++i) { + pDevice->so_targets[SOTargets + i] = NULL; + } + + if (!pipe->set_stream_output_targets) { + LOG_UNSUPPORTED(pipe->set_stream_output_targets); + return; + } + + pipe->set_stream_output_targets(pipe, SOTargets, pDevice->so_targets, + pOffsets); +} + + +/* + * ---------------------------------------------------------------------- + * + * CreatePixelShader -- + * + * The CreatePixelShader function converts pixel shader code into a + * hardware-specific format and associates this code with a + * shader handle. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreatePixelShader(D3D10DDI_HDEVICE hDevice, // IN + __in_ecount (pShaderCode[1]) const UINT *pShaderCode, // IN + D3D10DDI_HSHADER hShader, // IN + D3D10DDI_HRTSHADER hRTShader, // IN + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + Shader *pShader = CastShader(hShader); + + pShader->type = PIPE_SHADER_FRAGMENT; + pShader->output_resolved = TRUE; + + memset(&pShader->state, 0, sizeof pShader->state); + pShader->state.tokens = Shader_tgsi_translate(pShaderCode, + pShader->output_mapping); + + pShader->handle = pipe->create_fs_state(pipe, &pShader->state); + +} + + +/* + * ---------------------------------------------------------------------- + * + * PsSetShader -- + * + * The PsSetShader function sets a pixel shader to be used + * in all drawing operations. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +PsSetShader(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HSHADER hShader) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + struct pipe_context *pipe = pDevice->pipe; + void *state = CastPipeShader(hShader); + + if (!state) { + state = pDevice->empty_fs; + } + + pipe->bind_fs_state(pipe, state); +} + + +/* + * ---------------------------------------------------------------------- + * + * PsSetShaderResources -- + * + * The PsSetShaderResources function sets resources for a pixel shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +PsSetShaderResources(D3D10DDI_HDEVICE hDevice, // IN + UINT Offset, // IN + UINT NumViews, // IN + __in_ecount (NumViews) + const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews) // IN +{ + LOG_ENTRYPOINT(); + + SetShaderResources(PIPE_SHADER_FRAGMENT, hDevice, Offset, NumViews, phShaderResourceViews); +} + + +/* + * ---------------------------------------------------------------------- + * + * PsSetConstantBuffers -- + * + * The PsSetConstantBuffers function sets constant buffers for + * a pixel shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +PsSetConstantBuffers(D3D10DDI_HDEVICE hDevice, // IN + UINT StartBuffer, // IN + UINT NumBuffers, // IN + __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers) // IN +{ + LOG_ENTRYPOINT(); + + SetConstantBuffers(PIPE_SHADER_FRAGMENT, + hDevice, StartBuffer, NumBuffers, phBuffers); +} + +/* + * ---------------------------------------------------------------------- + * + * PsSetSamplers -- + * + * The PsSetSamplers function sets samplers for a pixel shader. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +PsSetSamplers(D3D10DDI_HDEVICE hDevice, // IN + UINT Offset, // IN + UINT NumSamplers, // IN + __in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers) // IN +{ + LOG_ENTRYPOINT(); + + SetSamplers(PIPE_SHADER_FRAGMENT, hDevice, Offset, NumSamplers, phSamplers); +} + + +/* + * ---------------------------------------------------------------------- + * + * ShaderResourceViewReadAfterWriteHazard -- + * + * The ShaderResourceViewReadAfterWriteHazard function informs + * the usermode display driver that the specified resource was + * used as an output from the graphics processing unit (GPU) + * and that the resource will be used as an input to the GPU. + * A shader resource view is also provided to indicate which + * view caused the hazard. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +ShaderResourceViewReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView, // IN + D3D10DDI_HRESOURCE hResource) // IN +{ + LOG_ENTRYPOINT(); + + /* Not actually necessary */ +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateShaderResourceViewSize -- + * + * The CalcPrivateShaderResourceViewSize function determines the size + * of the usermode display driver's private region of memory + * (that is, the size of internal driver structures, not the size of + * the resource video memory) for a shader resource view. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateShaderResourceViewSize( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView) // IN +{ + return sizeof(ShaderResourceView); +} + + +/* + * ---------------------------------------------------------------------- + * + * CalcPrivateShaderResourceViewSize -- + * + * The CalcPrivateShaderResourceViewSize function determines the size + * of the usermode display driver's private region of memory + * (that is, the size of internal driver structures, not the size of + * the resource video memory) for a shader resource view. + * + * ---------------------------------------------------------------------- + */ + +SIZE_T APIENTRY +CalcPrivateShaderResourceViewSize1( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_1DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView) // IN +{ + return sizeof(ShaderResourceView); +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateShaderResourceView -- + * + * The CreateShaderResourceView function creates a shader + * resource view. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateShaderResourceView( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView, // IN + D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView, // IN + D3D10DDI_HRTSHADERRESOURCEVIEW hRTShaderResourceView) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView); + struct pipe_resource *resource; + enum pipe_format format; + + struct pipe_sampler_view desc; + memset(&desc, 0, sizeof desc); + resource = CastPipeResource(pCreateSRView->hDrvResource); + format = FormatTranslate(pCreateSRView->Format, FALSE); + + u_sampler_view_default_template(&desc, + resource, + format); + + switch (pCreateSRView->ResourceDimension) { + case D3D10DDIRESOURCE_BUFFER: { + const struct util_format_description *fdesc = util_format_description(format); + desc.u.buf.offset = pCreateSRView->Buffer.FirstElement * + (fdesc->block.bits / 8) * fdesc->block.width; + desc.u.buf.size = pCreateSRView->Buffer.NumElements * + (fdesc->block.bits / 8) * fdesc->block.width; + } + break; + case D3D10DDIRESOURCE_TEXTURE1D: + desc.u.tex.first_level = pCreateSRView->Tex1D.MostDetailedMip; + desc.u.tex.last_level = pCreateSRView->Tex1D.MipLevels - 1 + desc.u.tex.first_level; + desc.u.tex.first_layer = pCreateSRView->Tex1D.FirstArraySlice; + desc.u.tex.last_layer = pCreateSRView->Tex1D.ArraySize - 1 + desc.u.tex.first_layer; + assert(pCreateSRView->Tex1D.MipLevels != 0 && pCreateSRView->Tex1D.MipLevels != (UINT)-1); + assert(pCreateSRView->Tex1D.ArraySize != 0 && pCreateSRView->Tex1D.ArraySize != (UINT)-1); + break; + case D3D10DDIRESOURCE_TEXTURE2D: + desc.u.tex.first_level = pCreateSRView->Tex2D.MostDetailedMip; + desc.u.tex.last_level = pCreateSRView->Tex2D.MipLevels - 1 + desc.u.tex.first_level; + desc.u.tex.first_layer = pCreateSRView->Tex2D.FirstArraySlice; + desc.u.tex.last_layer = pCreateSRView->Tex2D.ArraySize - 1 + desc.u.tex.first_layer; + assert(pCreateSRView->Tex2D.MipLevels != 0 && pCreateSRView->Tex2D.MipLevels != (UINT)-1); + assert(pCreateSRView->Tex2D.ArraySize != 0 && pCreateSRView->Tex2D.ArraySize != (UINT)-1); + break; + case D3D10DDIRESOURCE_TEXTURE3D: + desc.u.tex.first_level = pCreateSRView->Tex3D.MostDetailedMip; + desc.u.tex.last_level = pCreateSRView->Tex3D.MipLevels - 1 + desc.u.tex.first_level; + /* layer info filled in by default_template */ + assert(pCreateSRView->Tex3D.MipLevels != 0 && pCreateSRView->Tex3D.MipLevels != (UINT)-1); + break; + case D3D10DDIRESOURCE_TEXTURECUBE: + desc.u.tex.first_level = pCreateSRView->TexCube.MostDetailedMip; + desc.u.tex.last_level = pCreateSRView->TexCube.MipLevels - 1 + desc.u.tex.first_level; + /* layer info filled in by default_template */ + assert(pCreateSRView->TexCube.MipLevels != 0 && pCreateSRView->TexCube.MipLevels != (UINT)-1); + break; + default: + assert(0); + return; + } + + pSRView->handle = pipe->create_sampler_view(pipe, resource, &desc); +} + + +/* + * ---------------------------------------------------------------------- + * + * CreateShaderResourceView1 -- + * + * The CreateShaderResourceView function creates a shader + * resource view. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +CreateShaderResourceView1( + D3D10DDI_HDEVICE hDevice, // IN + __in const D3D10_1DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView, // IN + D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView, // IN + D3D10DDI_HRTSHADERRESOURCEVIEW hRTShaderResourceView) // IN +{ + LOG_ENTRYPOINT(); + + struct pipe_context *pipe = CastPipeContext(hDevice); + ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView); + struct pipe_resource *resource; + enum pipe_format format; + + struct pipe_sampler_view desc; + memset(&desc, 0, sizeof desc); + resource = CastPipeResource(pCreateSRView->hDrvResource); + format = FormatTranslate(pCreateSRView->Format, FALSE); + + u_sampler_view_default_template(&desc, + resource, + format); + + switch (pCreateSRView->ResourceDimension) { + case D3D10DDIRESOURCE_BUFFER: { + const struct util_format_description *fdesc = util_format_description(format); + desc.u.buf.offset = pCreateSRView->Buffer.FirstElement * + (fdesc->block.bits / 8) * fdesc->block.width; + desc.u.buf.size = pCreateSRView->Buffer.NumElements * + (fdesc->block.bits / 8) * fdesc->block.width; + } + break; + case D3D10DDIRESOURCE_TEXTURE1D: + desc.u.tex.first_level = pCreateSRView->Tex1D.MostDetailedMip; + desc.u.tex.last_level = pCreateSRView->Tex1D.MipLevels - 1 + desc.u.tex.first_level; + desc.u.tex.first_layer = pCreateSRView->Tex1D.FirstArraySlice; + desc.u.tex.last_layer = pCreateSRView->Tex1D.ArraySize - 1 + desc.u.tex.first_layer; + assert(pCreateSRView->Tex1D.MipLevels != 0 && pCreateSRView->Tex1D.MipLevels != (UINT)-1); + assert(pCreateSRView->Tex1D.ArraySize != 0 && pCreateSRView->Tex1D.ArraySize != (UINT)-1); + break; + case D3D10DDIRESOURCE_TEXTURE2D: + desc.u.tex.first_level = pCreateSRView->Tex2D.MostDetailedMip; + desc.u.tex.last_level = pCreateSRView->Tex2D.MipLevels - 1 + desc.u.tex.first_level; + desc.u.tex.first_layer = pCreateSRView->Tex2D.FirstArraySlice; + desc.u.tex.last_layer = pCreateSRView->Tex2D.ArraySize - 1 + desc.u.tex.first_layer; + assert(pCreateSRView->Tex2D.MipLevels != 0 && pCreateSRView->Tex2D.MipLevels != (UINT)-1); + assert(pCreateSRView->Tex2D.ArraySize != 0 && pCreateSRView->Tex2D.ArraySize != (UINT)-1); + break; + case D3D10DDIRESOURCE_TEXTURE3D: + desc.u.tex.first_level = pCreateSRView->Tex3D.MostDetailedMip; + desc.u.tex.last_level = pCreateSRView->Tex3D.MipLevels - 1 + desc.u.tex.first_level; + /* layer info filled in by default_template */ + assert(pCreateSRView->Tex3D.MipLevels != 0 && pCreateSRView->Tex3D.MipLevels != (UINT)-1); + break; + case D3D10DDIRESOURCE_TEXTURECUBE: + desc.u.tex.first_level = pCreateSRView->TexCube.MostDetailedMip; + desc.u.tex.last_level = pCreateSRView->TexCube.MipLevels - 1 + desc.u.tex.first_level; + desc.u.tex.first_layer = pCreateSRView->TexCube.First2DArrayFace; + desc.u.tex.last_layer = 6*pCreateSRView->TexCube.NumCubes - 1 + + pCreateSRView->TexCube.First2DArrayFace; + assert(pCreateSRView->TexCube.MipLevels != 0 && pCreateSRView->TexCube.MipLevels != (UINT)-1); + break; + default: + assert(0); + return; + } + + pSRView->handle = pipe->create_sampler_view(pipe, resource, &desc); +} + + +/* + * ---------------------------------------------------------------------- + * + * DestroyShaderResourceView -- + * + * The DestroyShaderResourceView function destroys the specified + * shader resource view object. The shader resource view object + * can be destoyed only if it is not currently bound to a + * display device. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +DestroyShaderResourceView(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView) // IN +{ + LOG_ENTRYPOINT(); + + ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView); + + pipe_sampler_view_reference(&pSRView->handle, NULL); +} + + +/* + * ---------------------------------------------------------------------- + * + * GenMips -- + * + * The GenMips function generates the lower MIP-map levels + * on the specified shader-resource view. + * + * ---------------------------------------------------------------------- + */ + +void APIENTRY +GenMips(D3D10DDI_HDEVICE hDevice, // IN + D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView) // IN +{ + LOG_ENTRYPOINT(); + + Device *pDevice = CastDevice(hDevice); + if (!CheckPredicate(pDevice)) { + return; + } + + struct pipe_context *pipe = pDevice->pipe; + struct pipe_sampler_view *sampler_view = CastPipeShaderResourceView(hShaderResourceView); + + util_gen_mipmap(pipe, + sampler_view->texture, + sampler_view->format, + sampler_view->u.tex.first_level, + sampler_view->u.tex.last_level, + sampler_view->u.tex.first_layer, + sampler_view->u.tex.last_layer, + PIPE_TEX_FILTER_LINEAR); +} + + +unsigned +ShaderFindOutputMapping(Shader *shader, unsigned registerIndex) +{ + if (!shader || !shader->state.tokens) + return registerIndex; + + for (unsigned i = 0; i < PIPE_MAX_SHADER_OUTPUTS; ++i) { + if (shader->output_mapping[i] == registerIndex) + return i; + } + return registerIndex; +} diff --git a/src/gallium/frontends/d3d10umd/Shader.h b/src/gallium/frontends/d3d10umd/Shader.h new file mode 100644 index 00000000000..ac64f3681a1 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/Shader.h @@ -0,0 +1,164 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * Shader.h -- + * Functions that manipulate shader resources. + */ + +#ifndef SHADER_H +#define SHADER_H + +#include "DriverIncludes.h" + +struct Device; +struct Shader; + +void * +CreateEmptyShader(Device *pDevice, + enum pipe_shader_type processor); + +void +DeleteEmptyShader(Device *pDevice, + enum pipe_shader_type processor, void *handle); + +unsigned +ShaderFindOutputMapping(Shader *shader, unsigned registerIndex); + +SIZE_T APIENTRY +CalcPrivateShaderSize(D3D10DDI_HDEVICE hDevice, + __in_ecount (pShaderCode[1]) const UINT *pShaderCode, + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures); + +void APIENTRY +DestroyShader(D3D10DDI_HDEVICE hDevice, D3D10DDI_HSHADER hShader); + +SIZE_T APIENTRY +CalcPrivateSamplerSize(D3D10DDI_HDEVICE hDevice, + __in const D3D10_DDI_SAMPLER_DESC *pSamplerDesc); + +void APIENTRY CreateSampler(D3D10DDI_HDEVICE hDevice, + __in const D3D10_DDI_SAMPLER_DESC *pSamplerDesc, + D3D10DDI_HSAMPLER hSampler, D3D10DDI_HRTSAMPLER hRTSampler); + +void APIENTRY DestroySampler(D3D10DDI_HDEVICE hDevice, D3D10DDI_HSAMPLER hSampler); + +void APIENTRY CreateVertexShader(D3D10DDI_HDEVICE hDevice, + __in_ecount (pShaderCode[1]) const UINT *pCode, + D3D10DDI_HSHADER hShader, D3D10DDI_HRTSHADER hRTShader, + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures); + +void APIENTRY VsSetShader(D3D10DDI_HDEVICE hDevice, D3D10DDI_HSHADER hShader); + +void APIENTRY VsSetShaderResources( + D3D10DDI_HDEVICE hDevice, UINT Offset, UINT NumViews, + __in_ecount (NumViews) const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews); +void APIENTRY VsSetConstantBuffers(D3D10DDI_HDEVICE hDevice, UINT StartBuffer, UINT NumBuffers, + __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers); + +void APIENTRY VsSetSamplers(D3D10DDI_HDEVICE hDevice, UINT Offset, UINT NumSamplers, + __in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers); + +void APIENTRY CreateGeometryShader(D3D10DDI_HDEVICE hDevice, + __in_ecount (pShaderCode[1]) const UINT *pCode, + D3D10DDI_HSHADER hShader, D3D10DDI_HRTSHADER hRTShader, + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures); + +void APIENTRY GsSetShader(D3D10DDI_HDEVICE hDevice, D3D10DDI_HSHADER hShader); + +void APIENTRY GsSetShaderResources( + D3D10DDI_HDEVICE hDevice, UINT Offset, UINT NumViews, + __in_ecount (NumViews) const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews); + +void APIENTRY GsSetConstantBuffers(D3D10DDI_HDEVICE hDevice, UINT StartBuffer, UINT NumBuffers, + __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers); + +void APIENTRY GsSetSamplers(D3D10DDI_HDEVICE hDevice, UINT Offset, UINT NumSamplers, + __in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers); + +SIZE_T APIENTRY CalcPrivateGeometryShaderWithStreamOutput( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATEGEOMETRYSHADERWITHSTREAMOUTPUT *pCreateGeometryShaderWithStreamOutput, + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures); + +void APIENTRY CreateGeometryShaderWithStreamOutput( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATEGEOMETRYSHADERWITHSTREAMOUTPUT *pCreateGeometryShaderWithStreamOutput, + D3D10DDI_HSHADER hShader, D3D10DDI_HRTSHADER hRTShader, + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures); + +void APIENTRY SoSetTargets(D3D10DDI_HDEVICE hDevice, UINT SOTargets, UINT ClearTargets, + __in_ecount (SOTargets) const D3D10DDI_HRESOURCE *phResource, + __in_ecount (SOTargets) const UINT *pOffsets); + +void APIENTRY CreatePixelShader(D3D10DDI_HDEVICE hDevice, + __in_ecount (pShaderCode[1]) const UINT *pCode, + D3D10DDI_HSHADER hShader, D3D10DDI_HRTSHADER hRTShader, + __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures); +void APIENTRY PsSetShader(D3D10DDI_HDEVICE hDevice, D3D10DDI_HSHADER hShader); + +void APIENTRY PsSetShaderResources( + D3D10DDI_HDEVICE hDevice, UINT Offset, UINT NumViews, + __in_ecount (NumViews) const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews); + +void APIENTRY PsSetConstantBuffers(D3D10DDI_HDEVICE hDevice, UINT StartBuffer, UINT NumBuffers, + __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers); + +void APIENTRY PsSetSamplers(D3D10DDI_HDEVICE hDevice, UINT Offset, UINT NumSamplers, + __in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers); + +void APIENTRY ShaderResourceViewReadAfterWriteHazard( + D3D10DDI_HDEVICE hDevice, D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView, + D3D10DDI_HRESOURCE hResource); + +SIZE_T APIENTRY CalcPrivateShaderResourceViewSize( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATESHADERRESOURCEVIEW *pCreateShaderResourceView); + +void APIENTRY CreateShaderResourceView( + D3D10DDI_HDEVICE hDevice, + __in const D3D10DDIARG_CREATESHADERRESOURCEVIEW *pCreateShaderResourceView, + D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView, + D3D10DDI_HRTSHADERRESOURCEVIEW hRTShaderResourceView); + +SIZE_T APIENTRY CalcPrivateShaderResourceViewSize1( + D3D10DDI_HDEVICE hDevice, + __in const D3D10_1DDIARG_CREATESHADERRESOURCEVIEW *pCreateShaderResourceView); + +void APIENTRY CreateShaderResourceView1( + D3D10DDI_HDEVICE hDevice, + __in const D3D10_1DDIARG_CREATESHADERRESOURCEVIEW *pCreateShaderResourceView, + D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView, + D3D10DDI_HRTSHADERRESOURCEVIEW hRTShaderResourceView); + +void APIENTRY DestroyShaderResourceView(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView); + +void APIENTRY GenMips(D3D10DDI_HDEVICE hDevice, + D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView); + +#endif /* SHADER_H */ diff --git a/src/gallium/frontends/d3d10umd/ShaderDump.cpp b/src/gallium/frontends/d3d10umd/ShaderDump.cpp new file mode 100644 index 00000000000..9f3862cd1e1 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/ShaderDump.cpp @@ -0,0 +1,72 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * ShaderDump.c -- + * Functions for printing out shaders. + */ + +#include "DriverIncludes.h" + +#include "ShaderDump.h" +#include "util/u_debug.h" + + +static void +dump_uints(const unsigned *data, + unsigned count) +{ + unsigned i; + + for (i = 0; i < count; i++) { + if (i % 8 == 7) { + debug_printf("0x%08x,\n", data[i]); + } else { + debug_printf("0x%08x, ", data[i]); + } + } + if (i % 8) { + debug_printf("\n"); + } +} + +void +dx10_shader_dump_binary(const unsigned *code) +{ + dump_uints(code, code[1]); +} + + +void +dx10_shader_dump_tokens(const unsigned *code) +{ + /* + * TODO: Dump SM4/5 disassembly via D3DDisassemble. However this requires + * rebuilding DXBC container. + */ + dx10_shader_dump_binary(code); +} diff --git a/src/gallium/frontends/d3d10umd/ShaderDump.h b/src/gallium/frontends/d3d10umd/ShaderDump.h new file mode 100644 index 00000000000..e2e296ea882 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/ShaderDump.h @@ -0,0 +1,50 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * ShaderDump.h -- + * Functions for printing out shaders. + */ + +#ifndef SHADER_DUMP_H +#define SHADER_DUMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +void +dx10_shader_dump_binary(const unsigned *code); + +void +dx10_shader_dump_tokens(const unsigned *code); + +#ifdef __cplusplus +} +#endif + +#endif /* SHADER_DUMP_H */ diff --git a/src/gallium/frontends/d3d10umd/ShaderParse.c b/src/gallium/frontends/d3d10umd/ShaderParse.c new file mode 100644 index 00000000000..e4b6b88aa72 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/ShaderParse.c @@ -0,0 +1,610 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * ShaderParse.c -- + * Functions for parsing shader tokens. + */ + +#include "Debug.h" +#include "ShaderParse.h" + +#include "util/u_memory.h" + + +void +Shader_parse_init(struct Shader_parser *parser, + const unsigned *code) +{ + parser->curr = parser->code = code; + + parser->header.type = DECODE_D3D10_SB_TOKENIZED_PROGRAM_TYPE(*parser->curr); + parser->header.major_version = DECODE_D3D10_SB_TOKENIZED_PROGRAM_MAJOR_VERSION(*parser->curr); + parser->header.minor_version = DECODE_D3D10_SB_TOKENIZED_PROGRAM_MINOR_VERSION(*parser->curr); + parser->curr++; + + parser->header.size = DECODE_D3D10_SB_TOKENIZED_PROGRAM_LENGTH(*parser->curr); + parser->curr++; +} + +#define OP_NOT_DONE (1 << 0) /* not implemented yet */ +#define OP_SATURATE (1 << 1) /* saturate in opcode specific control */ +#define OP_TEST_BOOLEAN (1 << 2) /* test boolean in opcode specific control */ +#define OP_DCL (1 << 3) /* custom opcode specific control */ +#define OP_RESINFO_RET_TYPE (1 << 4) /* return type for resinfo */ + +struct dx10_opcode_info { + D3D10_SB_OPCODE_TYPE type; + const char *name; + unsigned num_dst; + unsigned num_src; + unsigned flags; +}; + +#define _(_opcode) _opcode, #_opcode + +static const struct dx10_opcode_info +opcode_info[D3D10_SB_NUM_OPCODES] = { + {_(D3D10_SB_OPCODE_ADD), 1, 2, OP_SATURATE}, + {_(D3D10_SB_OPCODE_AND), 1, 2, 0}, + {_(D3D10_SB_OPCODE_BREAK), 0, 0, 0}, + {_(D3D10_SB_OPCODE_BREAKC), 0, 1, OP_TEST_BOOLEAN}, + {_(D3D10_SB_OPCODE_CALL), 0, 1, 0}, + {_(D3D10_SB_OPCODE_CALLC), 0, 2, OP_TEST_BOOLEAN}, + {_(D3D10_SB_OPCODE_CASE), 0, 1, 0}, + {_(D3D10_SB_OPCODE_CONTINUE), 0, 0, 0}, + {_(D3D10_SB_OPCODE_CONTINUEC), 0, 1, OP_TEST_BOOLEAN}, + {_(D3D10_SB_OPCODE_CUT), 0, 0, 0}, + {_(D3D10_SB_OPCODE_DEFAULT), 0, 0, 0}, + {_(D3D10_SB_OPCODE_DERIV_RTX), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_DERIV_RTY), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_DISCARD), 0, 1, OP_TEST_BOOLEAN}, + {_(D3D10_SB_OPCODE_DIV), 1, 2, OP_SATURATE}, + {_(D3D10_SB_OPCODE_DP2), 1, 2, OP_SATURATE}, + {_(D3D10_SB_OPCODE_DP3), 1, 2, OP_SATURATE}, + {_(D3D10_SB_OPCODE_DP4), 1, 2, OP_SATURATE}, + {_(D3D10_SB_OPCODE_ELSE), 0, 0, 0}, + {_(D3D10_SB_OPCODE_EMIT), 0, 0, 0}, + {_(D3D10_SB_OPCODE_EMITTHENCUT), 0, 0, 0}, + {_(D3D10_SB_OPCODE_ENDIF), 0, 0, 0}, + {_(D3D10_SB_OPCODE_ENDLOOP), 0, 0, 0}, + {_(D3D10_SB_OPCODE_ENDSWITCH), 0, 0, 0}, + {_(D3D10_SB_OPCODE_EQ), 1, 2, 0}, + {_(D3D10_SB_OPCODE_EXP), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_FRC), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_FTOI), 1, 1, 0}, + {_(D3D10_SB_OPCODE_FTOU), 1, 1, 0}, + {_(D3D10_SB_OPCODE_GE), 1, 2, 0}, + {_(D3D10_SB_OPCODE_IADD), 1, 2, 0}, + {_(D3D10_SB_OPCODE_IF), 0, 1, OP_TEST_BOOLEAN}, + {_(D3D10_SB_OPCODE_IEQ), 1, 2, 0}, + {_(D3D10_SB_OPCODE_IGE), 1, 2, 0}, + {_(D3D10_SB_OPCODE_ILT), 1, 2, 0}, + {_(D3D10_SB_OPCODE_IMAD), 1, 3, 0}, + {_(D3D10_SB_OPCODE_IMAX), 1, 2, 0}, + {_(D3D10_SB_OPCODE_IMIN), 1, 2, 0}, + {_(D3D10_SB_OPCODE_IMUL), 2, 2, 0}, + {_(D3D10_SB_OPCODE_INE), 1, 2, 0}, + {_(D3D10_SB_OPCODE_INEG), 1, 1, 0}, + {_(D3D10_SB_OPCODE_ISHL), 1, 2, 0}, + {_(D3D10_SB_OPCODE_ISHR), 1, 2, 0}, + {_(D3D10_SB_OPCODE_ITOF), 1, 1, 0}, + {_(D3D10_SB_OPCODE_LABEL), 0, 1, 0}, + {_(D3D10_SB_OPCODE_LD), 1, 2, 0}, + {_(D3D10_SB_OPCODE_LD_MS), 1, 3, 0}, + {_(D3D10_SB_OPCODE_LOG), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_LOOP), 0, 0, 0}, + {_(D3D10_SB_OPCODE_LT), 1, 2, 0}, + {_(D3D10_SB_OPCODE_MAD), 1, 3, OP_SATURATE}, + {_(D3D10_SB_OPCODE_MIN), 1, 2, OP_SATURATE}, + {_(D3D10_SB_OPCODE_MAX), 1, 2, OP_SATURATE}, + {_(D3D10_SB_OPCODE_CUSTOMDATA), 0, 0, 0}, + {_(D3D10_SB_OPCODE_MOV), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_MOVC), 1, 3, OP_SATURATE}, + {_(D3D10_SB_OPCODE_MUL), 1, 2, OP_SATURATE}, + {_(D3D10_SB_OPCODE_NE), 1, 2, 0}, + {_(D3D10_SB_OPCODE_NOP), 0, 0, 0}, + {_(D3D10_SB_OPCODE_NOT), 1, 1, 0}, + {_(D3D10_SB_OPCODE_OR), 1, 2, 0}, + {_(D3D10_SB_OPCODE_RESINFO), 1, 2, OP_RESINFO_RET_TYPE}, + {_(D3D10_SB_OPCODE_RET), 0, 0, 0}, + {_(D3D10_SB_OPCODE_RETC), 0, 1, OP_TEST_BOOLEAN}, + {_(D3D10_SB_OPCODE_ROUND_NE), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_ROUND_NI), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_ROUND_PI), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_ROUND_Z), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_RSQ), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_SAMPLE), 1, 3, 0}, + {_(D3D10_SB_OPCODE_SAMPLE_C), 1, 4, 0}, + {_(D3D10_SB_OPCODE_SAMPLE_C_LZ), 1, 4, 0}, + {_(D3D10_SB_OPCODE_SAMPLE_L), 1, 4, 0}, + {_(D3D10_SB_OPCODE_SAMPLE_D), 1, 5, 0}, + {_(D3D10_SB_OPCODE_SAMPLE_B), 1, 4, 0}, + {_(D3D10_SB_OPCODE_SQRT), 1, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_SWITCH), 0, 1, 0}, + {_(D3D10_SB_OPCODE_SINCOS), 2, 1, OP_SATURATE}, + {_(D3D10_SB_OPCODE_UDIV), 2, 2, 0}, + {_(D3D10_SB_OPCODE_ULT), 1, 2, 0}, + {_(D3D10_SB_OPCODE_UGE), 1, 2, 0}, + {_(D3D10_SB_OPCODE_UMUL), 2, 2, 0}, + {_(D3D10_SB_OPCODE_UMAD), 1, 3, 0}, + {_(D3D10_SB_OPCODE_UMAX), 1, 2, 0}, + {_(D3D10_SB_OPCODE_UMIN), 1, 2, 0}, + {_(D3D10_SB_OPCODE_USHR), 1, 2, 0}, + {_(D3D10_SB_OPCODE_UTOF), 1, 1, 0}, + {_(D3D10_SB_OPCODE_XOR), 1, 2, 0}, + {_(D3D10_SB_OPCODE_DCL_RESOURCE), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER), 0, 1, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_SAMPLER), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_INDEX_RANGE), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY), 0, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE), 0, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT), 0, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_INPUT), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_INPUT_SGV), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_INPUT_SIV), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_INPUT_PS), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_INPUT_PS_SGV), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_INPUT_PS_SIV), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_OUTPUT), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_OUTPUT_SGV), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_OUTPUT_SIV), 1, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_TEMPS), 0, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP), 0, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS), 0, 0, OP_DCL}, + {_(D3D10_SB_OPCODE_RESERVED0), 0, 0, OP_NOT_DONE}, + {_(D3D10_1_SB_OPCODE_LOD), 0, 0, OP_NOT_DONE}, + {_(D3D10_1_SB_OPCODE_GATHER4), 0, 0, OP_NOT_DONE}, + {_(D3D10_1_SB_OPCODE_SAMPLE_POS), 0, 0, OP_NOT_DONE}, + {_(D3D10_1_SB_OPCODE_SAMPLE_INFO), 0, 0, OP_NOT_DONE} +}; + +#undef _ + +static void +parse_operand(const unsigned **curr, + struct Shader_operand *operand) +{ + operand->type = DECODE_D3D10_SB_OPERAND_TYPE(**curr); + + /* Index dimension. */ + switch (DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(**curr)) { + case D3D10_SB_OPERAND_INDEX_0D: + operand->index_dim = 0; + break; + case D3D10_SB_OPERAND_INDEX_1D: + operand->index_dim = 1; + break; + case D3D10_SB_OPERAND_INDEX_2D: + operand->index_dim = 2; + break; + default: + assert(0); + } + + if (operand->index_dim >= 1) { + operand->index[0].index_rep = DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(0, **curr); + if (operand->index_dim >= 2) { + operand->index[1].index_rep = DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(1, **curr); + } + } + + (*curr)++; +} + +static void +parse_relative_operand(const unsigned **curr, + struct Shader_relative_operand *operand) +{ + assert(!DECODE_IS_D3D10_SB_OPERAND_EXTENDED(**curr)); + assert(DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(**curr) == D3D10_SB_OPERAND_4_COMPONENT); + assert(DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(**curr) == D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE); + + operand->comp = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECT_1(**curr); + + operand->type = DECODE_D3D10_SB_OPERAND_TYPE(**curr); + assert(operand->type != D3D10_SB_OPERAND_TYPE_IMMEDIATE32); + + /* Index dimension. */ + assert(DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(0, **curr) == D3D10_SB_OPERAND_INDEX_IMMEDIATE32); + + if (DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(**curr) == D3D10_SB_OPERAND_INDEX_1D) { + (*curr)++; + operand->index[0].imm = **curr; + } else { + assert(DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(**curr) == D3D10_SB_OPERAND_INDEX_2D); + (*curr)++; + operand->index[0].imm = **curr; + (*curr)++; + operand->index[1].imm = **curr; + + } + (*curr)++; +} + +static void +parse_index(const unsigned **curr, + struct Shader_index *index) +{ + switch (index->index_rep) { + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32: + index->imm = *(*curr)++; + break; + case D3D10_SB_OPERAND_INDEX_RELATIVE: + index->imm = 0; + parse_relative_operand(curr, &index->rel); + break; + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + index->imm = *(*curr)++; + parse_relative_operand(curr, &index->rel); + break; + default: + /* XXX: Support other index representations. + */ + assert(0); + } +} + +static void +parse_operand_index(const unsigned **curr, + struct Shader_operand *operand) +{ + if (operand->index_dim >= 1) { + parse_index(curr, &operand->index[0]); + if (operand->index_dim >= 2) { + parse_index(curr, &operand->index[1]); + } + } +} + +boolean +Shader_parse_opcode(struct Shader_parser *parser, + struct Shader_opcode *opcode) +{ + const unsigned *curr = parser->curr; + const struct dx10_opcode_info *info; + unsigned length; + boolean opcode_is_extended; + unsigned i; + + if (curr >= parser->code + parser->header.size) { + return FALSE; + } + + memset(opcode, 0, sizeof *opcode); + + /* Opcode type. */ + opcode->type = DECODE_D3D10_SB_OPCODE_TYPE(*curr); + + if (opcode->type == D3D10_SB_OPCODE_CUSTOMDATA) { + opcode->customdata._class = DECODE_D3D10_SB_CUSTOMDATA_CLASS(*curr); + curr++; + + assert(opcode->customdata._class == D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER); + + opcode->customdata.u.constbuf.count = *curr - 2; + curr++; + + opcode->customdata.u.constbuf.data = MALLOC(opcode->customdata.u.constbuf.count * sizeof(unsigned)); + assert(opcode->customdata.u.constbuf.data); + + memcpy(opcode->customdata.u.constbuf.data, + curr, + opcode->customdata.u.constbuf.count * sizeof(unsigned)); + curr += opcode->customdata.u.constbuf.count; + + parser->curr = curr; + return TRUE; + } + + opcode->dcl_siv_name = D3D10_SB_NAME_UNDEFINED; + + /* Lookup extra information based on opcode type. */ + assert(opcode->type < D3D10_SB_NUM_OPCODES); + info = &opcode_info[opcode->type]; + + /* Opcode specific. */ + switch (opcode->type) { + case D3D10_SB_OPCODE_DCL_RESOURCE: + opcode->specific.dcl_resource_dimension = DECODE_D3D10_SB_RESOURCE_DIMENSION(*curr); + break; + case D3D10_SB_OPCODE_DCL_SAMPLER: + opcode->specific.dcl_sampler_mode = DECODE_D3D10_SB_SAMPLER_MODE(*curr); + break; + case D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + opcode->specific.dcl_gs_output_primitive_topology = DECODE_D3D10_SB_GS_OUTPUT_PRIMITIVE_TOPOLOGY(*curr); + break; + case D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE: + opcode->specific.dcl_gs_input_primitive = DECODE_D3D10_SB_GS_INPUT_PRIMITIVE(*curr); + break; + case D3D10_SB_OPCODE_DCL_INPUT_PS: + case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV: + opcode->specific.dcl_in_ps_interp = DECODE_D3D10_SB_INPUT_INTERPOLATION_MODE(*curr); + break; + case D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS: + opcode->specific.global_flags.refactoring_allowed = DECODE_D3D10_SB_GLOBAL_FLAGS(*curr) ? 1 : 0; + break; + default: + /* Parse opcode-specific control bits */ + if (info->flags & OP_DCL) { + /* no-op */ + } else if (info->flags & OP_SATURATE) { + opcode->saturate = + !!DECODE_IS_D3D10_SB_INSTRUCTION_SATURATE_ENABLED(*curr); + } else if (info->flags & OP_TEST_BOOLEAN) { + opcode->specific.test_boolean = + DECODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(*curr); + } else if (info->flags & OP_RESINFO_RET_TYPE) { + opcode->specific.resinfo_ret_type = + DECODE_D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE(*curr); + } else { + /* Warn if there are bits set in the opcode-specific controls (bits 23:11 inclusive)*/ + if (*curr & ((1 << 24) - (1 << 11))) { + debug_printf("warning: unexpected opcode-specific control in opcode %s\n", + info->name); + } + } + break; + } + + /* Opcode length in DWORDs. */ + length = DECODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(*curr); + assert(curr + length <= parser->code + parser->header.size); + + /* Opcode specific fields in token0. */ + switch (opcode->type) { + case D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER: + opcode->specific.dcl_cb_access_pattern = + DECODE_D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN(*curr); + break; + default: + break; + } + + opcode_is_extended = DECODE_IS_D3D10_SB_OPCODE_EXTENDED(*curr); + + curr++; + + if (opcode_is_extended) { + /* NOTE: DECODE_IS_D3D10_SB_OPCODE_DOUBLE_EXTENDED is broken. + */ + assert(!((*curr & D3D10_SB_OPCODE_DOUBLE_EXTENDED_MASK) >> D3D10_SB_OPERAND_DOUBLE_EXTENDED_SHIFT)); + + switch (DECODE_D3D10_SB_EXTENDED_OPCODE_TYPE(*curr)) { + case D3D10_SB_EXTENDED_OPCODE_EMPTY: + break; + case D3D10_SB_EXTENDED_OPCODE_SAMPLE_CONTROLS: + opcode->imm_texel_offset.u = DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_U, *curr); + opcode->imm_texel_offset.v = DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_V, *curr); + opcode->imm_texel_offset.w = DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_W, *curr); + break; + default: + assert(0); + } + + curr++; + } + + if (info->flags & OP_NOT_DONE) { + /* XXX: Need to figure out the number of operands for this opcode. + * Should be okay to continue execution -- we have enough info + * to skip to the next instruction. + */ + LOG_UNSUPPORTED(TRUE); + opcode->num_dst = 0; + opcode->num_src = 0; + goto skip; + } + + opcode->num_dst = info->num_dst; + opcode->num_src = info->num_src; + + /* Destination operands. */ + for (i = 0; i < info->num_dst; i++) { + D3D10_SB_OPERAND_NUM_COMPONENTS num_components; + + assert(!DECODE_IS_D3D10_SB_OPERAND_EXTENDED(*curr)); + + num_components = DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(*curr); + if (num_components == D3D10_SB_OPERAND_4_COMPONENT) { + D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE selection_mode; + + selection_mode = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(*curr); + assert(selection_mode == D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE); + + opcode->dst[i].mask = DECODE_D3D10_SB_OPERAND_4_COMPONENT_MASK(*curr); + } else { + assert(num_components == D3D10_SB_OPERAND_0_COMPONENT || + num_components == D3D10_SB_OPERAND_1_COMPONENT); + + opcode->dst[i].mask = D3D10_SB_OPERAND_4_COMPONENT_MASK_X; + } + + parse_operand(&curr, &opcode->dst[i].base); + parse_operand_index(&curr, &opcode->dst[i].base); + } + + /* Source operands. */ + for (i = 0; i < info->num_src; i++) { + boolean extended; + D3D10_SB_OPERAND_NUM_COMPONENTS num_components; + + extended = DECODE_IS_D3D10_SB_OPERAND_EXTENDED(*curr); + + num_components = DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(*curr); + if (num_components == D3D10_SB_OPERAND_4_COMPONENT) { + D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE selection_mode; + + selection_mode = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(*curr); + + if (selection_mode == D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_MODE) { + opcode->src[i].swizzle[0] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 0); + opcode->src[i].swizzle[1] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 1); + opcode->src[i].swizzle[2] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 2); + opcode->src[i].swizzle[3] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 3); + } else if (selection_mode == D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE) { + opcode->src[i].swizzle[0] = + opcode->src[i].swizzle[1] = + opcode->src[i].swizzle[2] = + opcode->src[i].swizzle[3] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECT_1(*curr); + } else { + /* This case apparently happens only for 4-component 32-bit + * immediate operands. + */ + assert(selection_mode == D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE); + assert(DECODE_D3D10_SB_OPERAND_4_COMPONENT_MASK(*curr) == 0); + assert(DECODE_D3D10_SB_OPERAND_TYPE(*curr) == D3D10_SB_OPERAND_TYPE_IMMEDIATE32); + + + opcode->src[i].swizzle[0] = D3D10_SB_4_COMPONENT_X; + opcode->src[i].swizzle[1] = D3D10_SB_4_COMPONENT_Y; + opcode->src[i].swizzle[2] = D3D10_SB_4_COMPONENT_Z; + opcode->src[i].swizzle[3] = D3D10_SB_4_COMPONENT_W; + } + } else if (num_components == D3D10_SB_OPERAND_1_COMPONENT) { + opcode->src[i].swizzle[0] = + opcode->src[i].swizzle[1] = + opcode->src[i].swizzle[2] = + opcode->src[i].swizzle[3] = D3D10_SB_4_COMPONENT_X; + } else { + /* Samplers only? + */ + assert(num_components == D3D10_SB_OPERAND_0_COMPONENT); + assert(DECODE_D3D10_SB_OPERAND_TYPE(*curr) == D3D10_SB_OPERAND_TYPE_SAMPLER || + DECODE_D3D10_SB_OPERAND_TYPE(*curr) == D3D10_SB_OPERAND_TYPE_LABEL); + + opcode->src[i].swizzle[0] = D3D10_SB_4_COMPONENT_X; + opcode->src[i].swizzle[1] = D3D10_SB_4_COMPONENT_Y; + opcode->src[i].swizzle[2] = D3D10_SB_4_COMPONENT_Z; + opcode->src[i].swizzle[3] = D3D10_SB_4_COMPONENT_W; + } + + parse_operand(&curr, &opcode->src[i].base); + + opcode->src[i].modifier = D3D10_SB_OPERAND_MODIFIER_NONE; + if (extended) { + /* NOTE: DECODE_IS_D3D10_SB_OPERAND_DOUBLE_EXTENDED is broken. + */ + assert(!((*curr & D3D10_SB_OPERAND_DOUBLE_EXTENDED_MASK) >> D3D10_SB_OPERAND_DOUBLE_EXTENDED_SHIFT)); + + switch (DECODE_D3D10_SB_EXTENDED_OPERAND_TYPE(*curr)) { + case D3D10_SB_EXTENDED_OPERAND_EMPTY: + break; + + case D3D10_SB_EXTENDED_OPERAND_MODIFIER: + opcode->src[i].modifier = DECODE_D3D10_SB_OPERAND_MODIFIER(*curr); + break; + + default: + assert(0); + } + + curr++; + } + + parse_operand_index(&curr, &opcode->src[i].base); + + if (opcode->src[i].base.type == D3D10_SB_OPERAND_TYPE_IMMEDIATE32) { + switch (num_components) { + case D3D10_SB_OPERAND_1_COMPONENT: + opcode->src[i].imm[0].u32 = + opcode->src[i].imm[1].u32 = + opcode->src[i].imm[2].u32 = + opcode->src[i].imm[3].u32 = *curr++; + break; + + case D3D10_SB_OPERAND_4_COMPONENT: + opcode->src[i].imm[0].u32 = *curr++; + opcode->src[i].imm[1].u32 = *curr++; + opcode->src[i].imm[2].u32 = *curr++; + opcode->src[i].imm[3].u32 = *curr++; + break; + + default: + /* XXX: Support other component sizes. + */ + assert(0); + } + } + } + + /* Opcode specific trailing operands. */ + switch (opcode->type) { + case D3D10_SB_OPCODE_DCL_RESOURCE: + opcode->dcl_resource_ret_type[0] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 0); + opcode->dcl_resource_ret_type[1] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 1); + opcode->dcl_resource_ret_type[2] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 2); + opcode->dcl_resource_ret_type[3] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 3); + curr++; + break; + case D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + opcode->specific.dcl_max_output_vertex_count = *curr; + curr++; + break; + case D3D10_SB_OPCODE_DCL_INPUT_SGV: + case D3D10_SB_OPCODE_DCL_INPUT_SIV: + case D3D10_SB_OPCODE_DCL_INPUT_PS_SGV: + case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV: + case D3D10_SB_OPCODE_DCL_OUTPUT_SIV: + case D3D10_SB_OPCODE_DCL_OUTPUT_SGV: + opcode->dcl_siv_name = DECODE_D3D10_SB_NAME(*curr); + curr++; + break; + case D3D10_SB_OPCODE_DCL_TEMPS: + opcode->specific.dcl_num_temps = *curr; + curr++; + break; + case D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP: + opcode->specific.dcl_indexable_temp.index = *curr++; + opcode->specific.dcl_indexable_temp.count = *curr++; + opcode->specific.dcl_indexable_temp.components = *curr++; + break; + case D3D10_SB_OPCODE_DCL_INDEX_RANGE: + opcode->specific.index_range_count = *curr++; + break; + default: + break; + } + + assert(curr == parser->curr + length); + +skip: + /* Advance to the next opcode. */ + parser->curr += length; + + return TRUE; +} + +void +Shader_opcode_free(struct Shader_opcode *opcode) +{ + if (opcode->type == D3D10_SB_OPCODE_CUSTOMDATA) { + if (opcode->customdata._class == D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER) { + FREE(opcode->customdata.u.constbuf.data); + } + } +} diff --git a/src/gallium/frontends/d3d10umd/ShaderParse.h b/src/gallium/frontends/d3d10umd/ShaderParse.h new file mode 100644 index 00000000000..5e8fba044ab --- /dev/null +++ b/src/gallium/frontends/d3d10umd/ShaderParse.h @@ -0,0 +1,183 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * ShaderParse.h -- + * Functions for parsing shader tokens. + */ + +#ifndef SHADER_PARSE_H +#define SHADER_PARSE_H + +#include "DriverIncludes.h" + +//#include "winddk/winddk_compat.h" +#include "winddk/d3d10tokenizedprogramformat.hpp" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Shader_header { + D3D10_SB_TOKENIZED_PROGRAM_TYPE type; + unsigned major_version; + unsigned minor_version; + unsigned size; +}; + +struct dx10_imm_const_buf { + unsigned count; + unsigned *data; +}; + +struct dx10_customdata { + D3D10_SB_CUSTOMDATA_CLASS _class; + union { + struct dx10_imm_const_buf constbuf; + } u; +}; + +struct dx10_indexable_temp { + unsigned index; + unsigned count; + unsigned components; +}; + +struct dx10_global_flags { + unsigned refactoring_allowed:1; +}; + +struct Shader_relative_index { + unsigned imm; +}; + +struct Shader_relative_operand { + D3D10_SB_OPERAND_TYPE type; + struct Shader_relative_index index[2]; + D3D10_SB_4_COMPONENT_NAME comp; +}; + +struct Shader_index { + unsigned imm; + struct Shader_relative_operand rel; + D3D10_SB_OPERAND_INDEX_REPRESENTATION index_rep; +}; + +struct Shader_operand { + D3D10_SB_OPERAND_TYPE type; + struct Shader_index index[2]; + unsigned index_dim; +}; + +struct Shader_dst_operand { + struct Shader_operand base; + unsigned mask; +}; + +union Shader_immediate { + float f32; + int i32; + unsigned u32; +}; + +struct Shader_src_operand { + struct Shader_operand base; + union Shader_immediate imm[4]; + D3D10_SB_4_COMPONENT_NAME swizzle[4]; + D3D10_SB_OPERAND_MODIFIER modifier; +}; + +#define SHADER_MAX_DST_OPERANDS 2 +#define SHADER_MAX_SRC_OPERANDS 5 + +struct Shader_opcode { + D3D10_SB_OPCODE_TYPE type; + unsigned num_dst; + unsigned num_src; + struct Shader_dst_operand dst[SHADER_MAX_DST_OPERANDS]; + struct Shader_src_operand src[SHADER_MAX_SRC_OPERANDS]; + + /* Opcode specific data. + */ + union { + D3D10_SB_RESOURCE_DIMENSION dcl_resource_dimension; + D3D10_SB_SAMPLER_MODE dcl_sampler_mode; + D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN dcl_cb_access_pattern; + D3D10_SB_INTERPOLATION_MODE dcl_in_ps_interp; + D3D10_SB_PRIMITIVE_TOPOLOGY dcl_gs_output_primitive_topology; + D3D10_SB_PRIMITIVE dcl_gs_input_primitive; + D3D10_SB_INSTRUCTION_TEST_BOOLEAN test_boolean; + D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE resinfo_ret_type; + unsigned dcl_max_output_vertex_count; + unsigned dcl_num_temps; + struct dx10_indexable_temp dcl_indexable_temp; + unsigned index_range_count; + struct dx10_global_flags global_flags; + } specific; + D3D10_SB_NAME dcl_siv_name; + D3D10_SB_RESOURCE_RETURN_TYPE dcl_resource_ret_type[4]; + + boolean saturate; + + struct { + int u:4; + int v:4; + int w:4; + } imm_texel_offset; + + struct dx10_customdata customdata; +}; + +struct Shader_parser { + const unsigned *code; + const unsigned *curr; + + struct Shader_header header; +}; + +void +Shader_parse_init(struct Shader_parser *parser, + const unsigned *code); + +boolean +Shader_parse_opcode(struct Shader_parser *parser, + struct Shader_opcode *opcode); + +void +Shader_opcode_free(struct Shader_opcode *opcode); + + +const struct tgsi_token * +Shader_tgsi_translate(const unsigned *code, + unsigned *output_mapping); + + +#ifdef __cplusplus +} +#endif + +#endif /* SHADER_PARSE_H */ diff --git a/src/gallium/frontends/d3d10umd/ShaderTGSI.c b/src/gallium/frontends/d3d10umd/ShaderTGSI.c new file mode 100644 index 00000000000..2ecbd8ed2b9 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/ShaderTGSI.c @@ -0,0 +1,2302 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * ShaderTGSI.c -- + * Functions for translating shaders. + */ + +#include "Debug.h" +#include "ShaderParse.h" + +#include "pipe/p_state.h" +#include "tgsi/tgsi_ureg.h" +#include "tgsi/tgsi_dump.h" +#include "util/u_memory.h" + +#include "ShaderDump.h" + + +enum dx10_opcode_format { + OF_FLOAT, + OF_INT, + OF_UINT +}; + +struct dx10_opcode_xlate { + D3D10_SB_OPCODE_TYPE type; + enum dx10_opcode_format format; + uint tgsi_opcode; +}; + +/* Opcodes that we have not even attempted to implement: + */ +#define TGSI_LOG_UNSUPPORTED TGSI_OPCODE_LAST + +/* Opcodes which do not translate directly to a TGSI opcode, but which + * have at least a partial implemention coded below: + */ +#define TGSI_EXPAND (TGSI_OPCODE_LAST+1) + +static struct dx10_opcode_xlate opcode_xlate[D3D10_SB_NUM_OPCODES] = { + {D3D10_SB_OPCODE_ADD, OF_FLOAT, TGSI_OPCODE_ADD}, + {D3D10_SB_OPCODE_AND, OF_UINT, TGSI_OPCODE_AND}, + {D3D10_SB_OPCODE_BREAK, OF_FLOAT, TGSI_OPCODE_BRK}, + {D3D10_SB_OPCODE_BREAKC, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_CALL, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_CALLC, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_CASE, OF_UINT, TGSI_OPCODE_CASE}, + {D3D10_SB_OPCODE_CONTINUE, OF_FLOAT, TGSI_OPCODE_CONT}, + {D3D10_SB_OPCODE_CONTINUEC, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_CUT, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DEFAULT, OF_FLOAT, TGSI_OPCODE_DEFAULT}, + {D3D10_SB_OPCODE_DERIV_RTX, OF_FLOAT, TGSI_OPCODE_DDX}, + {D3D10_SB_OPCODE_DERIV_RTY, OF_FLOAT, TGSI_OPCODE_DDY}, + {D3D10_SB_OPCODE_DISCARD, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DIV, OF_FLOAT, TGSI_OPCODE_DIV}, + {D3D10_SB_OPCODE_DP2, OF_FLOAT, TGSI_OPCODE_DP2}, + {D3D10_SB_OPCODE_DP3, OF_FLOAT, TGSI_OPCODE_DP3}, + {D3D10_SB_OPCODE_DP4, OF_FLOAT, TGSI_OPCODE_DP4}, + {D3D10_SB_OPCODE_ELSE, OF_FLOAT, TGSI_OPCODE_ELSE}, + {D3D10_SB_OPCODE_EMIT, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_EMITTHENCUT, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_ENDIF, OF_FLOAT, TGSI_OPCODE_ENDIF}, + {D3D10_SB_OPCODE_ENDLOOP, OF_FLOAT, TGSI_OPCODE_ENDLOOP}, + {D3D10_SB_OPCODE_ENDSWITCH, OF_FLOAT, TGSI_OPCODE_ENDSWITCH}, + {D3D10_SB_OPCODE_EQ, OF_FLOAT, TGSI_OPCODE_FSEQ}, + {D3D10_SB_OPCODE_EXP, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_FRC, OF_FLOAT, TGSI_OPCODE_FRC}, + {D3D10_SB_OPCODE_FTOI, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_FTOU, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_GE, OF_FLOAT, TGSI_OPCODE_FSGE}, + {D3D10_SB_OPCODE_IADD, OF_INT, TGSI_OPCODE_UADD}, + {D3D10_SB_OPCODE_IF, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_IEQ, OF_INT, TGSI_OPCODE_USEQ}, + {D3D10_SB_OPCODE_IGE, OF_INT, TGSI_OPCODE_ISGE}, + {D3D10_SB_OPCODE_ILT, OF_INT, TGSI_OPCODE_ISLT}, + {D3D10_SB_OPCODE_IMAD, OF_INT, TGSI_OPCODE_UMAD}, + {D3D10_SB_OPCODE_IMAX, OF_INT, TGSI_OPCODE_IMAX}, + {D3D10_SB_OPCODE_IMIN, OF_INT, TGSI_OPCODE_IMIN}, + {D3D10_SB_OPCODE_IMUL, OF_INT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_INE, OF_INT, TGSI_OPCODE_USNE}, + {D3D10_SB_OPCODE_INEG, OF_INT, TGSI_OPCODE_INEG}, + {D3D10_SB_OPCODE_ISHL, OF_INT, TGSI_OPCODE_SHL}, + {D3D10_SB_OPCODE_ISHR, OF_INT, TGSI_OPCODE_ISHR}, + {D3D10_SB_OPCODE_ITOF, OF_INT, TGSI_OPCODE_I2F}, + {D3D10_SB_OPCODE_LABEL, OF_INT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_LD, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_LD_MS, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_LOG, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_LOOP, OF_FLOAT, TGSI_OPCODE_BGNLOOP}, + {D3D10_SB_OPCODE_LT, OF_FLOAT, TGSI_OPCODE_FSLT}, + {D3D10_SB_OPCODE_MAD, OF_FLOAT, TGSI_OPCODE_MAD}, + {D3D10_SB_OPCODE_MIN, OF_FLOAT, TGSI_OPCODE_MIN}, + {D3D10_SB_OPCODE_MAX, OF_FLOAT, TGSI_OPCODE_MAX}, + {D3D10_SB_OPCODE_CUSTOMDATA, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_MOV, OF_UINT, TGSI_OPCODE_MOV}, + {D3D10_SB_OPCODE_MOVC, OF_UINT, TGSI_OPCODE_UCMP}, + {D3D10_SB_OPCODE_MUL, OF_FLOAT, TGSI_OPCODE_MUL}, + {D3D10_SB_OPCODE_NE, OF_FLOAT, TGSI_OPCODE_FSNE}, + {D3D10_SB_OPCODE_NOP, OF_FLOAT, TGSI_OPCODE_NOP}, + {D3D10_SB_OPCODE_NOT, OF_UINT, TGSI_OPCODE_NOT}, + {D3D10_SB_OPCODE_OR, OF_UINT, TGSI_OPCODE_OR}, + {D3D10_SB_OPCODE_RESINFO, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_RET, OF_FLOAT, TGSI_OPCODE_RET}, + {D3D10_SB_OPCODE_RETC, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_ROUND_NE, OF_FLOAT, TGSI_OPCODE_ROUND}, + {D3D10_SB_OPCODE_ROUND_NI, OF_FLOAT, TGSI_OPCODE_FLR}, + {D3D10_SB_OPCODE_ROUND_PI, OF_FLOAT, TGSI_OPCODE_CEIL}, + {D3D10_SB_OPCODE_ROUND_Z, OF_FLOAT, TGSI_OPCODE_TRUNC}, + {D3D10_SB_OPCODE_RSQ, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_SAMPLE, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_SAMPLE_C, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_SAMPLE_C_LZ, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_SAMPLE_L, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_SAMPLE_D, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_SAMPLE_B, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_SQRT, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_SWITCH, OF_UINT, TGSI_OPCODE_SWITCH}, + {D3D10_SB_OPCODE_SINCOS, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_UDIV, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_ULT, OF_UINT, TGSI_OPCODE_USLT}, + {D3D10_SB_OPCODE_UGE, OF_UINT, TGSI_OPCODE_USGE}, + {D3D10_SB_OPCODE_UMUL, OF_UINT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_UMAD, OF_UINT, TGSI_OPCODE_UMAD}, + {D3D10_SB_OPCODE_UMAX, OF_UINT, TGSI_OPCODE_UMAX}, + {D3D10_SB_OPCODE_UMIN, OF_UINT, TGSI_OPCODE_UMIN}, + {D3D10_SB_OPCODE_USHR, OF_UINT, TGSI_OPCODE_USHR}, + {D3D10_SB_OPCODE_UTOF, OF_UINT, TGSI_OPCODE_U2F}, + {D3D10_SB_OPCODE_XOR, OF_UINT, TGSI_OPCODE_XOR}, + {D3D10_SB_OPCODE_DCL_RESOURCE, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_SAMPLER, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_INDEX_RANGE, OF_FLOAT, TGSI_LOG_UNSUPPORTED}, + {D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_INPUT, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_INPUT_SGV, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_INPUT_SIV, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_INPUT_PS, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_INPUT_PS_SGV, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_INPUT_PS_SIV, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_OUTPUT, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_OUTPUT_SGV, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_OUTPUT_SIV, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_TEMPS, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP, OF_FLOAT, TGSI_EXPAND}, + {D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS, OF_FLOAT, TGSI_LOG_UNSUPPORTED}, + {D3D10_SB_OPCODE_RESERVED0, OF_FLOAT, TGSI_LOG_UNSUPPORTED}, + {D3D10_1_SB_OPCODE_LOD, OF_FLOAT, TGSI_LOG_UNSUPPORTED}, + {D3D10_1_SB_OPCODE_GATHER4, OF_FLOAT, TGSI_LOG_UNSUPPORTED}, + {D3D10_1_SB_OPCODE_SAMPLE_POS, OF_FLOAT, TGSI_LOG_UNSUPPORTED}, + {D3D10_1_SB_OPCODE_SAMPLE_INFO, OF_FLOAT, TGSI_LOG_UNSUPPORTED} +}; + +#define SHADER_MAX_TEMPS 4096 +#define SHADER_MAX_INPUTS 32 +#define SHADER_MAX_OUTPUTS 32 +#define SHADER_MAX_CONSTS 4096 +#define SHADER_MAX_RESOURCES PIPE_MAX_SHADER_SAMPLER_VIEWS +#define SHADER_MAX_SAMPLERS PIPE_MAX_SAMPLERS +#define SHADER_MAX_INDEXABLE_TEMPS 4096 + +struct Shader_call { + unsigned d3d_label; + unsigned tgsi_label_token; +}; + +struct Shader_label { + unsigned d3d_label; + unsigned tgsi_insn_no; +}; + +struct Shader_resource { + uint target; /* TGSI_TEXTURE_x */ +}; + +struct Shader_xlate { + struct ureg_program *ureg; + + uint vertices_in; + uint declared_temps; + + struct ureg_dst temps[SHADER_MAX_TEMPS]; + struct ureg_dst output_depth; + struct Shader_resource resources[SHADER_MAX_RESOURCES]; + struct ureg_src sv[SHADER_MAX_RESOURCES]; + struct ureg_src samplers[SHADER_MAX_SAMPLERS]; + struct ureg_src imms; + struct ureg_src prim_id; + + uint temp_offset; + uint indexable_temp_offsets[SHADER_MAX_INDEXABLE_TEMPS]; + + struct { + boolean declared; + uint writemask; + uint siv_name; + boolean overloaded; + struct ureg_src reg; + } inputs[SHADER_MAX_INPUTS]; + + struct { + struct ureg_dst reg[4]; + } outputs[SHADER_MAX_OUTPUTS]; + + struct { + uint d3d; + uint tgsi; + } clip_distance_mapping[2], cull_distance_mapping[2]; + uint num_clip_distances_declared; + uint num_cull_distances_declared; + + struct Shader_call *calls; + uint num_calls; + uint max_calls; + struct Shader_label *labels; + uint num_labels; + uint max_labels; +}; + +static uint +translate_interpolation(D3D10_SB_INTERPOLATION_MODE interpolation) +{ + switch (interpolation) { + case D3D10_SB_INTERPOLATION_UNDEFINED: + assert(0); + return TGSI_INTERPOLATE_LINEAR; + + case D3D10_SB_INTERPOLATION_CONSTANT: + return TGSI_INTERPOLATE_CONSTANT; + case D3D10_SB_INTERPOLATION_LINEAR: + return TGSI_INTERPOLATE_PERSPECTIVE; + case D3D10_SB_INTERPOLATION_LINEAR_NOPERSPECTIVE: + return TGSI_INTERPOLATE_LINEAR; + + case D3D10_SB_INTERPOLATION_LINEAR_CENTROID: + case D3D10_SB_INTERPOLATION_LINEAR_SAMPLE: // DX10.1 + LOG_UNSUPPORTED(TRUE); + return TGSI_INTERPOLATE_PERSPECTIVE; + + case D3D10_SB_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID: + case D3D10_SB_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE: // DX10.1 + LOG_UNSUPPORTED(TRUE); + return TGSI_INTERPOLATE_LINEAR; + } + + assert(0); + return TGSI_INTERPOLATE_LINEAR; +} + +static uint +translate_system_name(D3D10_SB_NAME name) +{ + switch (name) { + case D3D10_SB_NAME_UNDEFINED: + assert(0); /* should not happen */ + return TGSI_SEMANTIC_GENERIC; + case D3D10_SB_NAME_POSITION: + return TGSI_SEMANTIC_POSITION; + case D3D10_SB_NAME_CLIP_DISTANCE: + case D3D10_SB_NAME_CULL_DISTANCE: + return TGSI_SEMANTIC_CLIPDIST; + case D3D10_SB_NAME_PRIMITIVE_ID: + return TGSI_SEMANTIC_PRIMID; + case D3D10_SB_NAME_INSTANCE_ID: + return TGSI_SEMANTIC_INSTANCEID; + case D3D10_SB_NAME_VERTEX_ID: + return TGSI_SEMANTIC_VERTEXID_NOBASE; + case D3D10_SB_NAME_VIEWPORT_ARRAY_INDEX: + return TGSI_SEMANTIC_VIEWPORT_INDEX; + case D3D10_SB_NAME_RENDER_TARGET_ARRAY_INDEX: + return TGSI_SEMANTIC_LAYER; + case D3D10_SB_NAME_IS_FRONT_FACE: + return TGSI_SEMANTIC_FACE; + case D3D10_SB_NAME_SAMPLE_INDEX: + LOG_UNSUPPORTED(TRUE); + return TGSI_SEMANTIC_GENERIC; + } + + assert(0); + return TGSI_SEMANTIC_GENERIC; +} + +static uint +translate_semantic_index(struct Shader_xlate *sx, + D3D10_SB_NAME name, + const struct Shader_dst_operand *operand) +{ + unsigned idx; + switch (name) { + case D3D10_SB_NAME_CLIP_DISTANCE: + case D3D10_SB_NAME_CULL_DISTANCE: + if (sx->clip_distance_mapping[0].d3d == operand->base.index[0].imm) { + idx = sx->clip_distance_mapping[0].tgsi; + } else { + assert(sx->clip_distance_mapping[1].d3d == operand->base.index[0].imm); + idx = sx->clip_distance_mapping[1].tgsi; + } + break; +/* case D3D10_SB_NAME_CULL_DISTANCE: + if (sx->cull_distance_mapping[0].d3d == operand->base.index[0].imm) { + idx = sx->cull_distance_mapping[0].tgsi; + } else { + assert(sx->cull_distance_mapping[1].d3d == operand->base.index[0].imm); + idx = sx->cull_distance_mapping[1].tgsi; + } + break;*/ + default: + idx = 0; + } + return idx; +} + +static enum tgsi_return_type +trans_dcl_ret_type(D3D10_SB_RESOURCE_RETURN_TYPE d3drettype) { + switch (d3drettype) { + case D3D10_SB_RETURN_TYPE_UNORM: + return TGSI_RETURN_TYPE_UNORM; + case D3D10_SB_RETURN_TYPE_SNORM: + return TGSI_RETURN_TYPE_SNORM; + case D3D10_SB_RETURN_TYPE_SINT: + return TGSI_RETURN_TYPE_SINT; + case D3D10_SB_RETURN_TYPE_UINT: + return TGSI_RETURN_TYPE_UINT; + case D3D10_SB_RETURN_TYPE_FLOAT: + return TGSI_RETURN_TYPE_FLOAT; + case D3D10_SB_RETURN_TYPE_MIXED: + default: + LOG_UNSUPPORTED(TRUE); + return TGSI_RETURN_TYPE_FLOAT; + } +} + +static void +declare_vertices_in(struct Shader_xlate *sx, + unsigned in) +{ + /* Make sure vertices_in is consistent with input primitive + * and other input declarations. + */ + if (sx->vertices_in) { + assert(sx->vertices_in == in); + } else { + sx->vertices_in = in; + } +} + +struct swizzle_mapping { + unsigned x; + unsigned y; + unsigned z; + unsigned w; +}; + +/* mapping of writmask to swizzles */ +static const struct swizzle_mapping writemask_to_swizzle[] = { + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X }, //TGSI_WRITEMASK_NONE + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X }, //TGSI_WRITEMASK_X + { TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y }, //TGSI_WRITEMASK_Y + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y }, //TGSI_WRITEMASK_XY + { TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z }, //TGSI_WRITEMASK_Z + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Z }, //TGSI_WRITEMASK_XZ + { TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z }, //TGSI_WRITEMASK_YZ + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X }, //TGSI_WRITEMASK_XYZ + { TGSI_SWIZZLE_W, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W }, //TGSI_WRITEMASK_W + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_W, TGSI_SWIZZLE_X, TGSI_SWIZZLE_W }, //TGSI_WRITEMASK_XW + { TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W }, //TGSI_WRITEMASK_YW + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W }, //TGSI_WRITEMASK_XYW + { TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W }, //TGSI_WRITEMASK_ZW + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W }, //TGSI_WRITEMASK_XZW + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W }, //TGSI_WRITEMASK_YZW + { TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W }, //TGSI_WRITEMASK_XYZW +}; + +static struct ureg_src +swizzle_reg(struct ureg_src src, uint writemask, + unsigned siv_name) +{ + switch (siv_name) { + case D3D10_SB_NAME_PRIMITIVE_ID: + case D3D10_SB_NAME_INSTANCE_ID: + case D3D10_SB_NAME_VERTEX_ID: + case D3D10_SB_NAME_VIEWPORT_ARRAY_INDEX: + case D3D10_SB_NAME_RENDER_TARGET_ARRAY_INDEX: + case D3D10_SB_NAME_IS_FRONT_FACE: + return ureg_scalar(src, TGSI_SWIZZLE_X); + default: { + const struct swizzle_mapping *swizzle = + &writemask_to_swizzle[writemask]; + return ureg_swizzle(src, swizzle->x, swizzle->y, + swizzle->z, swizzle->w); + } + } +} + +static void +dcl_base_output(struct Shader_xlate *sx, + struct ureg_program *ureg, + struct ureg_dst reg, + const struct Shader_dst_operand *operand) +{ + unsigned writemask = + operand->mask >> D3D10_SB_OPERAND_4_COMPONENT_MASK_SHIFT; + unsigned idx = operand->base.index[0].imm; + unsigned i; + + if (!writemask) { + sx->outputs[idx].reg[0] = reg; + sx->outputs[idx].reg[1] = reg; + sx->outputs[idx].reg[2] = reg; + sx->outputs[idx].reg[3] = reg; + return; + } + + for (i = 0; i < 4; ++i) { + unsigned mask = 1 << i; + if ((writemask & mask)) { + sx->outputs[idx].reg[i] = reg; + } + } +} + +static void +dcl_base_input(struct Shader_xlate *sx, + struct ureg_program *ureg, + const struct Shader_dst_operand *operand, + struct ureg_src dcl_reg, + uint index, + uint siv_name) +{ + unsigned writemask = + operand->mask >> D3D10_SB_OPERAND_4_COMPONENT_MASK_SHIFT; + + if (sx->inputs[index].declared && !sx->inputs[index].overloaded) { + struct ureg_dst temp = ureg_DECL_temporary(sx->ureg); + + ureg_MOV(ureg, + ureg_writemask(temp, sx->inputs[index].writemask), + swizzle_reg(sx->inputs[index].reg, sx->inputs[index].writemask, + sx->inputs[index].siv_name)); + ureg_MOV(ureg, ureg_writemask(temp, writemask), + swizzle_reg(dcl_reg, writemask, siv_name)); + sx->inputs[index].reg = ureg_src(temp); + sx->inputs[index].overloaded = TRUE; + sx->inputs[index].writemask |= writemask; + } else if (sx->inputs[index].overloaded) { + struct ureg_dst temp = ureg_dst(sx->inputs[index].reg); + ureg_MOV(ureg, ureg_writemask(temp, writemask), + swizzle_reg(dcl_reg, writemask, siv_name)); + sx->inputs[index].writemask |= writemask; + } else { + assert(!sx->inputs[index].declared); + + sx->inputs[index].reg = dcl_reg; + sx->inputs[index].declared = TRUE; + sx->inputs[index].writemask = writemask; + sx->inputs[index].siv_name = siv_name; + } +} + +static void +dcl_vs_input(struct Shader_xlate *sx, + struct ureg_program *ureg, + const struct Shader_dst_operand *dst) +{ + struct ureg_src reg; + assert(dst->base.index_dim == 1); + assert(dst->base.index[0].imm < SHADER_MAX_INPUTS); + + reg = ureg_DECL_vs_input(ureg, dst->base.index[0].imm); + + dcl_base_input(sx, ureg, dst, reg, dst->base.index[0].imm, + D3D10_SB_NAME_UNDEFINED); +} + +static void +dcl_gs_input(struct Shader_xlate *sx, + struct ureg_program *ureg, + const struct Shader_dst_operand *dst) +{ + if (dst->base.index_dim == 2) { + assert(dst->base.index[1].imm < SHADER_MAX_INPUTS); + + declare_vertices_in(sx, dst->base.index[0].imm); + + /* XXX: Implement declaration masks in gallium. + */ + if (!sx->inputs[dst->base.index[1].imm].reg.File) { + struct ureg_src reg = + ureg_DECL_input(ureg, + TGSI_SEMANTIC_GENERIC, + dst->base.index[1].imm, + 0, 1); + dcl_base_input(sx, ureg, dst, reg, dst->base.index[1].imm, + D3D10_SB_NAME_UNDEFINED); + } + } else { + assert(dst->base.type == D3D10_SB_OPERAND_TYPE_INPUT_PRIMITIVEID); + assert(dst->base.index_dim == 0); + + sx->prim_id = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_PRIMID, 0); + } +} + +static void +dcl_sgv_input(struct Shader_xlate *sx, + struct ureg_program *ureg, + const struct Shader_dst_operand *dst, + uint dcl_siv_name) +{ + struct ureg_src reg; + assert(dst->base.index_dim == 1); + assert(dst->base.index[0].imm < SHADER_MAX_INPUTS); + + reg = ureg_DECL_system_value(ureg, translate_system_name(dcl_siv_name), 0); + + dcl_base_input(sx, ureg, dst, reg, dst->base.index[0].imm, + dcl_siv_name); +} + +static void +dcl_siv_input(struct Shader_xlate *sx, + struct ureg_program *ureg, + const struct Shader_dst_operand *dst, + uint dcl_siv_name) +{ + struct ureg_src reg; + assert(dst->base.index_dim == 2); + assert(dst->base.index[1].imm < SHADER_MAX_INPUTS); + + declare_vertices_in(sx, dst->base.index[0].imm); + + reg = ureg_DECL_input(ureg, + translate_system_name(dcl_siv_name), 0, + 0, 1); + + dcl_base_input(sx, ureg, dst, reg, dst->base.index[1].imm, + dcl_siv_name); +} + +static void +dcl_ps_input(struct Shader_xlate *sx, + struct ureg_program *ureg, + const struct Shader_dst_operand *dst, + uint dcl_in_ps_interp) +{ + struct ureg_src reg; + assert(dst->base.index_dim == 1); + assert(dst->base.index[0].imm < SHADER_MAX_INPUTS); + + reg = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, + dst->base.index[0].imm, + translate_interpolation(dcl_in_ps_interp)); + + dcl_base_input(sx, ureg, dst, reg, dst->base.index[0].imm, + D3D10_SB_NAME_UNDEFINED); +} + +static void +dcl_ps_sgv_input(struct Shader_xlate *sx, + struct ureg_program *ureg, + const struct Shader_dst_operand *dst, + uint dcl_siv_name) +{ + struct ureg_src reg; + assert(dst->base.index_dim == 1); + assert(dst->base.index[0].imm < SHADER_MAX_INPUTS); + + if (dcl_siv_name == D3D10_SB_NAME_POSITION) { + ureg_property(ureg, + TGSI_PROPERTY_FS_COORD_ORIGIN, + TGSI_FS_COORD_ORIGIN_UPPER_LEFT); + ureg_property(ureg, + TGSI_PROPERTY_FS_COORD_PIXEL_CENTER, + TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER); + } + + reg = ureg_DECL_fs_input(ureg, + translate_system_name(dcl_siv_name), + 0, + TGSI_INTERPOLATE_CONSTANT); + + if (dcl_siv_name == D3D10_SB_NAME_IS_FRONT_FACE) { + /* We need to map gallium's front_face to the one expected + * by D3D10 */ + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + + tmp = ureg_writemask(tmp, TGSI_WRITEMASK_X); + + ureg_CMP(ureg, tmp, reg, + ureg_imm1i(ureg, 0), ureg_imm1i(ureg, -1)); + + reg = ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X); + } + + dcl_base_input(sx, ureg, dst, reg, dst->base.index[0].imm, + dcl_siv_name); +} + +static void +dcl_ps_siv_input(struct Shader_xlate *sx, + struct ureg_program *ureg, + const struct Shader_dst_operand *dst, + uint dcl_siv_name, uint dcl_in_ps_interp) +{ + struct ureg_src reg; + assert(dst->base.index_dim == 1); + assert(dst->base.index[0].imm < SHADER_MAX_INPUTS); + + reg = ureg_DECL_fs_input(ureg, + translate_system_name(dcl_siv_name), + 0, + translate_interpolation(dcl_in_ps_interp)); + + if (dcl_siv_name == D3D10_SB_NAME_POSITION) { + /* D3D10 expects reciprocal of interpolated 1/w as 4th component, + * gallium/GL just interpolated 1/w */ + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + + ureg_MOV(ureg, tmp, reg); + ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), + ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_W)); + reg = ureg_src(tmp); + } + + dcl_base_input(sx, ureg, dst, reg, dst->base.index[0].imm, + dcl_siv_name); +} + +static struct ureg_src +translate_relative_operand(struct Shader_xlate *sx, + const struct Shader_relative_operand *operand) +{ + struct ureg_src reg; + + switch (operand->type) { + case D3D10_SB_OPERAND_TYPE_TEMP: + assert(operand->index[0].imm < SHADER_MAX_TEMPS); + + reg = ureg_src(sx->temps[sx->temp_offset + operand->index[0].imm]); + break; + + case D3D10_SB_OPERAND_TYPE_INPUT_PRIMITIVEID: + reg = sx->prim_id; + break; + + case D3D10_SB_OPERAND_TYPE_INDEXABLE_TEMP: + assert(operand->index[1].imm < SHADER_MAX_TEMPS); + + reg = ureg_src(sx->temps[sx->indexable_temp_offsets[operand->index[0].imm] + + operand->index[1].imm]); + break; + + case D3D10_SB_OPERAND_TYPE_INPUT: + case D3D10_SB_OPERAND_TYPE_OUTPUT: + case D3D10_SB_OPERAND_TYPE_IMMEDIATE32: + case D3D10_SB_OPERAND_TYPE_IMMEDIATE64: + case D3D10_SB_OPERAND_TYPE_SAMPLER: + case D3D10_SB_OPERAND_TYPE_RESOURCE: + case D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER: + case D3D10_SB_OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: + case D3D10_SB_OPERAND_TYPE_LABEL: + case D3D10_SB_OPERAND_TYPE_OUTPUT_DEPTH: + case D3D10_SB_OPERAND_TYPE_NULL: + case D3D10_SB_OPERAND_TYPE_RASTERIZER: + case D3D10_SB_OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + LOG_UNSUPPORTED(TRUE); + reg = ureg_src(ureg_DECL_temporary(sx->ureg)); + break; + + default: + assert(0); /* should never happen */ + reg = ureg_src(ureg_DECL_temporary(sx->ureg)); + } + + reg = ureg_scalar(reg, operand->comp); + return reg; +} + +static struct ureg_dst +translate_operand(struct Shader_xlate *sx, + const struct Shader_operand *operand, + unsigned writemask) +{ + struct ureg_dst reg; + + switch (operand->type) { + case D3D10_SB_OPERAND_TYPE_TEMP: + assert(operand->index_dim == 1); + assert(operand->index[0].index_rep == D3D10_SB_OPERAND_INDEX_IMMEDIATE32); + assert(operand->index[0].imm < SHADER_MAX_TEMPS); + + reg = sx->temps[sx->temp_offset + operand->index[0].imm]; + break; + + case D3D10_SB_OPERAND_TYPE_OUTPUT: + assert(operand->index_dim == 1); + assert(operand->index[0].imm < SHADER_MAX_OUTPUTS); + + if (operand->index[0].index_rep == D3D10_SB_OPERAND_INDEX_IMMEDIATE32) { + if (!writemask) { + reg = sx->outputs[operand->index[0].imm].reg[0]; + } else { + unsigned i; + for (i = 0; i < 4; ++i) { + unsigned mask = 1 << i; + if ((writemask & mask)) { + reg = sx->outputs[operand->index[0].imm].reg[i]; + break; + } + } + } + } else { + struct ureg_src addr = + translate_relative_operand(sx, &operand->index[0].rel); + assert(operand->index[0].index_rep == D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE); + reg = ureg_dst_indirect(sx->outputs[operand->index[0].imm].reg[0], addr); + } + break; + + case D3D10_SB_OPERAND_TYPE_OUTPUT_DEPTH: + assert(operand->index_dim == 0); + + reg = sx->output_depth; + break; + + case D3D10_SB_OPERAND_TYPE_INPUT_PRIMITIVEID: + assert(operand->index_dim == 0); + + reg = ureg_dst(sx->prim_id); + break; + + case D3D10_SB_OPERAND_TYPE_INPUT: + case D3D10_SB_OPERAND_TYPE_INDEXABLE_TEMP: + case D3D10_SB_OPERAND_TYPE_IMMEDIATE32: + case D3D10_SB_OPERAND_TYPE_IMMEDIATE64: + case D3D10_SB_OPERAND_TYPE_SAMPLER: + case D3D10_SB_OPERAND_TYPE_RESOURCE: + case D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER: + case D3D10_SB_OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: + case D3D10_SB_OPERAND_TYPE_LABEL: + case D3D10_SB_OPERAND_TYPE_NULL: + case D3D10_SB_OPERAND_TYPE_RASTERIZER: + case D3D10_SB_OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + /* XXX: Translate more operands types. + */ + LOG_UNSUPPORTED(TRUE); + reg = ureg_DECL_temporary(sx->ureg); + } + + return reg; +} + +static struct ureg_src +translate_indexable_temp(struct Shader_xlate *sx, + const struct Shader_operand *operand) +{ + struct ureg_src reg; + switch (operand->index[1].index_rep) { + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32: + reg = ureg_src( + sx->temps[sx->indexable_temp_offsets[operand->index[0].imm] + + operand->index[1].imm]); + break; + case D3D10_SB_OPERAND_INDEX_RELATIVE: + reg = ureg_src_indirect( + ureg_src(sx->temps[ + sx->indexable_temp_offsets[operand->index[0].imm]]), + translate_relative_operand(sx, + &operand->index[1].rel)); + break; + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + reg = ureg_src_indirect( + ureg_src(sx->temps[ + operand->index[1].imm + + sx->indexable_temp_offsets[operand->index[0].imm]]), + translate_relative_operand(sx, + &operand->index[1].rel)); + break; + default: + /* XXX: Other index representations. + */ + LOG_UNSUPPORTED(TRUE); + reg = ureg_src(ureg_DECL_temporary(sx->ureg)); + } + return reg; +} + +static struct ureg_dst +translate_dst_operand(struct Shader_xlate *sx, + const struct Shader_dst_operand *operand, + boolean saturate) +{ + struct ureg_dst reg; + unsigned writemask = + operand->mask >> D3D10_SB_OPERAND_4_COMPONENT_MASK_SHIFT; + + assert((D3D10_SB_OPERAND_4_COMPONENT_MASK_SHIFT) == 4); + assert((D3D10_SB_OPERAND_4_COMPONENT_MASK_X >> 4) == TGSI_WRITEMASK_X); + assert((D3D10_SB_OPERAND_4_COMPONENT_MASK_Y >> 4) == TGSI_WRITEMASK_Y); + assert((D3D10_SB_OPERAND_4_COMPONENT_MASK_Z >> 4) == TGSI_WRITEMASK_Z); + assert((D3D10_SB_OPERAND_4_COMPONENT_MASK_W >> 4) == TGSI_WRITEMASK_W); + + switch (operand->base.type) { + case D3D10_SB_OPERAND_TYPE_INDEXABLE_TEMP: + assert(operand->base.index_dim == 2); + assert(operand->base.index[0].index_rep == D3D10_SB_OPERAND_INDEX_IMMEDIATE32); + assert(operand->base.index[0].imm < SHADER_MAX_INDEXABLE_TEMPS); + + reg = ureg_dst(translate_indexable_temp(sx, &operand->base)); + break; + + default: + reg = translate_operand(sx, &operand->base, writemask); + } + + /* oDepth often has an empty writemask */ + if (operand->base.type != D3D10_SB_OPERAND_TYPE_OUTPUT_DEPTH) { + reg = ureg_writemask(reg, writemask); + } + + if (saturate) { + reg = ureg_saturate(reg); + } + + return reg; +} + +static struct ureg_src +translate_src_operand(struct Shader_xlate *sx, + const struct Shader_src_operand *operand, + const enum dx10_opcode_format format) +{ + struct ureg_src reg; + + switch (operand->base.type) { + case D3D10_SB_OPERAND_TYPE_INPUT: + if (operand->base.index_dim == 1) { + switch (operand->base.index[0].index_rep) { + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32: + assert(operand->base.index[0].imm < SHADER_MAX_INPUTS); + reg = sx->inputs[operand->base.index[0].imm].reg; + break; + case D3D10_SB_OPERAND_INDEX_RELATIVE: { + struct ureg_src tmp = + translate_relative_operand(sx, &operand->base.index[0].rel); + reg = ureg_src_indirect(sx->inputs[0].reg, tmp); + } + break; + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: { + struct ureg_src tmp = + translate_relative_operand(sx, &operand->base.index[0].rel); + reg = ureg_src_indirect(sx->inputs[operand->base.index[0].imm].reg, tmp); + } + break; + default: + /* XXX: Other index representations. + */ + LOG_UNSUPPORTED(TRUE); + + } + } else { + assert(operand->base.index_dim == 2); + assert(operand->base.index[1].imm < SHADER_MAX_INPUTS); + + switch (operand->base.index[1].index_rep) { + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32: + reg = sx->inputs[operand->base.index[1].imm].reg; + break; + case D3D10_SB_OPERAND_INDEX_RELATIVE: { + struct ureg_src tmp = + translate_relative_operand(sx, &operand->base.index[1].rel); + reg = ureg_src_indirect(sx->inputs[0].reg, tmp); + } + break; + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: { + struct ureg_src tmp = + translate_relative_operand(sx, &operand->base.index[1].rel); + reg = ureg_src_indirect(sx->inputs[operand->base.index[1].imm].reg, tmp); + } + break; + default: + /* XXX: Other index representations. + */ + LOG_UNSUPPORTED(TRUE); + } + + switch (operand->base.index[0].index_rep) { + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32: + reg = ureg_src_dimension(reg, operand->base.index[0].imm); + break; + case D3D10_SB_OPERAND_INDEX_RELATIVE:{ + struct ureg_src tmp = + translate_relative_operand(sx, &operand->base.index[0].rel); + reg = ureg_src_dimension_indirect(reg, tmp, 0); + } + break; + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: { + struct ureg_src tmp = + translate_relative_operand(sx, &operand->base.index[0].rel); + reg = ureg_src_dimension_indirect(reg, tmp, operand->base.index[0].imm); + } + break; + default: + /* XXX: Other index representations. + */ + LOG_UNSUPPORTED(TRUE); + } + } + break; + + case D3D10_SB_OPERAND_TYPE_INDEXABLE_TEMP: + assert(operand->base.index_dim == 2); + assert(operand->base.index[0].index_rep == D3D10_SB_OPERAND_INDEX_IMMEDIATE32); + assert(operand->base.index[0].imm < SHADER_MAX_INDEXABLE_TEMPS); + + reg = translate_indexable_temp(sx, &operand->base); + break; + + case D3D10_SB_OPERAND_TYPE_IMMEDIATE32: + switch (format) { + case OF_FLOAT: + reg = ureg_imm4f(sx->ureg, + operand->imm[0].f32, + operand->imm[1].f32, + operand->imm[2].f32, + operand->imm[3].f32); + break; + case OF_INT: + reg = ureg_imm4i(sx->ureg, + operand->imm[0].i32, + operand->imm[1].i32, + operand->imm[2].i32, + operand->imm[3].i32); + break; + case OF_UINT: + reg = ureg_imm4u(sx->ureg, + operand->imm[0].u32, + operand->imm[1].u32, + operand->imm[2].u32, + operand->imm[3].u32); + break; + default: + assert(0); + reg = ureg_src(ureg_DECL_temporary(sx->ureg)); + } + break; + + case D3D10_SB_OPERAND_TYPE_SAMPLER: + assert(operand->base.index_dim == 1); + assert(operand->base.index[0].index_rep == D3D10_SB_OPERAND_INDEX_IMMEDIATE32); + assert(operand->base.index[0].imm < SHADER_MAX_SAMPLERS); + + reg = sx->samplers[operand->base.index[0].imm]; + break; + + case D3D10_SB_OPERAND_TYPE_RESOURCE: + assert(operand->base.index_dim == 1); + assert(operand->base.index[0].index_rep == D3D10_SB_OPERAND_INDEX_IMMEDIATE32); + assert(operand->base.index[0].imm < SHADER_MAX_RESOURCES); + + reg = sx->sv[operand->base.index[0].imm]; + break; + + case D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER: + assert(operand->base.index_dim == 2); + + assert(operand->base.index[0].index_rep == D3D10_SB_OPERAND_INDEX_IMMEDIATE32); + assert(operand->base.index[0].imm < PIPE_MAX_CONSTANT_BUFFERS); + + switch (operand->base.index[1].index_rep) { + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32: + assert(operand->base.index[1].imm < SHADER_MAX_CONSTS); + + reg = ureg_src_register(TGSI_FILE_CONSTANT, operand->base.index[1].imm); + reg = ureg_src_dimension(reg, operand->base.index[0].imm); + break; + case D3D10_SB_OPERAND_INDEX_RELATIVE: + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + reg = ureg_src_register(TGSI_FILE_CONSTANT, operand->base.index[1].imm); + reg = ureg_src_indirect( + reg, + translate_relative_operand(sx, &operand->base.index[1].rel)); + reg = ureg_src_dimension(reg, operand->base.index[0].imm); + break; + default: + /* XXX: Other index representations. + */ + LOG_UNSUPPORTED(TRUE); + } + + break; + + case D3D10_SB_OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: + assert(operand->base.index_dim == 1); + + switch (operand->base.index[0].index_rep) { + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32: + reg = sx->imms; + reg.Index += operand->base.index[0].imm; + break; + case D3D10_SB_OPERAND_INDEX_RELATIVE: + case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + reg = sx->imms; + reg.Index += operand->base.index[0].imm; + reg = ureg_src_indirect( + sx->imms, + translate_relative_operand(sx, &operand->base.index[0].rel)); + break; + default: + /* XXX: Other index representations. + */ + LOG_UNSUPPORTED(TRUE); + } + break; + + case D3D10_SB_OPERAND_TYPE_INPUT_PRIMITIVEID: + reg = sx->prim_id; + break; + + default: + reg = ureg_src(translate_operand(sx, &operand->base, 0)); + } + + reg = ureg_swizzle(reg, + operand->swizzle[0], + operand->swizzle[1], + operand->swizzle[2], + operand->swizzle[3]); + + switch (operand->modifier) { + case D3D10_SB_OPERAND_MODIFIER_NONE: + break; + case D3D10_SB_OPERAND_MODIFIER_NEG: + reg = ureg_negate(reg); + break; + case D3D10_SB_OPERAND_MODIFIER_ABS: + reg = ureg_abs(reg); + break; + case D3D10_SB_OPERAND_MODIFIER_ABSNEG: + reg = ureg_negate(ureg_abs(reg)); + break; + default: + assert(0); + } + + return reg; +} + +static uint +translate_resource_dimension(D3D10_SB_RESOURCE_DIMENSION dim) +{ + switch (dim) { + case D3D10_SB_RESOURCE_DIMENSION_UNKNOWN: + return TGSI_TEXTURE_UNKNOWN; + case D3D10_SB_RESOURCE_DIMENSION_BUFFER: + return TGSI_TEXTURE_BUFFER; + case D3D10_SB_RESOURCE_DIMENSION_TEXTURE1D: + return TGSI_TEXTURE_1D; + case D3D10_SB_RESOURCE_DIMENSION_TEXTURE2D: + return TGSI_TEXTURE_2D; + case D3D10_SB_RESOURCE_DIMENSION_TEXTURE2DMS: + return TGSI_TEXTURE_2D_MSAA; + case D3D10_SB_RESOURCE_DIMENSION_TEXTURE3D: + return TGSI_TEXTURE_3D; + case D3D10_SB_RESOURCE_DIMENSION_TEXTURECUBE: + return TGSI_TEXTURE_CUBE; + case D3D10_SB_RESOURCE_DIMENSION_TEXTURE1DARRAY: + return TGSI_TEXTURE_1D_ARRAY; + case D3D10_SB_RESOURCE_DIMENSION_TEXTURE2DARRAY: + return TGSI_TEXTURE_2D_ARRAY; + case D3D10_SB_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + return TGSI_TEXTURE_2D_ARRAY_MSAA; + case D3D10_SB_RESOURCE_DIMENSION_TEXTURECUBEARRAY: + return TGSI_TEXTURE_CUBE_ARRAY; + default: + assert(0); + return TGSI_TEXTURE_UNKNOWN; + } +} + +static uint +texture_dim_from_tgsi_target(unsigned tgsi_target) +{ + switch (tgsi_target) { + case TGSI_TEXTURE_BUFFER: + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_1D_ARRAY: + return 1; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_2D_MSAA: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_2D_ARRAY: + case TGSI_TEXTURE_2D_ARRAY_MSAA: + return 2; + case TGSI_TEXTURE_3D: + return 3; + case TGSI_TEXTURE_UNKNOWN: + default: + assert(0); + return 1; + } +} + +static boolean +operand_is_scalar(const struct Shader_src_operand *operand) +{ + return operand->swizzle[0] == operand->swizzle[1] && + operand->swizzle[1] == operand->swizzle[2] && + operand->swizzle[2] == operand->swizzle[3]; +} + +static void +Shader_add_call(struct Shader_xlate *sx, + unsigned d3d_label, + unsigned tgsi_label_token) +{ + ASSERT(sx->num_calls < sx->max_calls); + + sx->calls[sx->num_calls].d3d_label = d3d_label; + sx->calls[sx->num_calls].tgsi_label_token = tgsi_label_token; + sx->num_calls++; +} + +static void +Shader_add_label(struct Shader_xlate *sx, + unsigned d3d_label, + unsigned tgsi_insn_no) +{ + ASSERT(sx->num_labels < sx->max_labels); + + sx->labels[sx->num_labels].d3d_label = d3d_label; + sx->labels[sx->num_labels].tgsi_insn_no = tgsi_insn_no; + sx->num_labels++; +} + + +static void +sample_ureg_emit(struct ureg_program *ureg, + unsigned tgsi_opcode, + unsigned num_src, + struct Shader_opcode *opcode, + struct ureg_dst dst, + struct ureg_src *src) +{ + unsigned num_offsets = 0; + struct tgsi_texture_offset texoffsets; + + memset(&texoffsets, 0, sizeof texoffsets); + + if (opcode->imm_texel_offset.u || + opcode->imm_texel_offset.v || + opcode->imm_texel_offset.w) { + struct ureg_src offsetreg; + num_offsets = 1; + /* don't actually always need all 3 values */ + offsetreg = ureg_imm3i(ureg, + opcode->imm_texel_offset.u, + opcode->imm_texel_offset.v, + opcode->imm_texel_offset.w); + texoffsets.File = offsetreg.File; + texoffsets.Index = offsetreg.Index; + texoffsets.SwizzleX = offsetreg.SwizzleX; + texoffsets.SwizzleY = offsetreg.SwizzleY; + texoffsets.SwizzleZ = offsetreg.SwizzleZ; + } + + ureg_tex_insn(ureg, + tgsi_opcode, + &dst, 1, + TGSI_TEXTURE_UNKNOWN, + TGSI_RETURN_TYPE_UNKNOWN, + &texoffsets, num_offsets, + src, num_src); +} + +typedef void (*unary_ureg_func)(struct ureg_program *ureg, struct ureg_dst dst, + struct ureg_src src); +static void +expand_unary_to_scalarf(struct ureg_program *ureg, unary_ureg_func func, + struct Shader_xlate *sx, struct Shader_opcode *opcode) +{ + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_dst dst = translate_dst_operand(sx, &opcode->dst[0], + opcode->saturate); + struct ureg_src src = translate_src_operand(sx, &opcode->src[0], OF_FLOAT); + struct ureg_dst scalar_dst; + ureg_MOV(ureg, tmp, src); + src = ureg_src(tmp); + + scalar_dst = ureg_writemask(dst, TGSI_WRITEMASK_X); + if (scalar_dst.WriteMask != TGSI_WRITEMASK_NONE) { + func(ureg, scalar_dst, + ureg_scalar(src, TGSI_SWIZZLE_X)); + } + scalar_dst = ureg_writemask(dst, TGSI_WRITEMASK_Y); + if (scalar_dst.WriteMask != TGSI_WRITEMASK_NONE) { + func(ureg, scalar_dst, + ureg_scalar(src, TGSI_SWIZZLE_Y)); + } + scalar_dst = ureg_writemask(dst, TGSI_WRITEMASK_Z); + if (scalar_dst.WriteMask != TGSI_WRITEMASK_NONE) { + func(ureg, scalar_dst, + ureg_scalar(src, TGSI_SWIZZLE_Z)); + } + scalar_dst = ureg_writemask(dst, TGSI_WRITEMASK_W); + if (scalar_dst.WriteMask != TGSI_WRITEMASK_NONE) { + func(ureg, scalar_dst, + ureg_scalar(src, TGSI_SWIZZLE_W)); + } + ureg_release_temporary(ureg, tmp); +} + +const struct tgsi_token * +Shader_tgsi_translate(const unsigned *code, + unsigned *output_mapping) +{ + struct Shader_xlate sx; + struct Shader_parser parser; + struct ureg_program *ureg = NULL; + struct Shader_opcode opcode; + const struct tgsi_token *tokens = NULL; + uint nr_tokens; + boolean shader_dumped = FALSE; + boolean inside_sub = FALSE; + uint i, j; + + memset(&sx, 0, sizeof sx); + + Shader_parse_init(&parser, code); + + if (st_debug & ST_DEBUG_TGSI) { + dx10_shader_dump_tokens(code); + shader_dumped = TRUE; + } + + sx.max_calls = 64; + sx.calls = (struct Shader_call *)MALLOC(sx.max_calls * + sizeof(struct Shader_call)); + sx.num_calls = 0; + + sx.max_labels = 64; + sx.labels = (struct Shader_label *)MALLOC(sx.max_labels * + sizeof(struct Shader_call)); + sx.num_labels = 0; + + + + /* Header. */ + switch (parser.header.type) { + case D3D10_SB_PIXEL_SHADER: + ureg = ureg_create(PIPE_SHADER_FRAGMENT); + break; + case D3D10_SB_VERTEX_SHADER: + ureg = ureg_create(PIPE_SHADER_VERTEX); + break; + case D3D10_SB_GEOMETRY_SHADER: + ureg = ureg_create(PIPE_SHADER_GEOMETRY); + break; + } + + assert(ureg); + sx.ureg = ureg; + + while (Shader_parse_opcode(&parser, &opcode)) { + const struct dx10_opcode_xlate *ox; + + assert(opcode.type < D3D10_SB_NUM_OPCODES); + ox = &opcode_xlate[opcode.type]; + + switch (opcode.type) { + case D3D10_SB_OPCODE_EXP: + expand_unary_to_scalarf(ureg, ureg_EX2, &sx, &opcode); + break; + case D3D10_SB_OPCODE_SQRT: + expand_unary_to_scalarf(ureg, ureg_SQRT, &sx, &opcode); + break; + case D3D10_SB_OPCODE_RSQ: + expand_unary_to_scalarf(ureg, ureg_RSQ, &sx, &opcode); + break; + case D3D10_SB_OPCODE_LOG: + expand_unary_to_scalarf(ureg, ureg_LG2, &sx, &opcode); + break; + case D3D10_SB_OPCODE_IMUL: + if (opcode.dst[0].base.type != D3D10_SB_OPERAND_TYPE_NULL) { + ureg_IMUL_HI(ureg, + translate_dst_operand(&sx, &opcode.dst[0], opcode.saturate), + translate_src_operand(&sx, &opcode.src[0], OF_INT), + translate_src_operand(&sx, &opcode.src[1], OF_INT)); + } + + if (opcode.dst[1].base.type != D3D10_SB_OPERAND_TYPE_NULL) { + ureg_UMUL(ureg, + translate_dst_operand(&sx, &opcode.dst[1], opcode.saturate), + translate_src_operand(&sx, &opcode.src[0], OF_INT), + translate_src_operand(&sx, &opcode.src[1], OF_INT)); + } + + break; + + case D3D10_SB_OPCODE_FTOI: { + /* XXX: tgsi (and just about everybody else, c, opencl, glsl) has + * out-of-range (and NaN) values undefined for f2i/f2u, but d3d10 + * requires clamping to min and max representable value (as well as 0 + * for NaNs) (this applies to both ftoi and ftou). At least the online + * docs state that - this is consistent with generic d3d10 conversion + * rules. + * For FTOI, we cheat a bit here - in particular depending on noone + * caring about NaNs, and depending on the (undefined!) behavior of + * F2I returning 0x80000000 for too negative values (which works with + * x86 sse). Hence only need to clamp too positive values. + * Note that it is impossible to clamp using a float, since 2^31 - 1 + * is not exactly representable with a float. + */ + struct ureg_dst too_large = ureg_DECL_temporary(ureg); + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + ureg_FSGE(ureg, too_large, + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT), + ureg_imm1f(ureg, 2147483648.0f)); + ureg_F2I(ureg, tmp, + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT)); + ureg_UCMP(ureg, + translate_dst_operand(&sx, &opcode.dst[0], opcode.saturate), + ureg_src(too_large), + ureg_imm1i(ureg, 0x7fffffff), + ureg_src(tmp)); + ureg_release_temporary(ureg, too_large); + ureg_release_temporary(ureg, tmp); + } + break; + + case D3D10_SB_OPCODE_FTOU: { + /* For ftou, we need to do both clamps, which as a bonus also + * gets us correct NaN behavior. + * Note that it is impossible to clamp using a float against the upper + * limit, since 2^32 - 1 is not exactly representable with a float, + * but the clamp against 0.0 certainly works just fine. + */ + struct ureg_dst too_large = ureg_DECL_temporary(ureg); + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + ureg_FSGE(ureg, too_large, + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT), + ureg_imm1f(ureg, 4294967296.0f)); + /* clamp negative values + NaN to zero. + * (Could be done slightly more efficient in llvmpipe due to + * MAX NaN behavior handling.) + */ + ureg_MAX(ureg, tmp, + ureg_imm1f(ureg, 0.0f), + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT)); + ureg_F2U(ureg, tmp, + ureg_src(tmp)); + ureg_UCMP(ureg, + translate_dst_operand(&sx, &opcode.dst[0], opcode.saturate), + ureg_src(too_large), + ureg_imm1u(ureg, 0xffffffff), + ureg_src(tmp)); + ureg_release_temporary(ureg, too_large); + ureg_release_temporary(ureg, tmp); + } + break; + + case D3D10_SB_OPCODE_LD_MS: + /* XXX: We don't support multi-sampling yet, but we need to parse + * this opcode regardless, so we just ignore sample index operand + * for now */ + case D3D10_SB_OPCODE_LD: + if (st_debug & ST_DEBUG_OLD_TEX_OPS) { + unsigned resource = opcode.src[1].base.index[0].imm; + assert(opcode.src[1].base.index_dim == 1); + assert(opcode.src[1].base.index[0].imm < SHADER_MAX_RESOURCES); + + if (ureg_src_is_undef(sx.samplers[resource])) { + sx.samplers[resource] = + ureg_DECL_sampler(ureg, resource); + } + + ureg_TXF(ureg, + translate_dst_operand(&sx, &opcode.dst[0], opcode.saturate), + sx.resources[resource].target, + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT), + sx.samplers[resource]); + } + else { + struct ureg_src srcreg[2]; + srcreg[0] = translate_src_operand(&sx, &opcode.src[0], OF_INT); + srcreg[1] = translate_src_operand(&sx, &opcode.src[1], OF_INT); + + sample_ureg_emit(ureg, TGSI_OPCODE_SAMPLE_I, 2, &opcode, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + srcreg); + } + break; + + case D3D10_SB_OPCODE_CUSTOMDATA: + if (opcode.customdata._class == + D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER) { + sx.imms = + ureg_DECL_immediate_block_uint(ureg, + opcode.customdata.u.constbuf.data, + opcode.customdata.u.constbuf.count); + } else { + assert(0); + } + break; + + case D3D10_SB_OPCODE_RESINFO: + if (st_debug & ST_DEBUG_OLD_TEX_OPS) { + unsigned resource = opcode.src[1].base.index[0].imm; + assert(opcode.src[1].base.index_dim == 1); + assert(opcode.src[1].base.index[0].imm < SHADER_MAX_RESOURCES); + + if (ureg_src_is_undef(sx.samplers[resource])) { + sx.samplers[resource] = + ureg_DECL_sampler(ureg, resource); + } + /* don't bother with swizzle, ret type etc. */ + ureg_TXQ(ureg, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + sx.resources[resource].target, + translate_src_operand(&sx, &opcode.src[0], OF_UINT), + sx.samplers[resource]); + } + else { + struct ureg_dst r0 = ureg_DECL_temporary(ureg); + struct ureg_src tsrc = translate_src_operand(&sx, &opcode.src[1], OF_UINT); + struct ureg_dst dstreg = translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate); + + /* while specs say swizzle is ignored better safe than sorry */ + tsrc.SwizzleX = TGSI_SWIZZLE_X; + tsrc.SwizzleY = TGSI_SWIZZLE_Y; + tsrc.SwizzleZ = TGSI_SWIZZLE_Z; + tsrc.SwizzleW = TGSI_SWIZZLE_W; + + ureg_SVIEWINFO(ureg, r0, + translate_src_operand(&sx, &opcode.src[0], OF_UINT), + tsrc); + + tsrc = ureg_src(r0); + tsrc.SwizzleX = opcode.src[1].swizzle[0]; + tsrc.SwizzleY = opcode.src[1].swizzle[1]; + tsrc.SwizzleZ = opcode.src[1].swizzle[2]; + tsrc.SwizzleW = opcode.src[1].swizzle[3]; + + if (opcode.specific.resinfo_ret_type == + D3D10_SB_RESINFO_INSTRUCTION_RETURN_UINT) { + ureg_MOV(ureg, dstreg, tsrc); + } + else if (opcode.specific.resinfo_ret_type == + D3D10_SB_RESINFO_INSTRUCTION_RETURN_FLOAT) { + ureg_I2F(ureg, dstreg, tsrc); + } + else { /* D3D10_SB_RESINFO_INSTRUCTION_RETURN_RCPFLOAT */ + unsigned i; + /* + * Must apply rcp only to parts determined by dims, + * (width/height/depth) but NOT to array size nor mip levels + * hence need to figure that out here. + * This is one sick modifier if you ask me! + */ + unsigned res_index = opcode.src[1].base.index[0].imm; + unsigned target = sx.resources[res_index].target; + unsigned dims = texture_dim_from_tgsi_target(target); + + ureg_I2F(ureg, r0, ureg_src(r0)); + tsrc = ureg_src(r0); + for (i = 0; i < 4; i++) { + unsigned dst_swizzle = opcode.src[1].swizzle[i]; + struct ureg_dst dstregmasked = ureg_writemask(dstreg, 1 << i); + /* + * could do one mov with multiple write mask bits set + * but rcp is scalar anyway. + */ + if (dst_swizzle < dims) { + ureg_RCP(ureg, dstregmasked, ureg_scalar(tsrc, dst_swizzle)); + } + else { + ureg_MOV(ureg, dstregmasked, ureg_scalar(tsrc, dst_swizzle)); + } + } + } + ureg_release_temporary(ureg, r0); + } + break; + + case D3D10_SB_OPCODE_SAMPLE: + if (st_debug & ST_DEBUG_OLD_TEX_OPS) { + assert(opcode.src[1].base.index_dim == 1); + assert(opcode.src[1].base.index[0].imm < SHADER_MAX_RESOURCES); + + LOG_UNSUPPORTED(opcode.src[1].base.index[0].imm != opcode.src[2].base.index[0].imm); + + ureg_TEX(ureg, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + sx.resources[opcode.src[1].base.index[0].imm].target, + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT), + translate_src_operand(&sx, &opcode.src[2], OF_FLOAT)); + } + else { + struct ureg_src srcreg[3]; + srcreg[0] = translate_src_operand(&sx, &opcode.src[0], OF_FLOAT); + srcreg[1] = translate_src_operand(&sx, &opcode.src[1], OF_UINT); + srcreg[2] = translate_src_operand(&sx, &opcode.src[2], OF_UINT); + + sample_ureg_emit(ureg, TGSI_OPCODE_SAMPLE, 3, &opcode, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + srcreg); + } + break; + + case D3D10_SB_OPCODE_SAMPLE_C: + if (st_debug & ST_DEBUG_OLD_TEX_OPS) { + struct ureg_dst r0 = ureg_DECL_temporary(ureg); + + /* XXX: Support only 2D texture targets for now. + * Need to figure out how to pack the compare value + * for other dimensions and if there is enough space + * in a single operand for all possible cases. + */ + LOG_UNSUPPORTED(sx.resources[opcode.src[1].base.index[0].imm].target != + TGSI_TEXTURE_2D); + + assert(opcode.src[1].base.index_dim == 1); + assert(opcode.src[1].base.index[0].imm < SHADER_MAX_RESOURCES); + + /* Insert the compare value into .z component. + */ + ureg_MOV(ureg, + ureg_writemask(r0, TGSI_WRITEMASK_XYW), + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT)); + ureg_MOV(ureg, + ureg_writemask(r0, TGSI_WRITEMASK_Z), + translate_src_operand(&sx, &opcode.src[3], OF_FLOAT)); + + /* XXX: Pass explicit Lod=0 in D3D10_SB_OPCODE_SAMPLE_C_LZ case. + */ + + ureg_TEX(ureg, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + sx.resources[opcode.src[1].base.index[0].imm].target, + ureg_src(r0), + translate_src_operand(&sx, &opcode.src[2], OF_FLOAT)); + + ureg_release_temporary(ureg, r0); + } + else { + struct ureg_src srcreg[4]; + srcreg[0] = translate_src_operand(&sx, &opcode.src[0], OF_FLOAT); + srcreg[1] = translate_src_operand(&sx, &opcode.src[1], OF_UINT); + srcreg[2] = translate_src_operand(&sx, &opcode.src[2], OF_UINT); + srcreg[3] = translate_src_operand(&sx, &opcode.src[3], OF_FLOAT); + + sample_ureg_emit(ureg, TGSI_OPCODE_SAMPLE_C, 4, &opcode, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + srcreg); + } + break; + + case D3D10_SB_OPCODE_SAMPLE_C_LZ: + if (st_debug & ST_DEBUG_OLD_TEX_OPS) { + struct ureg_dst r0 = ureg_DECL_temporary(ureg); + + assert(opcode.src[1].base.index_dim == 1); + assert(opcode.src[1].base.index[0].imm < SHADER_MAX_RESOURCES); + + /* XXX: Support only 2D texture targets for now. + * Need to figure out how to pack the compare value + * for other dimensions and if there is enough space + * in a single operand for all possible cases. + */ + LOG_UNSUPPORTED(sx.resources[opcode.src[1].base.index[0].imm].target != + TGSI_TEXTURE_2D); + + /* Insert the compare value into .z component. + * Insert 0 into .w component. + */ + ureg_MOV(ureg, + ureg_writemask(r0, TGSI_WRITEMASK_XY), + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT)); + ureg_MOV(ureg, + ureg_writemask(r0, TGSI_WRITEMASK_Z), + translate_src_operand(&sx, &opcode.src[3], OF_FLOAT)); + ureg_MOV(ureg, + ureg_writemask(r0, TGSI_WRITEMASK_W), + ureg_imm1f(ureg, 0.0f)); + + ureg_TXL(ureg, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + sx.resources[opcode.src[1].base.index[0].imm].target, + ureg_src(r0), + translate_src_operand(&sx, &opcode.src[2], OF_FLOAT)); + + ureg_release_temporary(ureg, r0); + } + else { + struct ureg_src srcreg[4]; + srcreg[0] = translate_src_operand(&sx, &opcode.src[0], OF_FLOAT); + srcreg[1] = translate_src_operand(&sx, &opcode.src[1], OF_UINT); + srcreg[2] = translate_src_operand(&sx, &opcode.src[2], OF_UINT); + srcreg[3] = translate_src_operand(&sx, &opcode.src[3], OF_FLOAT); + + sample_ureg_emit(ureg, TGSI_OPCODE_SAMPLE_C_LZ, 4, &opcode, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + srcreg); + } + break; + + case D3D10_SB_OPCODE_SAMPLE_L: + if (st_debug & ST_DEBUG_OLD_TEX_OPS) { + struct ureg_dst r0 = ureg_DECL_temporary(ureg); + + assert(opcode.src[1].base.index_dim == 1); + assert(opcode.src[1].base.index[0].imm < SHADER_MAX_RESOURCES); + + /* Insert LOD into .w component. + */ + ureg_MOV(ureg, + ureg_writemask(r0, TGSI_WRITEMASK_XYZ), + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT)); + ureg_MOV(ureg, + ureg_writemask(r0, TGSI_WRITEMASK_W), + translate_src_operand(&sx, &opcode.src[3], OF_FLOAT)); + + ureg_TXL(ureg, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + sx.resources[opcode.src[1].base.index[0].imm].target, + ureg_src(r0), + translate_src_operand(&sx, &opcode.src[2], OF_FLOAT)); + + ureg_release_temporary(ureg, r0); + } + else { + struct ureg_src srcreg[4]; + srcreg[0] = translate_src_operand(&sx, &opcode.src[0], OF_FLOAT); + srcreg[1] = translate_src_operand(&sx, &opcode.src[1], OF_UINT); + srcreg[2] = translate_src_operand(&sx, &opcode.src[2], OF_UINT); + srcreg[3] = translate_src_operand(&sx, &opcode.src[3], OF_FLOAT); + + sample_ureg_emit(ureg, TGSI_OPCODE_SAMPLE_L, 4, &opcode, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + srcreg); + } + break; + + case D3D10_SB_OPCODE_SAMPLE_D: + if (st_debug & ST_DEBUG_OLD_TEX_OPS) { + assert(opcode.src[1].base.index_dim == 1); + assert(opcode.src[1].base.index[0].imm < SHADER_MAX_RESOURCES); + + ureg_TXD(ureg, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + sx.resources[opcode.src[1].base.index[0].imm].target, + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT), + translate_src_operand(&sx, &opcode.src[3], OF_FLOAT), + translate_src_operand(&sx, &opcode.src[4], OF_FLOAT), + translate_src_operand(&sx, &opcode.src[2], OF_FLOAT)); + } + else { + struct ureg_src srcreg[5]; + srcreg[0] = translate_src_operand(&sx, &opcode.src[0], OF_FLOAT); + srcreg[1] = translate_src_operand(&sx, &opcode.src[1], OF_UINT); + srcreg[2] = translate_src_operand(&sx, &opcode.src[2], OF_UINT); + srcreg[3] = translate_src_operand(&sx, &opcode.src[3], OF_FLOAT); + srcreg[4] = translate_src_operand(&sx, &opcode.src[4], OF_FLOAT); + + sample_ureg_emit(ureg, TGSI_OPCODE_SAMPLE_D, 5, &opcode, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + srcreg); + } + break; + + case D3D10_SB_OPCODE_SAMPLE_B: + if (st_debug & ST_DEBUG_OLD_TEX_OPS) { + struct ureg_dst r0 = ureg_DECL_temporary(ureg); + + assert(opcode.src[1].base.index_dim == 1); + assert(opcode.src[1].base.index[0].imm < SHADER_MAX_RESOURCES); + + /* Insert LOD bias into .w component. + */ + ureg_MOV(ureg, + ureg_writemask(r0, TGSI_WRITEMASK_XYZ), + translate_src_operand(&sx, &opcode.src[0], OF_FLOAT)); + ureg_MOV(ureg, + ureg_writemask(r0, TGSI_WRITEMASK_W), + translate_src_operand(&sx, &opcode.src[3], OF_FLOAT)); + + ureg_TXB(ureg, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + sx.resources[opcode.src[1].base.index[0].imm].target, + ureg_src(r0), + translate_src_operand(&sx, &opcode.src[2], OF_FLOAT)); + + ureg_release_temporary(ureg, r0); + } + else { + struct ureg_src srcreg[4]; + srcreg[0] = translate_src_operand(&sx, &opcode.src[0], OF_FLOAT); + srcreg[1] = translate_src_operand(&sx, &opcode.src[1], OF_UINT); + srcreg[2] = translate_src_operand(&sx, &opcode.src[2], OF_UINT); + srcreg[3] = translate_src_operand(&sx, &opcode.src[3], OF_FLOAT); + + sample_ureg_emit(ureg, TGSI_OPCODE_SAMPLE_B, 4, &opcode, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + srcreg); + } + break; + + case D3D10_SB_OPCODE_SINCOS: { + struct ureg_dst src0 = ureg_DECL_temporary(ureg); + ureg_MOV(ureg, src0, translate_src_operand(&sx, &opcode.src[0], OF_FLOAT)); + if (opcode.dst[0].base.type != D3D10_SB_OPERAND_TYPE_NULL) { + struct ureg_dst dst = translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate); + struct ureg_src src = ureg_src(src0); + ureg_SIN(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), + ureg_scalar(src, TGSI_SWIZZLE_X)); + ureg_SIN(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), + ureg_scalar(src, TGSI_SWIZZLE_Y)); + ureg_SIN(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Z), + ureg_scalar(src, TGSI_SWIZZLE_Z)); + ureg_SIN(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), + ureg_scalar(src, TGSI_SWIZZLE_W)); + } + if (opcode.dst[1].base.type != D3D10_SB_OPERAND_TYPE_NULL) { + struct ureg_dst dst = translate_dst_operand(&sx, &opcode.dst[1], + opcode.saturate); + struct ureg_src src = ureg_src(src0); + ureg_COS(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), + ureg_scalar(src, TGSI_SWIZZLE_X)); + ureg_COS(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), + ureg_scalar(src, TGSI_SWIZZLE_Y)); + ureg_COS(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Z), + ureg_scalar(src, TGSI_SWIZZLE_Z)); + ureg_COS(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), + ureg_scalar(src, TGSI_SWIZZLE_W)); + } + ureg_release_temporary(ureg, src0); + } + break; + + case D3D10_SB_OPCODE_UDIV: { + struct ureg_dst src0 = ureg_DECL_temporary(ureg); + struct ureg_dst src1 = ureg_DECL_temporary(ureg); + ureg_MOV(ureg, src0, translate_src_operand(&sx, &opcode.src[0], OF_UINT)); + ureg_MOV(ureg, src1, translate_src_operand(&sx, &opcode.src[1], OF_UINT)); + if (opcode.dst[0].base.type != D3D10_SB_OPERAND_TYPE_NULL) { + ureg_UDIV(ureg, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + ureg_src(src0), ureg_src(src1)); + } + if (opcode.dst[1].base.type != D3D10_SB_OPERAND_TYPE_NULL) { + ureg_UMOD(ureg, + translate_dst_operand(&sx, &opcode.dst[1], + opcode.saturate), + ureg_src(src0), ureg_src(src1)); + } + ureg_release_temporary(ureg, src0); + ureg_release_temporary(ureg, src1); + } + break; + case D3D10_SB_OPCODE_UMUL: { + if (opcode.dst[0].base.type != D3D10_SB_OPERAND_TYPE_NULL) { + ureg_UMUL_HI(ureg, + translate_dst_operand(&sx, &opcode.dst[0], + opcode.saturate), + translate_src_operand(&sx, &opcode.src[0], OF_UINT), + translate_src_operand(&sx, &opcode.src[1], OF_UINT)); + } + if (opcode.dst[1].base.type != D3D10_SB_OPERAND_TYPE_NULL) { + ureg_UMUL(ureg, + translate_dst_operand(&sx, &opcode.dst[1], + opcode.saturate), + translate_src_operand(&sx, &opcode.src[0], OF_UINT), + translate_src_operand(&sx, &opcode.src[1], OF_UINT)); + } + } + break; + + case D3D10_SB_OPCODE_DCL_RESOURCE: + { + unsigned target; + unsigned res_index = opcode.dst[0].base.index[0].imm; + assert(opcode.dst[0].base.index_dim == 1); + assert(res_index < SHADER_MAX_RESOURCES); + + target = translate_resource_dimension(opcode.specific.dcl_resource_dimension); + sx.resources[res_index].target = target; + if (!(st_debug & ST_DEBUG_OLD_TEX_OPS)) { + sx.sv[res_index] = + ureg_DECL_sampler_view(ureg, res_index, target, + trans_dcl_ret_type(opcode.dcl_resource_ret_type[0]), + trans_dcl_ret_type(opcode.dcl_resource_ret_type[1]), + trans_dcl_ret_type(opcode.dcl_resource_ret_type[2]), + trans_dcl_ret_type(opcode.dcl_resource_ret_type[3])); + } + break; + } + + case D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER: { + unsigned num_constants = opcode.src[0].base.index[1].imm; + + assert(opcode.src[0].base.index[0].imm < PIPE_MAX_CONSTANT_BUFFERS); + + if (num_constants == 0) { + num_constants = SHADER_MAX_CONSTS; + } else { + assert(num_constants <= SHADER_MAX_CONSTS); + } + + ureg_DECL_constant2D(ureg, + 0, + num_constants - 1, + opcode.src[0].base.index[0].imm); + break; + } + + case D3D10_SB_OPCODE_DCL_SAMPLER: + assert(opcode.dst[0].base.index_dim == 1); + assert(opcode.dst[0].base.index[0].imm < SHADER_MAX_SAMPLERS); + + sx.samplers[opcode.dst[0].base.index[0].imm] = + ureg_DECL_sampler(ureg, + opcode.dst[0].base.index[0].imm); + break; + + case D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + assert(parser.header.type == D3D10_SB_GEOMETRY_SHADER); + + switch (opcode.specific.dcl_gs_output_primitive_topology) { + case D3D10_SB_PRIMITIVE_TOPOLOGY_POINTLIST: + ureg_property(sx.ureg, + TGSI_PROPERTY_GS_OUTPUT_PRIM, + PIPE_PRIM_POINTS); + break; + + case D3D10_SB_PRIMITIVE_TOPOLOGY_LINESTRIP: + ureg_property(sx.ureg, + TGSI_PROPERTY_GS_OUTPUT_PRIM, + PIPE_PRIM_LINE_STRIP); + break; + + case D3D10_SB_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: + ureg_property(sx.ureg, + TGSI_PROPERTY_GS_OUTPUT_PRIM, + PIPE_PRIM_TRIANGLE_STRIP); + break; + + default: + assert(0); + } + break; + + case D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE: + assert(parser.header.type == D3D10_SB_GEOMETRY_SHADER); + + /* Figure out the second dimension of GS inputs. + */ + switch (opcode.specific.dcl_gs_input_primitive) { + case D3D10_SB_PRIMITIVE_POINT: + declare_vertices_in(&sx, 1); + ureg_property(sx.ureg, + TGSI_PROPERTY_GS_INPUT_PRIM, + PIPE_PRIM_POINTS); + break; + + case D3D10_SB_PRIMITIVE_LINE: + declare_vertices_in(&sx, 2); + ureg_property(sx.ureg, + TGSI_PROPERTY_GS_INPUT_PRIM, + PIPE_PRIM_LINES); + break; + + case D3D10_SB_PRIMITIVE_TRIANGLE: + declare_vertices_in(&sx, 3); + ureg_property(sx.ureg, + TGSI_PROPERTY_GS_INPUT_PRIM, + PIPE_PRIM_TRIANGLES); + break; + + case D3D10_SB_PRIMITIVE_LINE_ADJ: + declare_vertices_in(&sx, 4); + ureg_property(sx.ureg, + TGSI_PROPERTY_GS_INPUT_PRIM, + PIPE_PRIM_LINES_ADJACENCY); + break; + + case D3D10_SB_PRIMITIVE_TRIANGLE_ADJ: + declare_vertices_in(&sx, 6); + ureg_property(sx.ureg, + TGSI_PROPERTY_GS_INPUT_PRIM, + PIPE_PRIM_TRIANGLES_ADJACENCY); + break; + + default: + assert(0); + } + break; + + case D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + assert(parser.header.type == D3D10_SB_GEOMETRY_SHADER); + + ureg_property(sx.ureg, + TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, + opcode.specific.dcl_max_output_vertex_count); + break; + + case D3D10_SB_OPCODE_DCL_INPUT: + if (parser.header.type == D3D10_SB_VERTEX_SHADER) { + dcl_vs_input(&sx, ureg, &opcode.dst[0]); + } else { + assert(parser.header.type == D3D10_SB_GEOMETRY_SHADER); + dcl_gs_input(&sx, ureg, &opcode.dst[0]); + } + break; + + case D3D10_SB_OPCODE_DCL_INPUT_SGV: + assert(parser.header.type == D3D10_SB_VERTEX_SHADER); + dcl_sgv_input(&sx, ureg, &opcode.dst[0], opcode.dcl_siv_name); + break; + + case D3D10_SB_OPCODE_DCL_INPUT_SIV: + assert(parser.header.type == D3D10_SB_GEOMETRY_SHADER); + dcl_siv_input(&sx, ureg, &opcode.dst[0], opcode.dcl_siv_name); + break; + + case D3D10_SB_OPCODE_DCL_INPUT_PS: + assert(parser.header.type == D3D10_SB_PIXEL_SHADER); + dcl_ps_input(&sx, ureg, &opcode.dst[0], + opcode.specific.dcl_in_ps_interp); + break; + + case D3D10_SB_OPCODE_DCL_INPUT_PS_SGV: + assert(parser.header.type == D3D10_SB_PIXEL_SHADER); + dcl_ps_sgv_input(&sx, ureg, &opcode.dst[0], + opcode.dcl_siv_name); + break; + + case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV: + assert(parser.header.type == D3D10_SB_PIXEL_SHADER); + dcl_ps_siv_input(&sx, ureg, &opcode.dst[0], + opcode.dcl_siv_name, + opcode.specific.dcl_in_ps_interp); + break; + + case D3D10_SB_OPCODE_DCL_OUTPUT: + if (parser.header.type == D3D10_SB_PIXEL_SHADER) { + /* Pixel shader outputs. */ + if (opcode.dst[0].base.type == D3D10_SB_OPERAND_TYPE_OUTPUT_DEPTH) { + /* Depth output. */ + assert(opcode.dst[0].base.index_dim == 0); + + sx.output_depth = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_POSITION, 0, TGSI_WRITEMASK_Z, 0, 1); + sx.output_depth = ureg_writemask(sx.output_depth, TGSI_WRITEMASK_Z); + } else { + /* Color outputs. */ + assert(opcode.dst[0].base.index_dim == 1); + assert(opcode.dst[0].base.index[0].imm < SHADER_MAX_OUTPUTS); + + dcl_base_output(&sx, ureg, + ureg_DECL_output(ureg, + TGSI_SEMANTIC_COLOR, + opcode.dst[0].base.index[0].imm), + &opcode.dst[0]); + } + } else { + assert(opcode.dst[0].base.index_dim == 1); + assert(opcode.dst[0].base.index[0].imm < SHADER_MAX_OUTPUTS); + + if (output_mapping) { + unsigned nr_outputs = ureg_get_nr_outputs(ureg); + output_mapping[nr_outputs] + = opcode.dst[0].base.index[0].imm; + } + dcl_base_output(&sx, ureg, + ureg_DECL_output(ureg, + TGSI_SEMANTIC_GENERIC, + opcode.dst[0].base.index[0].imm), + &opcode.dst[0]); + } + break; + + case D3D10_SB_OPCODE_DCL_OUTPUT_SIV: + assert(opcode.dst[0].base.index_dim == 1); + assert(opcode.dst[0].base.index[0].imm < SHADER_MAX_OUTPUTS); + + if (output_mapping) { + unsigned nr_outputs = ureg_get_nr_outputs(ureg); + output_mapping[nr_outputs] + = opcode.dst[0].base.index[0].imm; + } + if (opcode.dcl_siv_name == D3D10_SB_NAME_CLIP_DISTANCE || + opcode.dcl_siv_name == D3D10_SB_NAME_CULL_DISTANCE) { + /* + * FIXME: this is quite broken. gallium no longer has separate + * clip/cull dists, using (max 2) combined clipdist/culldist regs + * instead. Unlike d3d10 though, which is clip and which cull is + * simply determined by by number of clip/cull dists (that is, + * all clip dists must come first). + */ + unsigned numcliporcull = sx.num_clip_distances_declared + + sx.num_cull_distances_declared; + sx.clip_distance_mapping[numcliporcull].d3d = + opcode.dst[0].base.index[0].imm; + sx.clip_distance_mapping[numcliporcull].tgsi = numcliporcull; + if (opcode.dcl_siv_name == D3D10_SB_NAME_CLIP_DISTANCE) { + ++sx.num_clip_distances_declared; + /* re-emit should be safe... */ + ureg_property(ureg, TGSI_PROPERTY_NUM_CLIPDIST_ENABLED, + sx.num_clip_distances_declared); + } else { + ++sx.num_cull_distances_declared; + ureg_property(ureg, TGSI_PROPERTY_NUM_CULLDIST_ENABLED, + sx.num_cull_distances_declared); + } + } else if (0 && opcode.dcl_siv_name == D3D10_SB_NAME_CULL_DISTANCE) { + sx.cull_distance_mapping[sx.num_cull_distances_declared].d3d = + opcode.dst[0].base.index[0].imm; + sx.cull_distance_mapping[sx.num_cull_distances_declared].tgsi = + sx.num_cull_distances_declared; + ++sx.num_cull_distances_declared; + ureg_property(ureg, TGSI_PROPERTY_NUM_CULLDIST_ENABLED, + sx.num_cull_distances_declared); + } + + dcl_base_output(&sx, ureg, + ureg_DECL_output_masked( + ureg, + translate_system_name(opcode.dcl_siv_name), + translate_semantic_index(&sx, opcode.dcl_siv_name, + &opcode.dst[0]), + opcode.dst[0].mask >> D3D10_SB_OPERAND_4_COMPONENT_MASK_SHIFT, + 0, 1), + &opcode.dst[0]); + break; + + case D3D10_SB_OPCODE_DCL_OUTPUT_SGV: + assert(opcode.dst[0].base.index_dim == 1); + assert(opcode.dst[0].base.index[0].imm < SHADER_MAX_OUTPUTS); + + if (output_mapping) { + unsigned nr_outputs = ureg_get_nr_outputs(ureg); + output_mapping[nr_outputs] + = opcode.dst[0].base.index[0].imm; + } + dcl_base_output(&sx, ureg, + ureg_DECL_output(ureg, + translate_system_name(opcode.dcl_siv_name), + 0), + &opcode.dst[0]); + break; + + case D3D10_SB_OPCODE_DCL_TEMPS: + { + uint i; + + assert(opcode.specific.dcl_num_temps + sx.declared_temps <= + SHADER_MAX_TEMPS); + + sx.temp_offset = sx.declared_temps; + + for (i = 0; i < opcode.specific.dcl_num_temps; i++) { + sx.temps[sx.declared_temps + i] = ureg_DECL_temporary(ureg); + } + sx.declared_temps += opcode.specific.dcl_num_temps; + } + break; + + case D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP: + { + uint i; + + /* XXX: Add true indexable temps to gallium. + */ + + assert(opcode.specific.dcl_indexable_temp.index < + SHADER_MAX_INDEXABLE_TEMPS); + assert(opcode.specific.dcl_indexable_temp.count + sx.declared_temps <= + SHADER_MAX_TEMPS); + + sx.indexable_temp_offsets[opcode.specific.dcl_indexable_temp.index] = + sx.declared_temps; + + for (i = 0; i < opcode.specific.dcl_indexable_temp.count; i++) { + sx.temps[sx.declared_temps + i] = ureg_DECL_temporary(ureg); + } + sx.declared_temps += opcode.specific.dcl_indexable_temp.count; + } + break; + case D3D10_SB_OPCODE_IF: { + unsigned label = 0; + if (opcode.specific.test_boolean == D3D10_SB_INSTRUCTION_TEST_ZERO) { + struct ureg_src src = + translate_src_operand(&sx, &opcode.src[0], OF_INT); + struct ureg_dst src_nz = ureg_DECL_temporary(ureg); + ureg_USEQ(ureg, src_nz, src, ureg_imm1u(ureg, 0)); + ureg_UIF(ureg, ureg_src(src_nz), &label); + ureg_release_temporary(ureg, src_nz);; + } else { + ureg_UIF(ureg, translate_src_operand(&sx, &opcode.src[0], OF_INT), &label); + } + } + break; + case D3D10_SB_OPCODE_RETC: + case D3D10_SB_OPCODE_CONTINUEC: + case D3D10_SB_OPCODE_CALLC: + case D3D10_SB_OPCODE_DISCARD: + case D3D10_SB_OPCODE_BREAKC: + { + unsigned label = 0; + assert(operand_is_scalar(&opcode.src[0])); + if (opcode.specific.test_boolean == D3D10_SB_INSTRUCTION_TEST_ZERO) { + struct ureg_src src = + translate_src_operand(&sx, &opcode.src[0], OF_INT); + struct ureg_dst src_nz = ureg_DECL_temporary(ureg); + ureg_USEQ(ureg, src_nz, src, ureg_imm1u(ureg, 0)); + ureg_UIF(ureg, ureg_src(src_nz), &label); + ureg_release_temporary(ureg, src_nz); + } + else { + ureg_UIF(ureg, translate_src_operand(&sx, &opcode.src[0], OF_INT), &label); + } + switch (opcode.type) { + case D3D10_SB_OPCODE_RETC: + ureg_RET(ureg); + break; + case D3D10_SB_OPCODE_CONTINUEC: + ureg_CONT(ureg); + break; + case D3D10_SB_OPCODE_CALLC: { + unsigned label = opcode.src[1].base.index[0].imm; + unsigned tgsi_token_label = 0; + ureg_CAL(ureg, &tgsi_token_label); + Shader_add_call(&sx, label, tgsi_token_label); + } + break; + case D3D10_SB_OPCODE_DISCARD: + ureg_KILL(ureg); + break; + case D3D10_SB_OPCODE_BREAKC: + ureg_BRK(ureg); + break; + default: + assert(0); + break; + } + ureg_ENDIF(ureg); + } + break; + case D3D10_SB_OPCODE_LABEL: { + unsigned label = opcode.src[0].base.index[0].imm; + unsigned tgsi_inst_no = 0; + if (inside_sub) { + ureg_ENDSUB(ureg); + } + tgsi_inst_no = ureg_get_instruction_number(ureg); + ureg_BGNSUB(ureg); + inside_sub = TRUE; + Shader_add_label(&sx, label, tgsi_inst_no); + } + break; + case D3D10_SB_OPCODE_CALL: { + unsigned label = opcode.src[0].base.index[0].imm; + unsigned tgsi_token_label = 0; + ureg_CAL(ureg, &tgsi_token_label); + Shader_add_call(&sx, label, tgsi_token_label); + } + break; + case D3D10_SB_OPCODE_EMIT: + ureg_EMIT(ureg, ureg_imm1u(ureg, 0)); + break; + case D3D10_SB_OPCODE_CUT: + ureg_ENDPRIM(ureg, ureg_imm1u(ureg, 0)); + break; + case D3D10_SB_OPCODE_EMITTHENCUT: + ureg_EMIT(ureg, ureg_imm1u(ureg, 0)); + ureg_ENDPRIM(ureg, ureg_imm1u(ureg, 0)); + break; + case D3D10_SB_OPCODE_DCL_INDEX_RANGE: + case D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS: + /* Ignore */ + break; + default: + { + uint i; + struct ureg_dst dst[SHADER_MAX_DST_OPERANDS]; + struct ureg_src src[SHADER_MAX_SRC_OPERANDS]; + + assert(ox->tgsi_opcode != TGSI_EXPAND); + + if (ox->tgsi_opcode == TGSI_LOG_UNSUPPORTED) { + if (!shader_dumped) { + dx10_shader_dump_tokens(code); + shader_dumped = TRUE; + } + debug_printf("%s: unsupported opcode %i\n", + __FUNCTION__, ox->type); + assert(ox->tgsi_opcode != TGSI_LOG_UNSUPPORTED); + } + + /* Destination operands. */ + for (i = 0; i < opcode.num_dst; i++) { + dst[i] = translate_dst_operand(&sx, &opcode.dst[i], + opcode.saturate); + } + + /* Source operands. */ + for (i = 0; i < opcode.num_src; i++) { + src[i] = translate_src_operand(&sx, &opcode.src[i], ox->format); + } + + /* Try to re-route output depth to Z channel. */ + if (opcode.dst[0].base.type == D3D10_SB_OPERAND_TYPE_OUTPUT_DEPTH) { + LOG_UNSUPPORTED(opcode.type != D3D10_SB_OPCODE_MOV); + dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_Z); + src[0] = ureg_scalar(src[0], TGSI_SWIZZLE_X); + } + + ureg_insn(ureg, + ox->tgsi_opcode, + dst, + opcode.num_dst, + src, + opcode.num_src, 0); + } + } + + Shader_opcode_free(&opcode); + } + + if (inside_sub) { + ureg_ENDSUB(ureg); + } + + ureg_END(ureg); + + for (i = 0; i < sx.num_calls; ++i) { + for (j = 0; j < sx.num_labels; ++j) { + if (sx.calls[i].d3d_label == sx.labels[j].d3d_label) { + ureg_fixup_label(sx.ureg, + sx.calls[i].tgsi_label_token, + sx.labels[j].tgsi_insn_no); + break; + } + } + ASSERT(j < sx.num_labels); + } + FREE(sx.labels); + FREE(sx.calls); + + tokens = ureg_get_tokens(ureg, &nr_tokens); + assert(tokens); + ureg_destroy(ureg); + + if (st_debug & ST_DEBUG_TGSI) { + tgsi_dump(tokens, 0); + } + + return tokens; +} diff --git a/src/gallium/frontends/d3d10umd/State.h b/src/gallium/frontends/d3d10umd/State.h new file mode 100644 index 00000000000..5cb865ce695 --- /dev/null +++ b/src/gallium/frontends/d3d10umd/State.h @@ -0,0 +1,411 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/* + * State.h -- + * State declarations. + */ + + +#include "DriverIncludes.h" +#include "util/u_hash_table.h" + + +#define SUPPORT_MSAA 0 +#define SUPPORT_D3D10_1 0 +#define SUPPORT_D3D11 0 + + +struct Adapter +{ + struct pipe_screen *screen; +}; + + +static inline Adapter * +CastAdapter(D3D10DDI_HADAPTER hAdapter) +{ + return static_cast(hAdapter.pDrvPrivate); +} + +struct Shader +{ + void *handle; + uint type; + struct pipe_shader_state state; + unsigned output_mapping[PIPE_MAX_SHADER_OUTPUTS]; + boolean output_resolved; +}; + +struct Query; + +struct Device +{ + struct pipe_context *pipe; + + struct pipe_framebuffer_state fb; + struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; + struct pipe_resource *index_buffer; + unsigned restart_index; + unsigned index_size; + unsigned ib_offset; + void *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS]; + + void *empty_fs; + void *empty_vs; + + enum pipe_prim_type primitive; + + struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS]; + struct pipe_stream_output_target *draw_so_target; + Shader *bound_empty_gs; + Shader *bound_vs; + + unsigned max_dual_source_render_targets; + + D3D10DDI_HRTCORELAYER hRTCoreLayer; + + HANDLE hDevice; + HANDLE hContext; + + D3DDDI_DEVICECALLBACKS KTCallbacks; + D3D10DDI_CORELAYER_DEVICECALLBACKS UMCallbacks; + DXGI_DDI_BASE_CALLBACKS *pDXGIBaseCallbacks; + + INT LastEmittedQuerySeqNo; + INT LastFinishedQuerySeqNo; + + Query *pPredicate; + BOOL PredicateValue; +}; + + +static inline Device * +CastDevice(D3D10DDI_HDEVICE hDevice) +{ + return static_cast(hDevice.pDrvPrivate); +} + + +static inline struct pipe_context * +CastPipeContext(D3D10DDI_HDEVICE hDevice) +{ + Device *pDevice = CastDevice(hDevice); + return pDevice ? pDevice->pipe : NULL; +} + + +static inline Device * +CastDevice(DXGI_DDI_HDEVICE hDevice) +{ + return reinterpret_cast(hDevice); +} + + +static inline struct pipe_context * +CastPipeDevice(DXGI_DDI_HDEVICE hDevice) +{ + Device *pDevice = CastDevice(hDevice); + return pDevice ? pDevice->pipe : NULL; +} + + +static inline void +SetError(D3D10DDI_HDEVICE hDevice, HRESULT hr) +{ + if (FAILED(hr)) { + Device *pDevice = CastDevice(hDevice); + pDevice->UMCallbacks.pfnSetErrorCb(pDevice->hRTCoreLayer, hr); + } +} + + +struct Resource +{ + DXGI_FORMAT Format; + UINT MipLevels; + UINT NumSubResources; + struct pipe_resource *resource; + struct pipe_transfer **transfers; + struct pipe_stream_output_target *so_target; +}; + + +static inline Resource * +CastResource(D3D10DDI_HRESOURCE hResource) +{ + return static_cast(hResource.pDrvPrivate); +} + + +static inline Resource * +CastResource(DXGI_DDI_HRESOURCE hResource) +{ + return reinterpret_cast(hResource); +} + + +static inline struct pipe_resource * +CastPipeResource(D3D10DDI_HRESOURCE hResource) +{ + Resource *pResource = CastResource(hResource); + return pResource ? pResource->resource : NULL; +} + + +static inline struct pipe_resource * +CastPipeResource(DXGI_DDI_HRESOURCE hResource) +{ + Resource *pResource = CastResource(hResource); + return pResource ? pResource->resource : NULL; +} + + +static inline struct pipe_resource * +CastPipeBuffer(D3D10DDI_HRESOURCE hResource) +{ + Resource *pResource = CastResource(hResource); + if (!pResource) { + return NULL; + } + return static_cast(pResource->resource); +} + + +struct RenderTargetView +{ + struct pipe_surface *surface; + D3D10DDI_HRTRENDERTARGETVIEW hRTRenderTargetView; +}; + + +static inline RenderTargetView * +CastRenderTargetView(D3D10DDI_HRENDERTARGETVIEW hRenderTargetView) +{ + return static_cast(hRenderTargetView.pDrvPrivate); +} + + +static inline struct pipe_surface * +CastPipeRenderTargetView(D3D10DDI_HRENDERTARGETVIEW hRenderTargetView) +{ + RenderTargetView *pRenderTargetView = CastRenderTargetView(hRenderTargetView); + return pRenderTargetView ? pRenderTargetView->surface : NULL; +} + + +struct DepthStencilView +{ + struct pipe_surface *surface; + D3D10DDI_HRTDEPTHSTENCILVIEW hRTDepthStencilView; +}; + + +static inline DepthStencilView * +CastDepthStencilView(D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView) +{ + return static_cast(hDepthStencilView.pDrvPrivate); +} + + +static inline struct pipe_surface * +CastPipeDepthStencilView(D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView) +{ + DepthStencilView *pDepthStencilView = CastDepthStencilView(hDepthStencilView); + return pDepthStencilView ? pDepthStencilView->surface : NULL; +} + + +struct BlendState +{ + void *handle; +}; + + +static inline BlendState * +CastBlendState(D3D10DDI_HBLENDSTATE hBlendState) +{ + return static_cast(hBlendState.pDrvPrivate); +} + + +static inline void * +CastPipeBlendState(D3D10DDI_HBLENDSTATE hBlendState) +{ + BlendState *pBlendState = CastBlendState(hBlendState); + return pBlendState ? pBlendState->handle : NULL; +} + + +struct DepthStencilState +{ + void *handle; +}; + + +static inline DepthStencilState * +CastDepthStencilState(D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState) +{ + return static_cast(hDepthStencilState.pDrvPrivate); +} + + +static inline void * +CastPipeDepthStencilState(D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState) +{ + DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState); + return pDepthStencilState ? pDepthStencilState->handle : NULL; +} + + +struct RasterizerState +{ + void *handle; +}; + + +static inline RasterizerState * +CastRasterizerState(D3D10DDI_HRASTERIZERSTATE hRasterizerState) +{ + return static_cast(hRasterizerState.pDrvPrivate); +} + + +static inline void * +CastPipeRasterizerState(D3D10DDI_HRASTERIZERSTATE hRasterizerState) +{ + RasterizerState *pRasterizerState = CastRasterizerState(hRasterizerState); + return pRasterizerState ? pRasterizerState->handle : NULL; +} + + +static inline Shader * +CastShader(D3D10DDI_HSHADER hShader) +{ + return static_cast(hShader.pDrvPrivate); +} + + +static inline void * +CastPipeShader(D3D10DDI_HSHADER hShader) +{ + Shader *pShader = static_cast(hShader.pDrvPrivate); + return pShader ? pShader->handle : NULL; +} + + +struct ElementLayout +{ + void *handle; +}; + + +static inline ElementLayout * +CastElementLayout(D3D10DDI_HELEMENTLAYOUT hElementLayout) +{ + return static_cast(hElementLayout.pDrvPrivate); +} + +static inline void * +CastPipeInputLayout(D3D10DDI_HELEMENTLAYOUT hElementLayout) +{ + ElementLayout *pElementLayout = CastElementLayout(hElementLayout); + return pElementLayout ? pElementLayout->handle : NULL; +} + + +struct SamplerState +{ + void *handle; +}; + + +static inline SamplerState * +CastSamplerState(D3D10DDI_HSAMPLER hSampler) +{ + return static_cast(hSampler.pDrvPrivate); +} + + +static inline void * +CastPipeSamplerState(D3D10DDI_HSAMPLER hSampler) +{ + SamplerState *pSamplerState = CastSamplerState(hSampler); + return pSamplerState ? pSamplerState->handle : NULL; +} + + +struct ShaderResourceView +{ + struct pipe_sampler_view *handle; +}; + + +static inline ShaderResourceView * +CastShaderResourceView(D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView) +{ + return static_cast(hShaderResourceView.pDrvPrivate); +} + + +static inline struct pipe_sampler_view * +CastPipeShaderResourceView(D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView) +{ + ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView); + return pSRView ? pSRView->handle : NULL; +} + + +struct Query +{ + D3D10DDI_QUERY Type; + UINT Flags; + + unsigned pipe_type; + struct pipe_query *handle; + INT SeqNo; + UINT GetDataCount; + + D3D10_DDI_QUERY_DATA_PIPELINE_STATISTICS Statistics; +}; + + +static inline Query * +CastQuery(D3D10DDI_HQUERY hQuery) +{ + return static_cast(hQuery.pDrvPrivate); +} + + +static inline struct pipe_query * +CastPipeQuery(D3D10DDI_HQUERY hQuery) +{ + Query *pQuery = CastQuery(hQuery); + return pQuery ? pQuery->handle : NULL; +} + diff --git a/src/gallium/frontends/d3d10umd/d3d10_sw.def b/src/gallium/frontends/d3d10umd/d3d10_sw.def new file mode 100644 index 00000000000..5b76bfccefa --- /dev/null +++ b/src/gallium/frontends/d3d10umd/d3d10_sw.def @@ -0,0 +1,53 @@ +EXPORTS + OpenAdapter10 + OpenAdapter10_2 + D3DKMTAcquireKeyedMutex + D3DKMTCloseAdapter + D3DKMTConfigureSharedResource + D3DKMTCreateAllocation + D3DKMTCreateAllocation2 + D3DKMTCreateContext + D3DKMTCreateDevice + D3DKMTCreateKeyedMutex + D3DKMTCreateSynchronizationObject + D3DKMTCreateSynchronizationObject2 + D3DKMTDestroyAllocation + D3DKMTDestroyContext + D3DKMTDestroyDevice + D3DKMTDestroyKeyedMutex + D3DKMTDestroySynchronizationObject + D3DKMTEscape + D3DKMTGetContextSchedulingPriority + ;D3DKMTGetDeviceSchedulingPriority + D3DKMTGetDeviceState + D3DKMTGetDisplayModeList + D3DKMTGetMultisampleMethodList + D3DKMTGetRuntimeData + D3DKMTGetSharedPrimaryHandle + D3DKMTLock + D3DKMTOpenAdapterFromDeviceName + D3DKMTOpenAdapterFromGdiDisplayName + D3DKMTOpenKeyedMutex + D3DKMTOpenResource + D3DKMTOpenResource2 + D3DKMTOpenSynchronizationObject + D3DKMTPresent + D3DKMTQueryAdapterInfo + D3DKMTQueryAllocationResidency + D3DKMTQueryResourceInfo + D3DKMTReleaseKeyedMutex + D3DKMTRender + D3DKMTSetAllocationPriority + D3DKMTSetContextSchedulingPriority + ;D3DKMTSetDeviceSchedulingPriority + D3DKMTSetDisplayMode + D3DKMTSetDisplayPrivateDriverFormat + D3DKMTSetGammaRamp + D3DKMTSetVidPnSourceOwner + D3DKMTSetVidPnSourceOwner1 + D3DKMTSignalSynchronizationObject + D3DKMTSignalSynchronizationObject2 + D3DKMTUnlock + D3DKMTWaitForSynchronizationObject + D3DKMTWaitForSynchronizationObject2 + D3DKMTWaitForVerticalBlankEvent diff --git a/src/gallium/frontends/d3d10umd/meson.build b/src/gallium/frontends/d3d10umd/meson.build new file mode 100644 index 00000000000..90774d9217d --- /dev/null +++ b/src/gallium/frontends/d3d10umd/meson.build @@ -0,0 +1,35 @@ +inc_d3d10umd = include_directories('.') +_c_args_d3d10umd = [] + +if cc.get_id() == 'gcc' + _c_args_d3d10umd += '-Wno-unknown-pragmas' +endif + +inc_winddk = include_directories('../../../../include/winddk') + +libd3d10umd = static_library( + 'd3d10umd', + files( + 'Adapter.cpp', + 'Debug.cpp', + 'Device.cpp', + 'Draw.cpp', + 'Dxgi.cpp', + 'Format.cpp', + 'InputAssembly.cpp', + 'OutputMerger.cpp', + 'Query.cpp', + 'Rasterizer.cpp', + 'Resource.cpp', + 'Shader.cpp', + 'ShaderDump.cpp', + 'ShaderParse.c', + 'ShaderTGSI.c', + 'D3DKMT.cpp', + ), + c_args : _c_args_d3d10umd, + cpp_args : _c_args_d3d10umd, + include_directories : [ + inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_winddk, + ], +) diff --git a/src/gallium/meson.build b/src/gallium/meson.build index 0b2e4c5e01e..3b3bb07f1de 100644 --- a/src/gallium/meson.build +++ b/src/gallium/meson.build @@ -222,6 +222,10 @@ if with_gallium_st_nine subdir('frontends/nine') subdir('targets/d3dadapter9') endif +if with_gallium_st_d3d10umd + subdir('frontends/d3d10umd') + subdir('targets/d3d10sw') +endif if with_platform_windows subdir('frontends/wgl') if with_gallium_d3d12 diff --git a/src/gallium/targets/d3d10sw/README.md b/src/gallium/targets/d3d10sw/README.md new file mode 100644 index 00000000000..7487bb2bc6a --- /dev/null +++ b/src/gallium/targets/d3d10sw/README.md @@ -0,0 +1,50 @@ +The resulting d3d10sw.dll implements D3D10's software rendering interface, like +WARP. + + +It can be used directly from WLK 1.6 and WHCK 2.0 D3D10+ tests, via the -Src +and -SWDLL options. For example: + + wgf11blend.exe -Debug -DoNotCatchExceptions -DXGI:1.1 -FeatureLevel:10.0 -Src:SW -SWDLL:d3d10sw.dll -LogClean -LogVerbose + +However, as of WHCK version 2.1 this mechanism no longer works reliably. +Either you use WHCK 2.0 binaries, or you must use the alternative method +cribed below (of copying d3d10sw.dll into the executable directory and rename +it such that it matches the D3D10 UMD of the test machine). + + +Examples can be easily modified to load it too: + + D3D10CreateDeviceAndSwapChain(NULL, + D3D10_DRIVER_TYPE_SOFTWARE, + LoadLibraryA("d3d10sw"), /* Software */ + Flags, + D3D10_SDK_VERSION, + &SwapChainDesc, + &g_pSwapChain, + &g_pDevice); + + D3D11CreateDeviceAndSwapChain(NULL, /* pAdapter */ + D3D_DRIVER_TYPE_SOFTWARE, + LoadLibraryA("d3d10sw"), /* Software */ + Flags, + FeatureLevels, + sizeof FeatureLevels / sizeof FeatureLevels[0], + D3D11_SDK_VERSION, + &SwapChainDesc, + &g_pSwapChain, + &g_pDevice, + NULL, /* pFeatureLevel */ + &g_pDeviceContext); /* ppImmediateContext */ + + +Alternatively, it can be renamed into the system's D3D10 UMD driver (e.g., +vm3dum_10.dll for VMware vGPU, nvwgf2um.dll for NVIDIA GPU), and placed into +the application directory, or system's directory, and used instead. + +For the DLL to be picked from the application directory you'll need to do the +following once: + + reg add "HKLM\System\CurrentControlSet\Control\Session Manager" /v "SafeDllSearchMode" /t REG_DWORD /d 0 /f + +See also https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order diff --git a/src/gallium/targets/d3d10sw/d3d10_gdi.c b/src/gallium/targets/d3d10sw/d3d10_gdi.c new file mode 100644 index 00000000000..f5a22e50c39 --- /dev/null +++ b/src/gallium/targets/d3d10sw/d3d10_gdi.c @@ -0,0 +1,82 @@ +/************************************************************************** + * + * Copyright 2012-2021 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + + +#include "util/u_debug.h" +#include "target-helpers/inline_debug_helper.h" +#include "llvmpipe/lp_public.h" +#include "softpipe/sp_public.h" +#include "sw/gdi/gdi_sw_winsys.h" + + +extern struct pipe_screen * +d3d10_create_screen(void); + + +struct pipe_screen * +d3d10_create_screen(void) +{ + const char *default_driver; + const char *driver; + struct pipe_screen *screen = NULL; + struct sw_winsys *winsys; + + winsys = gdi_create_sw_winsys(); + if(!winsys) + goto no_winsys; + +#ifdef GALLIUM_LLVMPIPE + default_driver = "llvmpipe"; +#else + default_driver = "softpipe"; +#endif + + driver = debug_get_option("GALLIUM_DRIVER", default_driver); + +#ifdef GALLIUM_LLVMPIPE + if (strcmp(driver, "llvmpipe") == 0) { + screen = llvmpipe_create_screen( winsys ); + } +#else + (void)driver; +#endif + + if (screen == NULL) { + screen = softpipe_create_screen( winsys ); + } + + if (screen == NULL) + goto no_screen; + + return debug_screen_wrap( screen ); + +no_screen: + winsys->destroy(winsys); +no_winsys: + return NULL; +} diff --git a/src/gallium/targets/d3d10sw/meson.build b/src/gallium/targets/d3d10sw/meson.build new file mode 100644 index 00000000000..4e9a8dceaa6 --- /dev/null +++ b/src/gallium/targets/d3d10sw/meson.build @@ -0,0 +1,45 @@ +# Copyright © 2021 VMware, Inc +# Copyright © 2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +d3d10sw_def = files('../../frontends/d3d10umd/d3d10_sw.def')[0] +_link_args_d3d10sw = [] +if cc.get_id() == 'gcc' + _link_args_d3d10sw += '-Wl,--enable-stdcall-fixup' +endif + +libd3d10sw = shared_library( + 'd3d10sw', + ['d3d10_gdi.c'], + vs_module_defs : d3d10sw_def, + include_directories : [ + inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_d3d10umd, inc_gallium_winsys, inc_gallium_winsys_sw, inc_gallium_drivers, + ], + link_args : _link_args_d3d10sw, + link_whole : [libd3d10umd], + link_with : [ + libgallium, libwsgdi + ], + dependencies : [ + dep_ws2_32, idep_nir, driver_swrast + ], + name_prefix : '', # otherwise mingw will create libd3d10sw.dll + install : true, +)