Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2610 lines
100 KiB

  1. /*============================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: vshader.cpp
  6. * Content: SetStreamSource and VertexShader
  7. * software implementation.
  8. *
  9. ****************************************************************************/
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. #include "ibuffer.hpp"
  13. #include "fe.h"
  14. #include "ddibase.h"
  15. #include "pvvid.h"
  16. void __Transpose(D3DMATRIXI* m, D3DMATRIX* res)
  17. {
  18. res->_11 = m->_11;
  19. res->_12 = m->_21;
  20. res->_13 = m->_31;
  21. res->_14 = m->_41;
  22. res->_21 = m->_12;
  23. res->_22 = m->_22;
  24. res->_23 = m->_32;
  25. res->_24 = m->_42;
  26. res->_31 = m->_13;
  27. res->_32 = m->_23;
  28. res->_33 = m->_33;
  29. res->_34 = m->_43;
  30. res->_41 = m->_14;
  31. res->_42 = m->_24;
  32. res->_43 = m->_34;
  33. res->_44 = m->_44;
  34. }
  35. //-----------------------------------------------------------------------------
  36. // Forward definitions
  37. //
  38. void CD3DHal_DrawPrimitive(CD3DBase* pBaseDevice, D3DPRIMITIVETYPE PrimitiveType,
  39. UINT StartVertex, UINT PrimitiveCount);
  40. void CD3DHal_DrawIndexedPrimitive(CD3DBase* pBaseDevice,
  41. D3DPRIMITIVETYPE PrimitiveType,
  42. UINT BaseIndex,
  43. UINT MinIndex, UINT NumVertices,
  44. UINT StartIndex,
  45. UINT PrimitiveCount);
  46. void CD3DHal_DrawNPatch(CD3DBase* pBaseDevice, D3DPRIMITIVETYPE PrimitiveType,
  47. UINT StartVertex, UINT PrimitiveCount);
  48. void CD3DHal_DrawIndexedNPatch(CD3DBase* pBaseDevice,
  49. D3DPRIMITIVETYPE PrimitiveType,
  50. UINT BaseIndex,
  51. UINT MinIndex, UINT NumVertices,
  52. UINT StartIndex,
  53. UINT PrimitiveCount);
  54. //-----------------------------------------------------------------------------
  55. void __declspec(nothrow) CD3DHal::PickDrawPrimFn()
  56. {
  57. if (!(m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING))
  58. {
  59. m_pfnDrawPrim = m_pDDI->GetDrawPrimFunction();
  60. m_pfnDrawIndexedPrim = m_pDDI->GetDrawIndexedPrimFunction();
  61. if (m_dwRuntimeFlags & D3DRT_DONPATCHCONVERSION)
  62. {
  63. m_pfnDrawPrimFromNPatch = m_pfnDrawPrim;
  64. m_pfnDrawIndexedPrimFromNPatch = m_pfnDrawIndexedPrim;
  65. m_pfnDrawPrim = CD3DHal_DrawNPatch;
  66. m_pfnDrawIndexedPrim = CD3DHal_DrawIndexedNPatch;
  67. }
  68. }
  69. else
  70. {
  71. DWORD dwDeviceFlags = m_pv->dwDeviceFlags;
  72. BOOL bCallDriver;
  73. if (Enum()->GetAppSdkVersion() == D3D_SDK_VERSION_DX8)
  74. {
  75. bCallDriver = dwDeviceFlags & D3DDEV_TRANSFORMEDFVF &&
  76. (dwDeviceFlags & D3DDEV_DONOTCLIP ||
  77. !(dwDeviceFlags & D3DDEV_VBPROCVER));
  78. }
  79. else
  80. {
  81. bCallDriver = dwDeviceFlags & D3DDEV_TRANSFORMEDFVF &&
  82. dwDeviceFlags & D3DDEV_DONOTCLIP;
  83. }
  84. if (bCallDriver)
  85. {
  86. m_pfnDrawPrim = m_pDDI->GetDrawPrimFunction();
  87. m_pfnDrawIndexedPrim = m_pDDI->GetDrawIndexedPrimFunction();
  88. }
  89. else
  90. {
  91. m_pfnDrawPrim = CD3DHal_DrawPrimitive;
  92. m_pfnDrawIndexedPrim = CD3DHal_DrawIndexedPrimitive;
  93. }
  94. }
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Checks if we can call driver directly to draw the current primitive
  98. //
  99. inline BOOL CanCallDriver(CD3DHal* pDev, D3DPRIMITIVETYPE PrimType)
  100. {
  101. DWORD dwDeviceFlags = pDev->m_pv->dwDeviceFlags;
  102. if (PrimType != D3DPT_POINTLIST)
  103. return dwDeviceFlags & D3DDEV_TRANSFORMEDFVF &&
  104. (dwDeviceFlags & D3DDEV_DONOTCLIP ||
  105. pDev->Enum()->GetAppSdkVersion() == D3D_SDK_VERSION_DX8);
  106. else
  107. // This function could be called from DrawPointsI, which could be
  108. // called from other Draw() function than DrawPrimitiveUP, so we need
  109. // to check for D3DDEV_VBPROCVER. We cannot pass vertices, which are
  110. // result of ProcessVertices(), to the driver directly
  111. return dwDeviceFlags & D3DDEV_TRANSFORMEDFVF &&
  112. !(pDev->m_dwRuntimeFlags & D3DRT_DOPOINTSPRITEEMULATION) &&
  113. (dwDeviceFlags & D3DDEV_DONOTCLIP ||
  114. (pDev->Enum()->GetAppSdkVersion() == D3D_SDK_VERSION_DX8 &&
  115. !(dwDeviceFlags & D3DDEV_VBPROCVER)));
  116. }
  117. //-----------------------------------------------------------------------------
  118. // API calls
  119. //-----------------------------------------------------------------------------
  120. #undef DPF_MODNAME
  121. #define DPF_MODNAME "CD3DHal::SetStreamSourceI"
  122. void
  123. CD3DHal::SetStreamSourceI(CVStream* pStream)
  124. {
  125. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)
  126. {
  127. CVertexBuffer * pVB = pStream->m_pVB;
  128. m_pv->dwDeviceFlags &= ~D3DDEV_VBPROCVER;
  129. DWORD dwFVF = pVB->GetFVF();
  130. if (pVB->GetClipCodes() != NULL)
  131. {
  132. // This vertex buffer is the output of ProcessVertices
  133. DXGASSERT(FVF_TRANSFORMED(dwFVF));
  134. m_pv->dwDeviceFlags |= D3DDEV_VBPROCVER;
  135. }
  136. if (D3DVSD_ISLEGACY(m_dwCurrentShaderHandle))
  137. {
  138. SetupStrides(m_pv, m_pStream[0].m_dwStride);
  139. }
  140. }
  141. PickDrawPrimFn();
  142. }
  143. //-----------------------------------------------------------------------------
  144. #undef DPF_MODNAME
  145. #define DPF_MODNAME "CD3DHal::SetIndicesI"
  146. void
  147. CD3DHal::SetIndicesI(CVIndexStream* pStream)
  148. {
  149. }
  150. //-----------------------------------------------------------------------------
  151. #undef DPF_MODNAME
  152. #define DPF_MODNAME "CD3DHal::CreateVertexShaderI"
  153. void
  154. CD3DHal::CreateVertexShaderI(CONST DWORD* pdwDeclaration, DWORD dwDeclSize,
  155. CONST DWORD* pdwFunction, DWORD dwCodeSize,
  156. DWORD dwHandle)
  157. {
  158. BOOL bIsCheckedBuild =
  159. #if DBG
  160. TRUE;
  161. #else
  162. FALSE;
  163. #endif
  164. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  165. if (pShader->m_dwFlags & CVShader::SOFTWARE)
  166. {
  167. // Build the array of all vertex elements used in the shader by going
  168. // through all streams and elements inside each stream.
  169. CVDeclaration* pDecl = &pShader->m_Declaration;
  170. CVStreamDecl* pStream = pShader->m_Declaration.m_pActiveStreams;
  171. // This is the array we build
  172. CVElement* pVerElem = pShader->m_Declaration.m_VertexElements;
  173. pDecl->m_dwNumElements = 0;
  174. while (pStream)
  175. {
  176. for (DWORD i=0; i < pStream->m_dwNumElements; i++)
  177. {
  178. if (pDecl->m_dwNumElements >= __NUMELEMENTS)
  179. {
  180. D3D_THROW_FAIL("Declaration is using too many elements");
  181. }
  182. *pVerElem = pStream->m_Elements[i];
  183. pVerElem->m_dwStreamIndex = pStream->m_dwStreamIndex;
  184. pVerElem++;
  185. pDecl->m_dwNumElements++;
  186. }
  187. pStream = (CVStreamDecl*)pStream->m_pNext;
  188. }
  189. if (pdwFunction != NULL)
  190. {
  191. // compute adjusted function pointer depending on FREE/CHECKED and PSGP
  192. LPDWORD pdwFunctionAdj = pShader->m_pStrippedFuncCode;
  193. if ( bIsCheckedBuild &&
  194. ((LPVOID)m_pv->pGeometryFuncs == (LPVOID)GeometryFuncsGuaranteed) ) // !PSGP
  195. {
  196. pdwFunctionAdj = pShader->m_pOrgFuncCode;
  197. }
  198. // Microsoft shader is always created.
  199. // It is used for validation and to compute the output FVF in case
  200. // when PSGP is present
  201. HRESULT hr;
  202. hr = GeometryFuncsGuaranteed->CreateShader(
  203. pDecl->m_VertexElements,
  204. pDecl->m_dwNumElements,
  205. pdwFunctionAdj, 0,
  206. (CPSGPShader**)&pShader->m_pCode);
  207. if(FAILED(hr))
  208. {
  209. D3D_THROW_FAIL("Failed to create vertex shader code");
  210. }
  211. // When device driver can not handle separate fog value in the FVF,
  212. // we should use specular alpha as the fog factor
  213. if (pShader->m_pCode->m_dwOutFVF & D3DFVF_FOG &&
  214. !(GetD3DCaps()->PrimitiveMiscCaps & D3DPMISCCAPS_FOGINFVF))
  215. {
  216. pShader->m_pCode->m_dwOutFVF &= ~D3DFVF_FOG;
  217. // Assume that texture coordinates follow fog value
  218. // No need to adjust offsets when specular is already present
  219. if (pShader->m_pCode->m_dwOutFVF & D3DFVF_SPECULAR)
  220. {
  221. pShader->m_pCode->m_dwOutVerSize -= 4;
  222. pShader->m_pCode->m_dwTextureOffset -= 4;
  223. }
  224. pShader->m_pCode->m_dwOutFVF |= D3DFVF_SPECULAR;
  225. }
  226. // Clear texture format bits if device can handle only 2 floats per
  227. // texture coordinate
  228. if (m_dwRuntimeFlags & D3DRT_ONLY2FLOATSPERTEXTURE &&
  229. pShader->m_pCode->m_dwOutFVF & 0xFFFF0000)
  230. {
  231. CVShaderCode * pCode = pShader->m_pCode;
  232. pCode->m_dwOutFVF &= 0x0000FFFF;
  233. pCode->m_dwOutVerSize = ComputeVertexSizeFVF(pCode->m_dwOutFVF);
  234. for (DWORD i=0; i < pCode->m_nOutTexCoord; i++)
  235. {
  236. pCode->m_dwOutTexCoordSize[i] = 2 * 4;
  237. }
  238. }
  239. if ((LPVOID)m_pv->pGeometryFuncs != (LPVOID)GeometryFuncsGuaranteed)
  240. {
  241. DWORD dwOutputFVF = pShader->m_pCode->m_dwOutFVF;
  242. CVShaderCode* pCodeMs = pShader->m_pCode;
  243. // Now we can create PSGP shader
  244. hr = m_pv->pGeometryFuncs->CreateShader(pDecl->m_VertexElements,
  245. pDecl->m_dwNumElements,
  246. pdwFunctionAdj, dwOutputFVF,
  247. (CPSGPShader**)&pShader->m_pCode);
  248. if(FAILED(hr))
  249. {
  250. delete pCodeMs;
  251. D3D_THROW_FAIL("Failed to create vertex shader code");
  252. }
  253. // Copy pre-computed data from Microsoft's shader to the PSGP
  254. CPSGPShader * pCode = pShader->m_pCode;
  255. CPSGPShader * pMsShader = pCodeMs;
  256. pCode->m_dwOutRegs = pMsShader->m_dwOutRegs;
  257. pCode->m_dwOutFVF = pMsShader->m_dwOutFVF;
  258. pCode->m_dwPointSizeOffset = pMsShader->m_dwPointSizeOffset;
  259. pCode->m_dwDiffuseOffset = pMsShader->m_dwDiffuseOffset;
  260. pCode->m_dwSpecularOffset = pMsShader->m_dwSpecularOffset;
  261. pCode->m_dwFogOffset = pMsShader->m_dwFogOffset;
  262. pCode->m_dwTextureOffset = pMsShader->m_dwTextureOffset;
  263. pCode->m_nOutTexCoord = pMsShader->m_nOutTexCoord;
  264. pCode->m_dwOutVerSize = pMsShader->m_dwOutVerSize;
  265. for (DWORD i=0; i < pCode->m_nOutTexCoord; i++)
  266. {
  267. pCode->m_dwOutTexCoordSize[i] = pMsShader->m_dwOutTexCoordSize[i];
  268. }
  269. // Microsoft shader is not needed any more
  270. delete pCodeMs;
  271. }
  272. }
  273. }
  274. else
  275. {
  276. if ( bIsCheckedBuild && (GetDeviceType() != D3DDEVTYPE_HAL ) )
  277. {
  278. // pass non-stripped version
  279. m_pDDI->CreateVertexShader(
  280. pdwDeclaration, dwDeclSize,
  281. pShader->m_pOrgFuncCode,
  282. pShader->m_OrgFuncCodeSize, dwHandle,
  283. pShader->m_Declaration.m_bLegacyFVF);
  284. }
  285. else
  286. {
  287. // pass stripped version
  288. m_pDDI->CreateVertexShader(
  289. pdwDeclaration, dwDeclSize,
  290. pShader->m_pStrippedFuncCode,
  291. pShader->m_StrippedFuncCodeSize, dwHandle,
  292. pShader->m_Declaration.m_bLegacyFVF);
  293. }
  294. }
  295. DebugStateChanged( D3DDM_SC_VSMODIFYSHADERS );
  296. }
  297. //-----------------------------------------------------------------------------
  298. #undef DPF_MODNAME
  299. #define DPF_MODNAME "CD3DHal::SetVertexShaderI"
  300. void CD3DHal::SetVertexShaderI(DWORD dwHandle)
  301. {
  302. #if DBG
  303. // We need to validate shader handle here, because the shader could be
  304. // deleted by user after creating a state block with the shader handle.
  305. CheckVertexShaderHandle(dwHandle);
  306. #endif
  307. CVConstantData* pConst = NULL;
  308. if (!D3DVSD_ISLEGACY(dwHandle))
  309. {
  310. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  311. pConst = pShader->m_Declaration.m_pConstants;
  312. }
  313. // Ignore redundant handle when we do not need to update constantes
  314. if(pConst == NULL)
  315. {
  316. if(dwHandle == m_dwCurrentShaderHandle)
  317. return;
  318. }
  319. else
  320. {
  321. // Load constants
  322. while (pConst)
  323. {
  324. HRESULT hr;
  325. hr = m_pv->pGeometryFuncs->LoadShaderConstants(pConst->m_dwAddress,
  326. pConst->m_dwCount,
  327. pConst->m_pData);
  328. if (FAILED(hr))
  329. {
  330. D3D_THROW_FAIL("Failed to load vertex shader constants");
  331. }
  332. pConst = (CVConstantData*)pConst->m_pNext;
  333. m_dwRuntimeFlags |= D3DRT_NEED_VSCONST_UPDATE;
  334. }
  335. }
  336. ForceFVFRecompute();
  337. // When we switch from FVF shaders to programmable we need to re-compute
  338. // clipping planes, because they are transformed by different matrix
  339. if (this->rstates[D3DRENDERSTATE_CLIPPLANEENABLE])
  340. {
  341. this->dwFEFlags |= D3DFE_CLIPPLANES_DIRTY;
  342. }
  343. m_dwCurrentShaderHandle = dwHandle;
  344. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)
  345. {
  346. m_dwRuntimeFlags &= ~D3DRT_POINTSIZEINVERTEX;
  347. m_dwRuntimeFlags |= D3DRT_SHADERDIRTY;
  348. m_pv->dwDeviceFlags &= ~D3DDEV_TRANSFORMEDFVF;
  349. if (D3DVSD_ISLEGACY(dwHandle))
  350. {
  351. if (dwHandle & D3DFVF_PSIZE)
  352. m_dwRuntimeFlags |= D3DRT_POINTSIZEINVERTEX;
  353. m_pCurrentShader = NULL;
  354. m_pv->dwDeviceFlags &= ~(D3DDEV_STRIDE | D3DDEV_VERTEXSHADERS);
  355. if (FVF_TRANSFORMED(dwHandle))
  356. {
  357. if (!(m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE))
  358. {
  359. m_pDDI->SetVertexShader(dwHandle);
  360. }
  361. m_pv->dwDeviceFlags |= D3DDEV_TRANSFORMEDFVF;
  362. }
  363. m_pfnPrepareToDraw = PrepareToDrawLegacy;
  364. m_pv->dwVIDIn = dwHandle;
  365. SetupStrides(m_pv, m_pStream[0].m_dwStride);
  366. }
  367. else
  368. {
  369. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  370. m_pCurrentShader = pShader;
  371. if(!(pShader->m_dwFlags & CVShader::FIXEDFUNCTION))
  372. {
  373. // Programmable vertex shaders are used
  374. m_pv->dwDeviceFlags |= D3DDEV_VERTEXSHADERS;
  375. m_pfnPrepareToDraw = PrepareToDrawVVM;
  376. if (m_pCurrentShader->m_pCode->m_dwOutFVF & D3DFVF_PSIZE)
  377. m_dwRuntimeFlags |= D3DRT_POINTSIZEINVERTEX;
  378. // Pre-compute as much info as possible and keep it
  379. // in the vertex descriptors. This information is constant
  380. // unless shader is changed
  381. CVDeclaration* pDecl = &m_pCurrentShader->m_Declaration;
  382. CVertexDesc* pVD = m_pv->VertexDesc;
  383. CVElement *pElem = pDecl->m_VertexElements;
  384. m_pv->dwNumUsedVertexDescs = pDecl->m_dwNumElements;
  385. for (DWORD i = pDecl->m_dwNumElements; i; i--)
  386. {
  387. pVD->pfnCopy = pElem->m_pfnCopy;
  388. pVD->dwRegister = pElem->m_dwRegister;
  389. pVD->dwVertexOffset = pElem->m_dwOffset;
  390. pVD->pStream = &m_pStream[pElem->m_dwStreamIndex];
  391. pVD++;
  392. pElem++;
  393. }
  394. }
  395. else
  396. {
  397. // Fixed-function pipeline is used with declarations
  398. // We draw primitives using strided code path
  399. m_pv->dwDeviceFlags |= D3DDEV_STRIDE;
  400. m_pv->dwDeviceFlags &= ~D3DDEV_VERTEXSHADERS;
  401. m_pfnPrepareToDraw = PrepareToDraw;
  402. if (pShader->m_dwInputFVF & D3DFVF_PSIZE)
  403. m_dwRuntimeFlags |= D3DRT_POINTSIZEINVERTEX;
  404. // Go through the elements in the current declaration and
  405. // initialize vertex descriptors. They are used to quickly
  406. // initialize strided data pointers.
  407. CVDeclaration* pDecl = &m_pCurrentShader->m_Declaration;
  408. CVertexDesc* pVD = m_pv->VertexDesc;
  409. CVElement *pElem = pDecl->m_VertexElements;
  410. m_pv->dwNumUsedVertexDescs = pDecl->m_dwNumElements;
  411. for (DWORD i = pDecl->m_dwNumElements; i; i--)
  412. {
  413. pVD->pElement = &m_pv->elements[pElem->m_dwRegister];
  414. pVD->pStream = &m_pStream[pElem->m_dwStreamIndex];
  415. pVD->dwVertexOffset = pElem->m_dwOffset;
  416. pVD++;
  417. pElem++;
  418. }
  419. m_pv->dwVIDIn = pDecl->m_dwInputFVF;
  420. if (pDecl->m_dwInputFVF & D3DFVF_PSIZE)
  421. m_dwRuntimeFlags |= D3DRT_POINTSIZEINVERTEX;
  422. }
  423. HRESULT hr = m_pv->pGeometryFuncs->SetActiveShader(pShader->m_pCode);
  424. if (FAILED(hr))
  425. {
  426. D3D_THROW_FAIL("Failed to set active vertex shader");
  427. }
  428. }
  429. m_pDDI->PickProcessPrimitive();
  430. }
  431. else
  432. {
  433. #if DBG
  434. // For the validation we need to set the m_pCurrentShader even for
  435. // hardware mode
  436. m_pv->dwDeviceFlags &= ~D3DDEV_VERTEXSHADERS;
  437. if (D3DVSD_ISLEGACY(dwHandle))
  438. {
  439. m_pCurrentShader = NULL;
  440. }
  441. else
  442. {
  443. m_pCurrentShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  444. if(!(m_pCurrentShader->m_dwFlags & CVShader::FIXEDFUNCTION))
  445. {
  446. // Programmable pipeline is used
  447. m_pv->dwDeviceFlags |= D3DDEV_VERTEXSHADERS;
  448. }
  449. }
  450. #endif
  451. if (!(m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE))
  452. {
  453. m_pDDI->SetVertexShaderHW(dwHandle);
  454. }
  455. }
  456. PickDrawPrimFn();
  457. DebugStateChanged( D3DDM_SC_VSSETSHADER );
  458. }
  459. //-----------------------------------------------------------------------------
  460. #undef DPF_MODNAME
  461. #define DPF_MODNAME "CD3DHal::DeleteVertexShaderI"
  462. void CD3DHal::DeleteVertexShaderI(DWORD dwHandle)
  463. {
  464. #if DBG
  465. for(unsigned Handle = 0; Handle < m_pRTPatchValidationInfo->GetSize(); ++Handle)
  466. {
  467. if ((*m_pRTPatchValidationInfo)[Handle].m_pObj != 0)
  468. {
  469. if (static_cast<CRTPatchValidationInfo*>((*m_pRTPatchValidationInfo)[Handle].m_pObj)->m_ShaderHandle == dwHandle)
  470. {
  471. static_cast<CRTPatchValidationInfo*>((*m_pRTPatchValidationInfo)[Handle].m_pObj)->m_ShaderHandle = 0;
  472. D3D_INFO(0, "Found this vertex shader in a cached patch. Will invalidate the cached patch.");
  473. }
  474. }
  475. }
  476. #endif // DBG
  477. if (dwHandle == m_dwCurrentShaderHandle)
  478. {
  479. m_pCurrentShader = NULL;
  480. m_dwCurrentShaderHandle = 0;
  481. }
  482. if (!D3DVSD_ISLEGACY(dwHandle))
  483. {
  484. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  485. #if DBG
  486. if (pShader == NULL)
  487. {
  488. D3D_THROW(D3DERR_INVALIDCALL, "Invalid vertex shader handle");
  489. }
  490. #endif
  491. if (!(pShader->m_dwFlags & CVShader::SOFTWARE))
  492. {
  493. m_pDDI->DeleteVertexShader(dwHandle);
  494. }
  495. }
  496. DebugStateChanged( D3DDM_SC_VSMODIFYSHADERS );
  497. }
  498. //-----------------------------------------------------------------------------
  499. #undef DPF_MODNAME
  500. #define DPF_MODNAME "CD3DHal::SetVertexShaderConstantI"
  501. void
  502. CD3DHal::SetVertexShaderConstantI(DWORD Register, CONST VOID* pData, DWORD count)
  503. {
  504. HRESULT hr;
  505. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING ||
  506. ((count + Register) <= D3DVS_CONSTREG_MAX_V1_1))
  507. {
  508. // For software vertex processing we store constant registers in PSGP if
  509. // possible
  510. hr = m_pv->pGeometryFuncs->LoadShaderConstants(Register, count,
  511. const_cast<VOID*>(pData));
  512. }
  513. else
  514. {
  515. if (Register >= D3DVS_CONSTREG_MAX_V1_1)
  516. {
  517. // When all modified registers are above software limit, we use Microsoft
  518. // internal array
  519. hr = GeometryFuncsGuaranteed->LoadShaderConstants(Register, count,
  520. const_cast<VOID*>(pData));
  521. }
  522. else
  523. {
  524. // Part of constant data is stores in the PSGP array and part in the
  525. // Microsoft's array
  526. UINT FirstCount = D3DVS_CONSTREG_MAX_V1_1 - Register;
  527. hr = m_pv->pGeometryFuncs->LoadShaderConstants(Register, FirstCount,
  528. const_cast<VOID*>(pData));
  529. if (FAILED(hr))
  530. {
  531. D3D_THROW(hr, "Failed to set vertex shader constants");
  532. }
  533. hr = GeometryFuncsGuaranteed->LoadShaderConstants(D3DVS_CONSTREG_MAX_V1_1,
  534. Register + count - D3DVS_CONSTREG_MAX_V1_1,
  535. &((DWORD*)pData)[FirstCount*4]);
  536. }
  537. }
  538. if (FAILED(hr))
  539. {
  540. D3D_THROW(hr, "Failed to set vertex shader constants");
  541. }
  542. if (!(m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE))
  543. {
  544. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)
  545. m_dwRuntimeFlags |= D3DRT_NEED_VSCONST_UPDATE;
  546. else
  547. m_pDDI->SetVertexShaderConstant(Register,
  548. pData,
  549. count);
  550. }
  551. DebugStateChanged( D3DDM_SC_VSCONSTANTS );
  552. }
  553. //-----------------------------------------------------------------------------
  554. #undef DPF_MODNAME
  555. #define DPF_MODNAME "CD3DHal::ValidateDraw2"
  556. void CD3DHal::ValidateDraw2(D3DPRIMITIVETYPE primType,
  557. UINT StartVertex,
  558. UINT PrimitiveCount,
  559. UINT NumVertices,
  560. BOOL bIndexPrimitive,
  561. UINT StartIndex)
  562. {
  563. #if DBG
  564. if (this->rstates[D3DRS_FILLMODE] == D3DFILL_POINT &&
  565. m_dwRuntimeFlags & D3DRT_POINTSIZEPRESENT &&
  566. primType != D3DPT_POINTLIST)
  567. {
  568. D3D_INFO(0, "Result of drawing primitives with D3DFILL_POINT fill mode "
  569. "and point size not equal 1.0f could be different on "
  570. "different devices");
  571. }
  572. if ((m_dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE) == 0 &&
  573. !(m_pv->dwFlags & D3DPV_VBCALL))
  574. {
  575. D3D_THROW_FAIL("Need to call BeginScene before rendering.");
  576. }
  577. if (m_dwCurrentShaderHandle == 0)
  578. {
  579. D3D_THROW_FAIL("Invalid vertex shader handle (0x0)");
  580. }
  581. if (bIndexPrimitive && primType == D3DPT_POINTLIST)
  582. {
  583. D3D_THROW_FAIL("Indexed point lists are not supported");
  584. }
  585. if (*(FLOAT*)&rstates[D3DRS_PATCHSEGMENTS] > 1.f)
  586. {
  587. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)
  588. {
  589. D3D_THROW_FAIL("N-Patches are not supported with software vertex processing");
  590. }
  591. else
  592. if ((GetD3DCaps()->DevCaps & (D3DDEVCAPS_NPATCHES | D3DDEVCAPS_RTPATCHES)) == 0)
  593. {
  594. D3D_THROW_FAIL("N-Patches are not supported");
  595. }
  596. }
  597. BOOL bUserMemPrimitive = this->m_dwRuntimeFlags & D3DRT_USERMEMPRIMITIVE;
  598. if (D3DVSD_ISLEGACY(m_dwCurrentShaderHandle))
  599. {
  600. // DX7 FVF handles can work only from stream zero
  601. if (!bUserMemPrimitive)
  602. {
  603. if (m_pStream[0].m_pVB == NULL)
  604. {
  605. D3D_THROW_FAIL("Stream 0 should be initialized for FVF shaders");
  606. }
  607. DWORD dwFVF = m_pStream[0].m_pVB->GetFVF();
  608. if (dwFVF != 0 && dwFVF != m_dwCurrentShaderHandle)
  609. {
  610. D3D_THROW_FAIL("Current vertex shader doesn't match VB's FVF");
  611. }
  612. if (FVF_TRANSFORMED(m_dwCurrentShaderHandle))
  613. {
  614. if (!(m_pv->dwDeviceFlags & D3DDEV_DONOTCLIP) &&
  615. m_pStream[0].m_pVB->GetBufferDesc()->Usage & D3DUSAGE_DONOTCLIP)
  616. {
  617. D3D_THROW_FAIL("Vertex buffer with D3DUSAGE_DONOTCLIP is used with clipping");
  618. }
  619. }
  620. else
  621. {
  622. D3DVERTEXBUFFER_DESC Desc;
  623. static_cast<IDirect3DVertexBuffer8*>(m_pStream[0].m_pVB)->GetDesc(&Desc);
  624. if ((BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING) != 0 &&
  625. (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING) != 0 &&
  626. (Desc.Usage & D3DUSAGE_SOFTWAREPROCESSING) == 0 &&
  627. Desc.Pool != D3DPOOL_SYSTEMMEM)
  628. {
  629. D3D_THROW_FAIL("Vertex buffer should have software usage or should be managed or should be in system memory");
  630. }
  631. }
  632. if (m_pStream[0].m_pVB->IsLocked())
  633. {
  634. D3D_THROW_FAIL("Vertex buffer must be unlocked during DrawPrimitive call");
  635. }
  636. if (*((FLOAT*)&rstates[D3DRS_PATCHSEGMENTS]) > 1.f && (m_pStream[0].m_pVB->GetBufferDesc()->Usage & D3DUSAGE_NPATCHES) == 0)
  637. {
  638. D3D_THROW_FAIL("Vertex buffers used for rendering N-Patches should have D3DUSAGE_NPATCHES set");
  639. }
  640. }
  641. // DX7 drivers cannot handle case when vertex size, computed from FVF,
  642. // is different from the stream stride
  643. if (m_pStream[0].m_dwStride != ComputeVertexSizeFVF(m_dwCurrentShaderHandle))
  644. {
  645. D3D_THROW_FAIL("Stream 0 stride should match the stride, implied by the current vertex shader");
  646. }
  647. if (m_pStream[0].m_dwNumVertices < (StartVertex + NumVertices))
  648. {
  649. D3D_THROW_FAIL("Streams do not have required number of vertices");
  650. }
  651. }
  652. else
  653. {
  654. if (m_pv->dwDeviceFlags & D3DDEV_VERTEXSHADERS)
  655. {
  656. CVShaderCode * pCode = m_pCurrentShader->m_pCode;
  657. for (DWORD i=0; i < D3DHAL_TSS_MAXSTAGES; i++)
  658. {
  659. if (this->tsstates[i][D3DTSS_TEXCOORDINDEX] != i)
  660. {
  661. D3D_ERR("Stage %d - Texture coordinate index in the stage "
  662. "must be equal to the stage index when programmable"
  663. " vertex pipeline is used", i);
  664. D3D_THROW_FAIL("");
  665. }
  666. DWORD TexTransformFlags = tsstates[i][D3DTSS_TEXTURETRANSFORMFLAGS];
  667. if (pCode)
  668. {
  669. if (TexTransformFlags & D3DTTFF_PROJECTED &&
  670. !(m_dwRuntimeFlags & D3DRT_ONLY2FLOATSPERTEXTURE) &&
  671. pCode->m_dwOutTexCoordSize[i] != 16)
  672. {
  673. D3D_ERR("Stage %d - Vertex shader must write XYZW to the "
  674. "output texture register when texture projection is enabled", i);
  675. D3D_THROW_FAIL("");
  676. }
  677. }
  678. if ((TexTransformFlags & ~D3DTTFF_PROJECTED) != D3DTTFF_DISABLE)
  679. {
  680. D3D_ERR("Stage %d - Count in D3DTSS_TEXTURETRANSFORMFLAGS "
  681. "must be 0 when programmable pipeline is used", i);
  682. D3D_THROW_FAIL("");
  683. }
  684. }
  685. }
  686. if (m_pCurrentShader->m_Declaration.m_bStreamTessPresent)
  687. {
  688. D3D_THROW_FAIL("Declaration with tesselator stream cannot be used with DrawPrimitive API");
  689. }
  690. if (((GetDDIType() < D3DDDITYPE_DX8)&&
  691. (m_pCurrentShader->m_Declaration.m_bLegacyFVF == FALSE))
  692. &&
  693. !(m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)
  694. )
  695. {
  696. D3D_THROW_FAIL("Device does not support declarations");
  697. }
  698. // Check if
  699. // 1. streams, referenced by the current shader, are valid
  700. // 2. stride in the current shader and in the stream matches
  701. // 3. Compute max number of vertices the streams can contain
  702. CVStreamDecl* pStream;
  703. pStream = m_pCurrentShader->m_Declaration.m_pActiveStreams;
  704. while(pStream)
  705. {
  706. UINT index = pStream->m_dwStreamIndex;
  707. CVStream* pDeviceStream = &m_pStream[index];
  708. if (bUserMemPrimitive)
  709. {
  710. DXGASSERT(pDeviceStream->m_pData != NULL);
  711. if (index != 0)
  712. {
  713. D3D_THROW_FAIL("DrawPrimitiveUP can use declaration only with stream 0");
  714. }
  715. }
  716. else
  717. {
  718. if (pDeviceStream->m_pVB == NULL)
  719. {
  720. D3D_ERR("Stream %d is not set, but used by current declaration", index);
  721. D3D_THROW_FAIL("");
  722. }
  723. if (pDeviceStream->m_pVB->IsLocked())
  724. {
  725. D3D_ERR("Vertex buffer in stream %d must be unlocked during drawing", index);
  726. D3D_THROW_FAIL("");
  727. }
  728. D3DVERTEXBUFFER_DESC Desc;
  729. static_cast<IDirect3DVertexBuffer8*>(pDeviceStream->m_pVB)->GetDesc(&Desc);
  730. if ((BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING) != 0 &&
  731. (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING) != 0 &&
  732. (Desc.Usage & D3DUSAGE_SOFTWAREPROCESSING) == 0 &&
  733. Desc.Pool != D3DPOOL_SYSTEMMEM)
  734. {
  735. D3D_INFO(0, "In stream %d vertex buffer should have software usage or should be managed or should be in system memory", pStream->m_dwStreamIndex);
  736. D3D_THROW_FAIL("");
  737. }
  738. if (*((FLOAT*)&rstates[D3DRS_PATCHSEGMENTS]) > 1.f && (pDeviceStream->m_pVB->GetBufferDesc()->Usage & D3DUSAGE_NPATCHES) == 0)
  739. {
  740. D3D_THROW_FAIL("Vertex buffers used for rendering N-Patches should have D3DUSAGE_NPATCHES set");
  741. }
  742. // Validate matching of FVF in the vertex buffer and stream
  743. // declaration
  744. if (m_pv->dwDeviceFlags & D3DDEV_VERTEXSHADERS)
  745. {
  746. if (pDeviceStream->m_pVB->GetFVF() != 0)
  747. {
  748. D3D_INFO(1, "In stream %d vertex buffer with FVF is "
  749. "used with programmable vertex shader",
  750. pStream->m_dwStreamIndex);
  751. }
  752. }
  753. else
  754. {
  755. // Fixed function pipeline case
  756. DWORD vbFVF = pDeviceStream->m_pVB->GetFVF();
  757. DWORD streamFVF = pStream->m_dwFVF;
  758. // VB FVF should be a superset of the stream FVF
  759. if (vbFVF && ((vbFVF & streamFVF) != streamFVF))
  760. {
  761. D3D_INFO(0, "In stream %d vertex buffer FVF and declaration FVF do not match",
  762. pStream->m_dwStreamIndex);
  763. }
  764. }
  765. }
  766. // Stride 0 is allowed
  767. if (pDeviceStream->m_dwStride)
  768. {
  769. if (pDeviceStream->m_dwStride < pStream->m_dwStride)
  770. {
  771. D3D_ERR("Vertex strides in stream %d is less than in the declaration", index);
  772. D3D_THROW_FAIL("");
  773. }
  774. if (pDeviceStream->m_dwNumVertices < (StartVertex + NumVertices))
  775. {
  776. D3D_ERR("Stream %d does not have required number of vertices",
  777. pStream->m_dwStreamIndex);
  778. D3D_THROW_FAIL("");
  779. }
  780. }
  781. pStream = (CVStreamDecl*)pStream->m_pNext;
  782. }
  783. }
  784. if (bIndexPrimitive)
  785. {
  786. if (!bUserMemPrimitive)
  787. {
  788. if (m_pIndexStream->m_pVBI == NULL)
  789. {
  790. D3D_THROW_FAIL("Index stream is not set");
  791. }
  792. if (m_pIndexStream->m_pVBI->IsLocked())
  793. {
  794. D3D_THROW_FAIL("Index buffer must be unlocked during drawing");
  795. }
  796. UINT NumIndices = GETVERTEXCOUNT(primType, PrimitiveCount);
  797. if (m_pIndexStream->m_dwNumVertices < (StartIndex + NumIndices))
  798. {
  799. D3D_THROW_FAIL("Index stream does not have required number of indices");
  800. }
  801. if (FVF_TRANSFORMED(m_dwCurrentShaderHandle) &&
  802. D3DVSD_ISLEGACY(m_dwCurrentShaderHandle))
  803. {
  804. if (!(m_pv->dwDeviceFlags & D3DDEV_DONOTCLIP) &&
  805. (m_pIndexStream->m_pVBI->GetBufferDesc()->Usage & D3DUSAGE_DONOTCLIP))
  806. {
  807. D3D_THROW_FAIL("Index buffer with D3DUSAGE_DONOTCLIP is used with clipping");
  808. }
  809. }
  810. else
  811. {
  812. D3DINDEXBUFFER_DESC Desc;
  813. static_cast<IDirect3DIndexBuffer8*>(m_pIndexStream->m_pVBI)->GetDesc(&Desc);
  814. if ((BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING) != 0 &&
  815. (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING) != 0 &&
  816. (Desc.Usage & D3DUSAGE_SOFTWAREPROCESSING) == 0 &&
  817. Desc.Pool != D3DPOOL_SYSTEMMEM)
  818. {
  819. D3D_THROW_FAIL("Index buffer should have software usage or should be managed or should be in system memory");
  820. }
  821. }
  822. if (*((FLOAT*)&rstates[D3DRS_PATCHSEGMENTS]) > 1.f && (m_pIndexStream->m_pVBI->GetBufferDesc()->Usage & D3DUSAGE_NPATCHES) == 0)
  823. {
  824. D3D_THROW_FAIL("Index buffers used for rendering N-Patches should have D3DUSAGE_NPATCHES set");
  825. }
  826. }
  827. else
  828. {
  829. DXGASSERT(m_pIndexStream->m_pData != NULL);
  830. }
  831. }
  832. #endif //DBG
  833. }
  834. //-----------------------------------------------------------------------------
  835. #undef DPF_MODNAME
  836. #define DPF_MODNAME "CD3DHal::DrawPoints"
  837. void CD3DHal::DrawPoints(UINT StartVertex)
  838. {
  839. BOOL bRecomputeOutputFVF = FALSE;
  840. // If point scale is enabled and device supports point sprites
  841. // we may need to add the point size to the output FVF
  842. if (rstates[D3DRS_POINTSCALEENABLE] &&
  843. !(m_dwRuntimeFlags & D3DRT_POINTSIZEINVERTEX) &&
  844. !(m_pv->dwDeviceFlags & D3DDEV_TRANSFORMEDFVF))
  845. {
  846. ForceFVFRecompute();
  847. bRecomputeOutputFVF = TRUE;
  848. }
  849. if (m_dwRuntimeFlags & D3DRT_DOPOINTSPRITEEMULATION)
  850. {
  851. // We do point sprite expansion when point size is not 1.0 in the
  852. // render state or it is present in vertices or we need to do point
  853. // scaling for untransformed vertices
  854. if ((m_dwRuntimeFlags & D3DRT_POINTSIZEPRESENT ||
  855. (rstates[D3DRS_POINTSCALEENABLE] &&
  856. !(m_pv->dwDeviceFlags & D3DDEV_TRANSFORMEDFVF))) &&
  857. // We do not do emulation for devices which supports point sprites,
  858. // but only when there is no point size in the FVF
  859. !(bRecomputeOutputFVF == FALSE &&
  860. (m_dwRuntimeFlags & D3DRT_POINTSIZEINVERTEX) == 0 &&
  861. m_dwRuntimeFlags & D3DRT_SUPPORTSPOINTSPRITES))
  862. {
  863. m_pv->dwDeviceFlags |= D3DDEV_DOPOINTSPRITEEMULATION;
  864. m_pDDI->PickProcessPrimitive();
  865. }
  866. else
  867. {
  868. if (m_pv->dwDeviceFlags & D3DDEV_TRANSFORMEDFVF &&
  869. (m_pv->dwDeviceFlags & D3DDEV_DONOTCLIP ||
  870. !(m_pv->dwDeviceFlags & D3DDEV_VBPROCVER)))
  871. {
  872. // Now we can call DDI directly, because no emulation is
  873. // necessary
  874. if (m_pStream[0].m_pVB)
  875. {
  876. (*m_pDDI->GetDrawPrimFunction())(this, m_pv->primType,
  877. StartVertex,
  878. m_pv->dwNumPrimitives);
  879. }
  880. else
  881. {
  882. m_pDDI->SetVertexShader(m_dwCurrentShaderHandle);
  883. m_pDDI->SetStreamSource(0, &m_pStream[0]);
  884. m_pDDI->DrawPrimitiveUP(m_pv->primType, m_pv->dwNumPrimitives);
  885. }
  886. return;
  887. }
  888. }
  889. }
  890. (this->*m_pfnPrepareToDraw)(StartVertex);
  891. (m_pDDI->*m_pDDI->m_pfnProcessPrimitive)(m_pv, StartVertex);
  892. if (bRecomputeOutputFVF)
  893. {
  894. ForceFVFRecompute();
  895. }
  896. m_pv->dwDeviceFlags &= ~D3DDEV_DOPOINTSPRITEEMULATION;
  897. m_pDDI->PickProcessPrimitive();
  898. }
  899. //-----------------------------------------------------------------------------
  900. // Draw all primitive types except points
  901. //
  902. #undef DPF_MODNAME
  903. #define DPF_MODNAME "DrawPrimitiveHal"
  904. void CD3DHal_DrawPrimitive(CD3DBase* pBaseDevice, D3DPRIMITIVETYPE PrimitiveType,
  905. UINT StartVertex, UINT PrimitiveCount)
  906. {
  907. CD3DHal* pDevice = static_cast<CD3DHal*>(pBaseDevice);
  908. CD3DDDIDX6* pDDI = pBaseDevice->m_pDDI;
  909. #if DBG
  910. UINT nVer = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  911. pDevice->ValidateDraw2(PrimitiveType, StartVertex, PrimitiveCount, nVer,
  912. FALSE);
  913. #endif
  914. D3DFE_PROCESSVERTICES* pv = pDevice->m_pv;
  915. pv->primType = PrimitiveType;
  916. pv->dwNumPrimitives = PrimitiveCount;
  917. pv->dwNumVertices = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  918. pv->dwFlags &= D3DPV_PERSIST;
  919. (pDevice->*pDevice->m_pfnPrepareToDraw)(StartVertex);
  920. (pDDI->*pDDI->m_pfnProcessPrimitive)(pv, StartVertex);
  921. }
  922. //-----------------------------------------------------------------------------
  923. // Draw only points
  924. //
  925. #undef DPF_MODNAME
  926. #define DPF_MODNAME "CD3DHal::DrawPointsI"
  927. void CD3DHal::DrawPointsI(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
  928. UINT PrimitiveCount)
  929. {
  930. #if DBG
  931. UINT nVer = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  932. ValidateDraw2(PrimitiveType, StartVertex, PrimitiveCount, nVer, FALSE);
  933. #endif
  934. if (!(m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING) ||
  935. CanCallDriver(this, PrimitiveType))
  936. {
  937. (*m_pfnDrawPrim)(this, PrimitiveType, StartVertex, PrimitiveCount);
  938. }
  939. else
  940. {
  941. m_pv->primType = PrimitiveType;
  942. m_pv->dwNumPrimitives = PrimitiveCount;
  943. m_pv->dwNumVertices = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  944. m_pv->dwFlags &= D3DPV_PERSIST;
  945. DrawPoints(StartVertex);
  946. }
  947. }
  948. //-----------------------------------------------------------------------------
  949. #undef DPF_MODNAME
  950. #define DPF_MODNAME "CD3DHal_DrawIndexedPrimitive"
  951. void CD3DHal_DrawIndexedPrimitive(CD3DBase* pBaseDevice,
  952. D3DPRIMITIVETYPE PrimitiveType,
  953. UINT BaseIndex,
  954. UINT MinIndex, UINT NumVertices,
  955. UINT StartIndex,
  956. UINT PrimitiveCount)
  957. {
  958. CD3DHal* pDevice = static_cast<CD3DHal*>(pBaseDevice);
  959. CVIndexStream* pIndexStream = pBaseDevice->m_pIndexStream;
  960. CD3DDDIDX6* pDDI = pBaseDevice->m_pDDI;
  961. #if DBG
  962. pDevice->ValidateDraw2(PrimitiveType, MinIndex + pIndexStream->m_dwBaseIndex,
  963. PrimitiveCount, NumVertices, TRUE, StartIndex);
  964. #endif
  965. D3DFE_PROCESSVERTICES* pv = pDevice->m_pv;
  966. pIndexStream->m_pData = NULL;
  967. pv->primType = PrimitiveType;
  968. pv->dwNumPrimitives = PrimitiveCount;
  969. pv->dwFlags &= D3DPV_PERSIST;
  970. pv->dwNumVertices = NumVertices;
  971. pv->dwNumIndices = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  972. pv->dwIndexSize = pIndexStream->m_dwStride;
  973. UINT StartVertex = MinIndex + pIndexStream->m_dwBaseIndex;
  974. pDDI->SetIndexedPrimParams(StartIndex, MinIndex, NumVertices,
  975. pIndexStream->m_dwBaseIndex);
  976. (pDevice->*pDevice->m_pfnPrepareToDraw)(StartVertex);
  977. (pDDI->*pDDI->m_pfnProcessIndexedPrimitive)(pv, StartVertex);
  978. }
  979. //-----------------------------------------------------------------------------
  980. #undef DPF_MODNAME
  981. #define DPF_MODNAME "CD3DHal::DrawPrimitiveUPI"
  982. void CD3DHal::DrawPrimitiveUPI(D3DPRIMITIVETYPE PrimType, UINT PrimCount)
  983. {
  984. #if DBG
  985. UINT nVer = GETVERTEXCOUNT(PrimType, PrimCount);
  986. ValidateDraw2(PrimType, 0, PrimCount, nVer, FALSE);
  987. #endif
  988. m_pv->dwDeviceFlags &= ~D3DDEV_VBPROCVER;
  989. if (!(m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING))
  990. {
  991. if (m_dwRuntimeFlags & D3DRT_DONPATCHCONVERSION &&
  992. PrimType >= D3DPT_TRIANGLELIST)
  993. {
  994. CD3DHal_DrawNPatch(this, PrimType, 0, PrimCount);
  995. }
  996. else
  997. {
  998. m_pDDI->DrawPrimitiveUP(PrimType, PrimCount);
  999. }
  1000. }
  1001. else
  1002. if (CanCallDriver(this, PrimType))
  1003. {
  1004. m_pDDI->SetVertexShader(m_dwCurrentShaderHandle);
  1005. m_pDDI->SetStreamSource(0, &m_pStream[0]);
  1006. m_pDDI->DrawPrimitiveUP(PrimType, PrimCount);
  1007. }
  1008. else
  1009. {
  1010. SetupStrides(m_pv, m_pStream[0].m_dwStride);
  1011. m_pv->primType = PrimType;
  1012. m_pv->dwNumPrimitives = PrimCount;
  1013. m_pv->dwNumVertices = GETVERTEXCOUNT(PrimType, PrimCount);
  1014. m_pv->dwFlags &= D3DPV_PERSIST;
  1015. if (PrimType != D3DPT_POINTLIST)
  1016. {
  1017. (this->*m_pfnPrepareToDraw)(0);
  1018. (m_pDDI->*m_pDDI->m_pfnProcessPrimitive)(m_pv, 0);
  1019. }
  1020. else
  1021. DrawPoints(0);
  1022. }
  1023. }
  1024. //-----------------------------------------------------------------------------
  1025. #undef DPF_MODNAME
  1026. #define DPF_MODNAME "CD3DHal::DrawIndexedPrimitiveUPI"
  1027. void
  1028. CD3DHal::DrawIndexedPrimitiveUPI(D3DPRIMITIVETYPE PrimType,
  1029. UINT MinVertexIndex,
  1030. UINT NumVertices,
  1031. UINT PrimCount)
  1032. {
  1033. #if DBG
  1034. ValidateDraw2(PrimType, 0, PrimCount, NumVertices, TRUE);
  1035. #endif
  1036. m_pv->dwDeviceFlags &= ~D3DDEV_VBPROCVER;
  1037. if (!(m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING))
  1038. {
  1039. if (m_dwRuntimeFlags & D3DRT_DONPATCHCONVERSION &&
  1040. PrimType >= D3DPT_TRIANGLELIST)
  1041. {
  1042. CD3DHal_DrawIndexedNPatch(this, PrimType, 0, MinVertexIndex,
  1043. NumVertices, 0, PrimCount);
  1044. }
  1045. else
  1046. {
  1047. m_pDDI->DrawIndexedPrimitiveUP(PrimType, MinVertexIndex, NumVertices,
  1048. PrimCount);
  1049. }
  1050. }
  1051. else
  1052. if (CanCallDriver(this, PrimType))
  1053. {
  1054. m_pDDI->SetVertexShader(m_dwCurrentShaderHandle);
  1055. m_pDDI->SetStreamSource(0, &m_pStream[0]);
  1056. m_pDDI->SetIndices(m_pIndexStream);
  1057. m_pDDI->DrawIndexedPrimitiveUP(PrimType, MinVertexIndex, NumVertices,
  1058. PrimCount);
  1059. }
  1060. else
  1061. {
  1062. SetupStrides(m_pv, m_pStream[0].m_dwStride);
  1063. m_pv->primType = PrimType;
  1064. m_pv->dwNumPrimitives = PrimCount;
  1065. m_pv->dwFlags &= D3DPV_PERSIST;
  1066. m_pv->dwNumVertices = NumVertices;
  1067. m_pv->dwNumIndices = GETVERTEXCOUNT(PrimType, PrimCount);
  1068. m_pv->lpwIndices = (WORD*)m_pIndexStream->m_pData;
  1069. m_pv->dwIndexSize = m_pIndexStream->m_dwStride;
  1070. m_pDDI->SetIndexedPrimParams(0, MinVertexIndex,
  1071. MinVertexIndex + NumVertices, 0);
  1072. (this->*m_pfnPrepareToDraw)(MinVertexIndex);
  1073. (m_pDDI->*m_pDDI->m_pfnProcessIndexedPrimitive)(m_pv, MinVertexIndex);
  1074. }
  1075. }
  1076. //-----------------------------------------------------------------------------
  1077. #undef DPF_MODNAME
  1078. #define DPF_MODNAME "SetupFVFDataVVM"
  1079. void SetupFVFDataVVM(CD3DHal* pDev)
  1080. {
  1081. D3DFE_PROCESSVERTICES* pv = pDev->m_pv;
  1082. // We have to restore texture stage indices if previous primitive
  1083. // re-mapped them
  1084. if (pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  1085. {
  1086. RestoreTextureStages(pDev);
  1087. }
  1088. // Input FVF has no meaning for vertex shaders, but it is used for validaion
  1089. pv->dwVIDIn = 0;
  1090. // Compute output FVF
  1091. CVShaderCode * pCode = pDev->m_pCurrentShader->m_pCode;
  1092. pv->dwVIDOut = pCode->m_dwOutFVF;
  1093. pv->dwOutputSize = pCode->m_dwOutVerSize;
  1094. pv->nOutTexCoord = pCode->m_nOutTexCoord;
  1095. // We use offsets, computed by the vertex shader
  1096. pv->pointSizeOffsetOut = pCode->m_dwPointSizeOffset;
  1097. pv->diffuseOffsetOut = pCode->m_dwDiffuseOffset;
  1098. pv->specularOffsetOut = pCode->m_dwSpecularOffset;
  1099. pv->fogOffsetOut = pCode->m_dwFogOffset;
  1100. pv->texOffsetOut = pCode->m_dwTextureOffset;
  1101. pv->dwTextureCoordSizeTotal = 0;
  1102. for (DWORD i=0; i < pv->nOutTexCoord; i++)
  1103. {
  1104. DWORD dwSize = pCode->m_dwOutTexCoordSize[i];
  1105. pv->dwTextureCoordSize[i] = dwSize;
  1106. pv->dwTextureCoordSizeTotal += dwSize;
  1107. }
  1108. }
  1109. //----------------------------------------------------------------------
  1110. void CD3DHal::SetupFVFData()
  1111. {
  1112. CD3DHal::SetupFVFDataCommon();
  1113. if (!(m_pv->dwVIDIn & D3DFVF_NORMAL))
  1114. m_pv->dwDeviceFlags &= ~D3DDEV_NORMALINCAMERASPACE;
  1115. }
  1116. //---------------------------------------------------------------------
  1117. // Computes the following data
  1118. // - dwTextureCoordOffset[] offset of every input texture coordinates
  1119. static __inline void ComputeInpTexCoordOffsets(DWORD dwNumTexCoord,
  1120. DWORD dwFVF,
  1121. DWORD *pdwTextureCoordOffset)
  1122. {
  1123. // Compute texture coordinate size
  1124. DWORD dwTextureFormats = dwFVF >> 16;
  1125. if (dwTextureFormats == 0)
  1126. {
  1127. for (DWORD i=0; i < dwNumTexCoord; i++)
  1128. {
  1129. pdwTextureCoordOffset[i] = i << 3;
  1130. }
  1131. }
  1132. else
  1133. {
  1134. DWORD dwOffset = 0;
  1135. for (DWORD i=0; i < dwNumTexCoord; i++)
  1136. {
  1137. pdwTextureCoordOffset[i] = dwOffset;
  1138. dwOffset += g_TextureSize[dwTextureFormats & 3];
  1139. dwTextureFormats >>= 2;
  1140. }
  1141. }
  1142. return;
  1143. }
  1144. //---------------------------------------------------------------------
  1145. // Returns 2 bits of FVF texture format for the texture index
  1146. //
  1147. static inline DWORD FVFGetTextureFormat(DWORD dwFVF, DWORD dwTextureIndex)
  1148. {
  1149. return (dwFVF >> (dwTextureIndex*2 + 16)) & 3;
  1150. }
  1151. //---------------------------------------------------------------------
  1152. // Returns texture format bits shifted to the right place
  1153. //
  1154. static inline DWORD FVFMakeTextureFormat(DWORD dwNumberOfCoordinates, DWORD dwTextureIndex)
  1155. {
  1156. return g_dwTextureFormat[dwNumberOfCoordinates] << ((dwTextureIndex << 1) + 16);
  1157. }
  1158. //---------------------------------------------------------------------
  1159. inline DWORD GetOutTexCoordSize(DWORD *pdwStage, DWORD dwInpTexCoordSize)
  1160. {
  1161. // Low byte has texture coordinate count
  1162. const DWORD dwTextureTransformFlags = pdwStage[D3DTSS_TEXTURETRANSFORMFLAGS] & 0xFF;
  1163. if (dwTextureTransformFlags == 0)
  1164. return dwInpTexCoordSize;
  1165. else
  1166. return (dwTextureTransformFlags << 2);
  1167. }
  1168. //----------------------------------------------------------------------
  1169. // pDevI->nOutTexCoord should be initialized to the number of input texture coord sets
  1170. //
  1171. void EvalTextureTransforms(LPD3DHAL pDevI, DWORD dwTexTransform,
  1172. DWORD *pdwOutTextureSize, DWORD *pdwOutTextureFormat)
  1173. {
  1174. D3DFE_PROCESSVERTICES* pv = pDevI->m_pv;
  1175. DWORD dwOutTextureSize = 0; // Used to compute output vertex size
  1176. DWORD dwOutTextureFormat = 0; // Used to compute output texture FVF
  1177. // The bits are used to find out how the texture coordinates are used.
  1178. const DWORD __USED_BY_TRANSFORM = 1;
  1179. const DWORD __USED = 2;
  1180. const DWORD __USED_TEXTURE_PROJECTION = 4;
  1181. // The low 16 bits are for _USED bits. The high 16 bits will hold
  1182. // re-mapped texture index for a stage
  1183. DWORD dwTexCoordUsage[D3DDP_MAXTEXCOORD];
  1184. memset(dwTexCoordUsage, 0, sizeof(dwTexCoordUsage));
  1185. // Re-mapping buffer will contain only stages that use texture
  1186. // This variable is used to count them
  1187. pDevI->dwNumTextureStagesToRemap = 0;
  1188. DWORD dwNewIndex = 0; // Used to generate output index
  1189. // We need offsets for every input texture coordinate, because
  1190. // we could access them in random order.
  1191. // Offsets are not needed for strided input
  1192. DWORD dwTextureCoordOffset[D3DDP_MAXTEXCOORD];
  1193. if (!(pv->dwDeviceFlags & D3DDEV_STRIDE))
  1194. {
  1195. ComputeInpTexCoordOffsets(pv->nTexCoord, pv->dwVIDIn, dwTextureCoordOffset);
  1196. }
  1197. DWORD dwOutTextureCoordSize[D3DDP_MAXTEXCOORD];
  1198. // TRUE, if we do not do texture projection and transform for a stage,
  1199. // because the stage does not have corresponding texture coordinates in the
  1200. // input
  1201. BOOL bIgnoreTexCoord = FALSE;
  1202. // Go through all texture stages and find those wich use texture coordinates
  1203. for (DWORD i=0; i < D3DDP_MAXTEXCOORD; i++)
  1204. {
  1205. if (pDevI->tsstates[i][D3DTSS_COLOROP] == D3DTOP_DISABLE)
  1206. break;
  1207. DWORD dwIndex = pDevI->tsstates[i][D3DTSS_TEXCOORDINDEX];
  1208. DWORD dwInpTextureFormat;
  1209. DWORD dwInpTexSize;
  1210. LPD3DFE_TEXTURESTAGE pStage = &pDevI->textureStageToRemap[pDevI->dwNumTextureStagesToRemap];
  1211. DWORD dwTexGenMode = dwIndex & ~0xFFFF;
  1212. pStage->dwInpOffset = 0;
  1213. dwIndex = dwIndex & 0xFFFF; // Remove texture generation mode
  1214. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL ||
  1215. dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION ||
  1216. dwTexGenMode == D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR)
  1217. {
  1218. dwInpTextureFormat = D3DFVF_TEXCOORDSIZE3(dwIndex);
  1219. dwInpTexSize = 3*sizeof(D3DVALUE);
  1220. pv->dwDeviceFlags |= D3DDEV_REMAPTEXTUREINDICES;
  1221. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR)
  1222. pv->dwDeviceFlags |= D3DDEV_NORMALINCAMERASPACE | D3DDEV_POSITIONINCAMERASPACE;
  1223. else
  1224. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL)
  1225. pv->dwDeviceFlags |= D3DDEV_NORMALINCAMERASPACE;
  1226. else
  1227. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION)
  1228. pv->dwDeviceFlags |= D3DDEV_POSITIONINCAMERASPACE;
  1229. }
  1230. else
  1231. {
  1232. if (dwIndex >= pv->nTexCoord)
  1233. {
  1234. // This could happen when input vertex does not have texture
  1235. // coordinates, but it is OK, because texture pointer in the
  1236. // stage could be NULL, or the stage does not use texture, or
  1237. // pixel shader is used.
  1238. // It is too complex and error prone to check all cases when
  1239. // this is an user error, so we just make this case to work.
  1240. dwIndex = 0;
  1241. dwInpTexSize = sizeof(float)*2;
  1242. dwInpTextureFormat = 0;
  1243. // Ignore special texture coordinate processing for this stage
  1244. bIgnoreTexCoord = TRUE;
  1245. // Disable texture transform for the stage
  1246. dwTexTransform &= ~1;
  1247. pStage->dwInpOffset = 0;
  1248. }
  1249. else
  1250. {
  1251. dwInpTexSize = pv->dwTextureCoordSize[dwIndex];
  1252. dwInpTextureFormat = FVFGetTextureFormat(pv->dwVIDIn, dwIndex);
  1253. pStage->dwInpOffset = dwTextureCoordOffset[dwIndex];
  1254. }
  1255. }
  1256. pStage->dwInpCoordIndex = dwIndex;
  1257. pStage->dwTexGenMode = dwTexGenMode;
  1258. pStage->dwOrgStage = i;
  1259. pStage->bDoTextureProjection = FALSE;
  1260. DWORD dwOutTexCoordSize; // Size of the texture coord set in bytes for this stage
  1261. if (dwTexTransform & 1)
  1262. {
  1263. pv->dwDeviceFlags |= D3DDEV_TEXTURETRANSFORM;
  1264. pStage->pmTextureTransform = &pv->mTexture[i];
  1265. dwOutTexCoordSize = GetOutTexCoordSize((DWORD*)&pDevI->tsstates[i], dwInpTexSize);
  1266. // If we have to add or remove some coordinates we go through
  1267. // the re-mapping path
  1268. if (dwOutTexCoordSize != dwInpTexSize)
  1269. pv->dwDeviceFlags |= D3DDEV_REMAPTEXTUREINDICES;
  1270. pStage->dwTexTransformFuncIndex = MakeTexTransformFuncIndex
  1271. (dwInpTexSize >> 2, dwOutTexCoordSize >> 2);
  1272. }
  1273. else
  1274. {
  1275. pStage->pmTextureTransform = NULL;
  1276. dwOutTexCoordSize = dwInpTexSize;
  1277. pStage->dwTexTransformFuncIndex = 0;
  1278. }
  1279. if (NeedTextureProjection(pv, i) && !bIgnoreTexCoord)
  1280. {
  1281. // Remove one float from the output
  1282. dwOutTexCoordSize -= 4;
  1283. // Set re-mapping so we do not complicate simple case
  1284. pv->dwDeviceFlags |= D3DDEV_REMAPTEXTUREINDICES;
  1285. // Texture projection is required for the stage
  1286. pStage->bDoTextureProjection = TRUE;
  1287. }
  1288. if ((dwTexCoordUsage[dwIndex] & 0xFFFF) == 0)
  1289. {
  1290. // Texture coordinate set is used first time
  1291. if (dwTexTransform & 1)
  1292. dwTexCoordUsage[dwIndex] |= __USED_BY_TRANSFORM;
  1293. dwTexCoordUsage[dwIndex] |= __USED;
  1294. if (pStage->bDoTextureProjection)
  1295. dwTexCoordUsage[dwIndex] |= __USED_TEXTURE_PROJECTION;
  1296. }
  1297. else
  1298. {
  1299. // Texture coordinate set is used second or more time
  1300. if (dwTexTransform & 1)
  1301. {
  1302. // This set is used by two texture transforms or a
  1303. // texture transform and without it, so we have to
  1304. // generate an additional output texture coordinate
  1305. dwTexCoordUsage[dwIndex] |= __USED_BY_TRANSFORM;
  1306. pv->dwDeviceFlags |= D3DDEV_REMAPTEXTUREINDICES;
  1307. }
  1308. else
  1309. {
  1310. if (dwTexCoordUsage[dwIndex] & __USED_BY_TRANSFORM)
  1311. {
  1312. // This set is used by two texture transforms or a
  1313. // texture transform and without it, so we have to
  1314. // generate an additional output texture coordinate
  1315. pv->dwDeviceFlags |= D3DDEV_REMAPTEXTUREINDICES;
  1316. }
  1317. else
  1318. // We can re-use the same input texture coordinate if there is no
  1319. // texture generation and texture projection flag is the same for both
  1320. // stages
  1321. if (dwTexGenMode == 0 &&
  1322. (pStage->bDoTextureProjection == ((dwTexCoordUsage[dwIndex] & __USED_TEXTURE_PROJECTION) != 0)))
  1323. {
  1324. DWORD dwOutIndex = dwTexCoordUsage[dwIndex] >> 16;
  1325. pStage->dwOutCoordIndex = dwOutIndex;
  1326. // Mark the stage as not to be used in the vertex processing loop
  1327. pStage->dwInpOffset = 0xFFFFFFFF;
  1328. goto l_NoNewOutTexCoord;
  1329. }
  1330. }
  1331. }
  1332. // If we are here, we have to generate new output texture coordinate set
  1333. pStage->dwOutCoordIndex = dwNewIndex;
  1334. dwTexCoordUsage[dwIndex] |= dwNewIndex << 16;
  1335. dwOutTextureSize += dwOutTexCoordSize;
  1336. dwOutTextureCoordSize[dwNewIndex] = dwOutTexCoordSize;
  1337. dwOutTextureFormat |= FVFMakeTextureFormat(dwOutTexCoordSize >> 2, dwNewIndex);
  1338. dwNewIndex++;
  1339. l_NoNewOutTexCoord:
  1340. pDevI->dwNumTextureStagesToRemap++;
  1341. dwTexTransform >>= 1;
  1342. }
  1343. if (pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  1344. {
  1345. // Now, when we have to do re-mapping, we have to set new output texture
  1346. // coordinate set sizes and we need to remove stages, which do not produce
  1347. // output texture coordinates.
  1348. DWORD dwNumTextureStages = 0;
  1349. for (DWORD i=0; i < pDevI->dwNumTextureStagesToRemap; i++)
  1350. {
  1351. if (pDevI->textureStageToRemap[i].dwInpOffset != 0xFFFFFFFF)
  1352. {
  1353. pv->textureStage[dwNumTextureStages] = pDevI->textureStageToRemap[i];
  1354. pv->dwTextureCoordSize[dwNumTextureStages] = dwOutTextureCoordSize[dwNumTextureStages];
  1355. dwNumTextureStages++;
  1356. }
  1357. pv->dwNumTextureStages = dwNumTextureStages;
  1358. }
  1359. pv->nOutTexCoord = dwNewIndex;
  1360. }
  1361. *pdwOutTextureSize = dwOutTextureSize;
  1362. *pdwOutTextureFormat = dwOutTextureFormat;
  1363. }
  1364. //----------------------------------------------------------------------
  1365. // Sets texture transform pointer for every input texture coordinate set
  1366. //
  1367. void SetupTextureTransforms(LPD3DHAL pDevI)
  1368. {
  1369. D3DFE_PROCESSVERTICES* pv = pDevI->m_pv;
  1370. // Set texture transforms to NULL in case when some texture coordinates
  1371. // are not used by texture stages
  1372. memset(pv->pmTexture, 0, sizeof(pv->pmTexture));
  1373. for (DWORD i=0; i < pDevI->dwNumTextureStagesToRemap; i++)
  1374. {
  1375. LPD3DFE_TEXTURESTAGE pStage = &pDevI->textureStageToRemap[i];
  1376. pv->pmTexture[pStage->dwInpCoordIndex] = pStage->pmTextureTransform;
  1377. }
  1378. }
  1379. //----------------------------------------------------------------------
  1380. // Computes the following device data
  1381. // - dwVIDOut, based on input FVF id and device settings
  1382. // - nTexCoord
  1383. // - dwTextureCoordSizeTotal
  1384. // - dwTextureCoordSize[] array, based on the input FVF id
  1385. // - dwOutputSize, based on the output FVF id
  1386. //
  1387. // The function is called from ProcessVertices and DrawPrimitives code paths
  1388. //
  1389. // The following variables should be set in the pDevI:
  1390. // - dwVIDIn
  1391. //
  1392. // Number of texture coordinates is set based on dwVIDIn. ValidateFVF should
  1393. // make sure that it is not greater than supported by the driver
  1394. // Last settings for dwVIDOut and dwVIDIn are saved to speed up processing
  1395. //
  1396. #undef DPF_MODNAME
  1397. #define DPF_MODNAME "CD3DHal::SetupFVFDataCommon"
  1398. void CD3DHal::SetupFVFDataCommon()
  1399. {
  1400. HRESULT ret;
  1401. this->dwFEFlags &= ~D3DFE_FVF_DIRTY;
  1402. // We have to restore texture stage indices if previous primitive
  1403. // re-mapped them
  1404. if (m_pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  1405. {
  1406. RestoreTextureStages(this);
  1407. }
  1408. // Compute number of the input texture coordinates
  1409. m_pv->nTexCoord = FVF_TEXCOORD_NUMBER(m_pv->dwVIDIn);
  1410. // Compute size of input texture coordinates
  1411. m_pv->dwTextureCoordSizeTotal = ComputeTextureCoordSize(m_pv->dwVIDIn,
  1412. m_pv->dwInpTextureCoordSize);
  1413. // This size is the same for input and output FVFs in case when we do not have to
  1414. // expand number of texture coordinates
  1415. for (DWORD i=0; i < m_pv->nTexCoord; i++)
  1416. m_pv->dwTextureCoordSize[i] = m_pv->dwInpTextureCoordSize[i];
  1417. m_pv->nOutTexCoord = m_pv->nTexCoord;
  1418. // Setup input vertex offsets
  1419. UpdateGeometryLoopData(m_pv);
  1420. if (FVF_TRANSFORMED(m_pv->dwVIDIn))
  1421. {
  1422. // Set up vertex pointers
  1423. m_pv->dwVIDOut = m_pv->dwVIDIn;
  1424. ComputeOutputVertexOffsets(m_pv);
  1425. m_pv->dwOutputSize = ComputeVertexSizeFVF(m_pv->dwVIDOut);
  1426. return;
  1427. }
  1428. // Compute output FVF
  1429. m_pv->dwVIDOut = D3DFVF_XYZRHW;
  1430. if (m_pv->dwDeviceFlags & D3DDEV_DONOTSTRIPELEMENTS &&
  1431. !(m_pv->dwFlags & D3DPV_VBCALL))
  1432. {
  1433. m_pv->dwVIDOut |= D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
  1434. }
  1435. else
  1436. {
  1437. // If normal present we have to compute specular and duffuse
  1438. // Otherwise set these bits the same as input.
  1439. // Not that normal should not be present for XYZRHW position type
  1440. if (m_pv->dwDeviceFlags & D3DDEV_LIGHTING)
  1441. m_pv->dwVIDOut |= D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
  1442. else
  1443. m_pv->dwVIDOut |= m_pv->dwVIDIn &
  1444. (D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
  1445. // Always set specular flag if vertex fog is enabled
  1446. if (this->rstates[D3DRENDERSTATE_FOGENABLE] &&
  1447. m_pv->lighting.fog_mode != D3DFOG_NONE)
  1448. {
  1449. m_pv->dwVIDOut |= D3DFVF_SPECULAR;
  1450. }
  1451. else
  1452. // Clear specular flag if specular disabled and we do not have
  1453. // specular in the input
  1454. if (!this->rstates[D3DRENDERSTATE_SPECULARENABLE] &&
  1455. !(m_pv->dwVIDIn & D3DFVF_SPECULAR))
  1456. {
  1457. m_pv->dwVIDOut &= ~D3DFVF_SPECULAR;
  1458. }
  1459. }
  1460. if (m_pv->dwVIDIn & D3DFVF_PSIZE ||
  1461. m_pv->primType == D3DPT_POINTLIST &&
  1462. this->rstates[D3DRS_POINTSCALEENABLE])
  1463. {
  1464. m_pv->dwVIDOut |= D3DFVF_PSIZE;
  1465. }
  1466. // Compute number of the output texture coordinates
  1467. // Transform enable bits
  1468. m_pv->dwDeviceFlags &= ~D3DDEV_TEXTURETRANSFORM;
  1469. DWORD dwTexTransform = m_pv->dwFlags2 & __FLAGS2_TEXTRANSFORM;
  1470. // When texture transform is enabled or we need to do projected texture
  1471. // emulation or texture coordinates are taken from the vertex data (texgen),
  1472. // output texture coordinates could be generated.
  1473. // So we go and evaluate texture stages
  1474. if ((m_pv->dwFlags2 & (__FLAGS2_TEXTRANSFORM | __FLAGS2_TEXPROJ)
  1475. && (m_pv->nTexCoord > 0)) ||
  1476. m_pv->dwFlags2 & __FLAGS2_TEXGEN)
  1477. {
  1478. DWORD dwOutTextureSize; // Used to compute output vertex size
  1479. DWORD dwOutTextureFormat; // Used to compute output texture FVF
  1480. // There are texture transforms.
  1481. // Now we find out if some of the texture coordinates are used two
  1482. // or more times and used by a texture transform. In this case we
  1483. // have expand number of output texture coordinates.
  1484. EvalTextureTransforms(this, dwTexTransform,
  1485. &dwOutTextureSize,
  1486. &dwOutTextureFormat);
  1487. if (m_pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  1488. {
  1489. // For ProcessVertices calls user should set texture stages and
  1490. // wrap modes himself
  1491. if (!(m_pv->dwFlags & D3DPV_VBCALL))
  1492. {
  1493. // dwVIDIn is used to force re-compute FVF in the
  1494. // SetTextureStageState. so we save and restore it.
  1495. DWORD dwVIDInSaved = m_pv->dwVIDIn;
  1496. // Re-map indices in the texture stages and wrap modes
  1497. DWORD dwOrgWrapModes[D3DDP_MAXTEXCOORD];
  1498. memcpy(dwOrgWrapModes, &this->rstates[D3DRENDERSTATE_WRAP0],
  1499. sizeof(dwOrgWrapModes));
  1500. for (DWORD i=0; i < this->dwNumTextureStagesToRemap; i++)
  1501. {
  1502. LPD3DFE_TEXTURESTAGE pStage = &this->textureStageToRemap[i];
  1503. DWORD dwOutIndex = pStage->dwOutCoordIndex;
  1504. DWORD dwInpIndex = pStage->dwInpCoordIndex;
  1505. if (dwOutIndex != dwInpIndex || pStage->dwTexGenMode)
  1506. {
  1507. DWORD dwState = D3DRENDERSTATE_WRAP0 + dwOutIndex;
  1508. pStage->dwOrgWrapMode = dwOrgWrapModes[dwOutIndex];
  1509. DWORD dwValue = dwOrgWrapModes[dwInpIndex];
  1510. // We do not call UpdateInternaState because it
  1511. // will call ForceRecomputeFVF and we do not want this.
  1512. this->rstates[dwState] = dwValue;
  1513. m_pDDI->SetRenderState((D3DRENDERSTATETYPE)dwState, dwValue);
  1514. // We do not call UpdateInternalTextureStageState because it
  1515. // will call ForceRecomputeFVF and we do not want this.
  1516. m_pDDI->SetTSS(pStage->dwOrgStage, D3DTSS_TEXCOORDINDEX, dwOutIndex);
  1517. // We do not call UpdateInternalTextureStageState because it
  1518. // will call ForceRecomputeFVF and we do not want this.
  1519. // We set some invalid value to the internal array, because otherwise
  1520. // a new SetTextureStageState could be filtered as redundant
  1521. tsstates[pStage->dwOrgStage][D3DTSS_TEXCOORDINDEX] = 0xFFFFFFFF;
  1522. }
  1523. }
  1524. m_pv->dwVIDIn = dwVIDInSaved;
  1525. }
  1526. else
  1527. {
  1528. }
  1529. m_pv->dwVIDOut |= dwOutTextureFormat;
  1530. m_pv->dwTextureCoordSizeTotal = dwOutTextureSize;
  1531. }
  1532. else
  1533. { // We do not do re-mapping but we have to make correspondence between
  1534. // texture sets and texture transforms
  1535. SetupTextureTransforms(this);
  1536. // Copy input texture formats
  1537. m_pv->dwVIDOut |= m_pv->dwVIDIn & 0xFFFF0000;
  1538. }
  1539. }
  1540. else
  1541. {
  1542. // Copy input texture formats
  1543. m_pv->dwVIDOut |= m_pv->dwVIDIn & 0xFFFF0000;
  1544. // When we have texture coordinate set with number of floats different
  1545. // from 2 and device does not support them, we "fix" the texture format
  1546. if (m_pv->dwVIDOut & 0xFFFF0000)
  1547. {
  1548. if (m_dwRuntimeFlags & D3DRT_ONLY2FLOATSPERTEXTURE)
  1549. {
  1550. m_pv->dwVIDOut &= ~0xFFFF0000;
  1551. for (DWORD i=0; i < m_pv->nOutTexCoord; i++)
  1552. m_pv->dwTextureCoordSize[i] = 8;
  1553. m_pv->dwTextureCoordSizeTotal = m_pv->nTexCoord * 8;
  1554. }
  1555. }
  1556. }
  1557. if (m_pv->dwDeviceFlags & D3DDEV_DONOTSTRIPELEMENTS)
  1558. {
  1559. if (m_pv->nOutTexCoord == 0 && !(m_pv->dwFlags & D3DPV_VBCALL))
  1560. {
  1561. m_pv->dwTextureCoordSize[0] = 0;
  1562. m_pv->dwVIDOut |= (1 << D3DFVF_TEXCOUNT_SHIFT);
  1563. }
  1564. }
  1565. // Set up number of output texture coordinates
  1566. m_pv->dwVIDOut |= (m_pv->nOutTexCoord << D3DFVF_TEXCOUNT_SHIFT);
  1567. if ((m_pv->dwVIDOut & 0xFFFF0000) &&
  1568. (GetDDIType() < D3DDDITYPE_DX7))
  1569. {
  1570. D3D_THROW_FAIL("Texture format bits in the output FVF for this device should be 0");
  1571. }
  1572. if (!(m_pv->dwFlags & D3DPV_VBCALL))
  1573. {
  1574. m_pv->dwOutputSize = ComputeVertexSizeFVF(m_pv->dwVIDOut);
  1575. ComputeOutputVertexOffsets(m_pv);
  1576. }
  1577. // In case if COLORVERTEX is TRUE, the vertexAlpha could be overriden
  1578. // by vertex alpha
  1579. m_pv->lighting.alpha = (DWORD)m_pv->lighting.materialAlpha;
  1580. m_pv->lighting.alphaSpecular = (DWORD)m_pv->lighting.materialAlphaS;
  1581. this->dwFEFlags |= D3DFE_VERTEXBLEND_DIRTY | D3DFE_FRONTEND_DIRTY;
  1582. }
  1583. //-----------------------------------------------------------------------------
  1584. // Sets input vertex pointers and output offsets for legacy vertex shaders for
  1585. // the programmable vertex shaders
  1586. //
  1587. #undef DPF_MODNAME
  1588. #define DPF_MODNAME "CD3DHal::PrepareToDrawVVM"
  1589. void CD3DHal::PrepareToDrawVVM(UINT StartVertex)
  1590. {
  1591. if (m_dwRuntimeFlags & D3DRT_SHADERDIRTY)
  1592. {
  1593. SetupFVFDataVVM(this);
  1594. m_dwRuntimeFlags &= ~D3DRT_SHADERDIRTY;
  1595. m_pDDI->SetVertexShader(m_pv->dwVIDOut);
  1596. }
  1597. // Initialize vertex pointers used in the vertex loop
  1598. CVertexDesc* pVD = m_pv->VertexDesc;
  1599. for (DWORD i = m_pv->dwNumUsedVertexDescs; i; i--)
  1600. {
  1601. CVStream* pStream = pVD->pStream;
  1602. DWORD dwStride = pStream->m_dwStride;
  1603. pVD->pMemory = pStream->Data() + pVD->dwVertexOffset +
  1604. StartVertex * dwStride;
  1605. pVD->dwStride = dwStride;
  1606. pVD++;
  1607. }
  1608. }
  1609. //-----------------------------------------------------------------------------
  1610. // Sets input vertex pointers and output offsets for legacy vertex shaders
  1611. //
  1612. #undef DPF_MODNAME
  1613. #define DPF_MODNAME "CD3DHal::PrepareToDrawLegacy"
  1614. void CD3DHal::PrepareToDrawLegacy(UINT StartVertex)
  1615. {
  1616. // For legacy FVFs we draw using Stream[0]
  1617. m_pv->position.lpvData = m_pStream[0].Data() +
  1618. m_pStream[0].m_dwStride * StartVertex;
  1619. if (m_dwRuntimeFlags & D3DRT_SHADERDIRTY)
  1620. {
  1621. SetupFVFData();
  1622. m_pDDI->SetVertexShader(m_pv->dwVIDOut);
  1623. m_dwRuntimeFlags &= ~D3DRT_SHADERDIRTY;
  1624. }
  1625. }
  1626. //-----------------------------------------------------------------------------
  1627. // Sets input vertex pointers and output offsets for the fixed-function pipeline
  1628. // and non-legacy vertex declarations
  1629. //
  1630. #undef DPF_MODNAME
  1631. #define DPF_MODNAME "CD3DHal::PrepareToDraw"
  1632. void CD3DHal::PrepareToDraw(UINT StartVertex)
  1633. {
  1634. // Initialize strided data pointers used in the vertex loop
  1635. #if DBG
  1636. {
  1637. // Set all NULL pointers to check if they are initialized by the
  1638. // declaration
  1639. for (DWORD i=0; i < __NUMELEMENTS; i++)
  1640. {
  1641. m_pv->elements[i].lpvData = NULL;
  1642. }
  1643. }
  1644. #endif
  1645. CVertexDesc* pVD = m_pv->VertexDesc;
  1646. for (DWORD i = m_pv->dwNumUsedVertexDescs; i; i--)
  1647. {
  1648. CVStream* pStream = pVD->pStream;
  1649. DWORD dwStride = pStream->m_dwStride;
  1650. pVD->pElement->lpvData = pStream->Data() +
  1651. pVD->dwVertexOffset +
  1652. StartVertex * dwStride;
  1653. pVD->pElement->dwStride = dwStride;
  1654. pVD++;
  1655. }
  1656. if (m_dwRuntimeFlags & D3DRT_SHADERDIRTY)
  1657. {
  1658. SetupFVFData();
  1659. m_pDDI->SetVertexShader(m_pv->dwVIDOut);
  1660. m_dwRuntimeFlags &= ~D3DRT_SHADERDIRTY;
  1661. }
  1662. }
  1663. //-----------------------------------------------------------------------------
  1664. //
  1665. // Object implementations
  1666. //
  1667. //---------------------------------------------------------------------
  1668. const DWORD CVShader::FIXEDFUNCTION = 1;
  1669. const DWORD CVShader::SOFTWARE = 2;
  1670. void CheckForNull(LPVOID p, DWORD line, char* file)
  1671. {
  1672. if (p == NULL)
  1673. D3D_THROW_LINE(E_OUTOFMEMORY, "Not enough memory", line, file);
  1674. }
  1675. //-----------------------------------------------------------------------------
  1676. void Copy_FLOAT1(LPVOID pInputStream, UINT stride, UINT count,
  1677. VVM_WORD * pVertexRegister)
  1678. {
  1679. for (UINT i=0; i < count; i++)
  1680. {
  1681. pVertexRegister->x = *(float*)pInputStream;
  1682. pVertexRegister->y = 0;
  1683. pVertexRegister->z = 0;
  1684. pVertexRegister->w = 1;
  1685. pInputStream = (BYTE*)pInputStream + stride;
  1686. pVertexRegister++;
  1687. }
  1688. }
  1689. void Copy_FLOAT2(LPVOID pInputStream, UINT stride, UINT count,
  1690. VVM_WORD * pVertexRegister)
  1691. {
  1692. for (UINT i=0; i < count; i++)
  1693. {
  1694. pVertexRegister->x = ((float*)pInputStream)[0];
  1695. pVertexRegister->y = ((float*)pInputStream)[1];
  1696. pVertexRegister->z = 0;
  1697. pVertexRegister->w = 1;
  1698. pInputStream = (BYTE*)pInputStream + stride;
  1699. pVertexRegister++;
  1700. }
  1701. }
  1702. void Copy_FLOAT3(LPVOID pInputStream, UINT stride, UINT count,
  1703. VVM_WORD * pVertexRegister)
  1704. {
  1705. for (UINT i=0; i < count; i++)
  1706. {
  1707. pVertexRegister->x = ((float*)pInputStream)[0];
  1708. pVertexRegister->y = ((float*)pInputStream)[1];
  1709. pVertexRegister->z = ((float*)pInputStream)[2];
  1710. pVertexRegister->w = 1;
  1711. pInputStream = (BYTE*)pInputStream + stride;
  1712. pVertexRegister++;
  1713. }
  1714. }
  1715. void Copy_FLOAT4(LPVOID pInputStream, UINT stride, UINT count,
  1716. VVM_WORD * pVertexRegister)
  1717. {
  1718. for (UINT i=0; i < count; i++)
  1719. {
  1720. pVertexRegister->x = ((float*)pInputStream)[0];
  1721. pVertexRegister->y = ((float*)pInputStream)[1];
  1722. pVertexRegister->z = ((float*)pInputStream)[2];
  1723. pVertexRegister->w = ((float*)pInputStream)[3];
  1724. pInputStream = (BYTE*)pInputStream + stride;
  1725. pVertexRegister++;
  1726. }
  1727. }
  1728. void Copy_D3DCOLOR(LPVOID pInputStream, UINT stride, UINT count,
  1729. VVM_WORD * pVertexRegister)
  1730. {
  1731. const float scale = 1.0f/255.f;
  1732. for (UINT i=0; i < count; i++)
  1733. {
  1734. const DWORD v = ((DWORD*)pInputStream)[0];
  1735. pVertexRegister->x = scale * RGBA_GETRED(v);
  1736. pVertexRegister->y = scale * RGBA_GETGREEN(v);
  1737. pVertexRegister->z = scale * RGBA_GETBLUE(v);
  1738. pVertexRegister->w = scale * RGBA_GETALPHA(v);
  1739. pInputStream = (BYTE*)pInputStream + stride;
  1740. pVertexRegister++;
  1741. }
  1742. }
  1743. void Copy_UBYTE4(LPVOID pInputStream, UINT stride, UINT count,
  1744. VVM_WORD * pVertexRegister)
  1745. {
  1746. for (UINT i=0; i < count; i++)
  1747. {
  1748. const BYTE* v = (BYTE*)pInputStream;
  1749. pVertexRegister->x = v[0];
  1750. pVertexRegister->y = v[1];
  1751. pVertexRegister->z = v[2];
  1752. pVertexRegister->w = v[3];
  1753. pInputStream = (BYTE*)pInputStream + stride;
  1754. pVertexRegister++;
  1755. }
  1756. }
  1757. void Copy_SHORT2(LPVOID pInputStream, UINT stride, UINT count,
  1758. VVM_WORD * pVertexRegister)
  1759. {
  1760. for (UINT i=0; i < count; i++)
  1761. {
  1762. const short* v = (short*)pInputStream;
  1763. pVertexRegister->x = v[0];
  1764. pVertexRegister->y = v[1];
  1765. pVertexRegister->z = 0;
  1766. pVertexRegister->w = 1;
  1767. pInputStream = (BYTE*)pInputStream + stride;
  1768. pVertexRegister++;
  1769. }
  1770. }
  1771. void Copy_SHORT4(LPVOID pInputStream, UINT stride, UINT count,
  1772. VVM_WORD * pVertexRegister)
  1773. {
  1774. for (UINT i=0; i < count; i++)
  1775. {
  1776. const short* v = (short*)pInputStream;
  1777. pVertexRegister->x = v[0];
  1778. pVertexRegister->y = v[1];
  1779. pVertexRegister->z = v[2];
  1780. pVertexRegister->w = v[3];
  1781. pInputStream = (BYTE*)pInputStream + stride;
  1782. pVertexRegister++;
  1783. }
  1784. }
  1785. //-----------------------------------------------------------------------------
  1786. // Based on register and data type the function computes FVF dword and presence
  1787. // bits:
  1788. // - Bits in the dwFVF2 are used to detect that some field is not entered twice
  1789. // - pnFloats is used to compute number of floats with position
  1790. //
  1791. // Bits for dwFVF2. Order is the same as in the FVF!!!
  1792. //
  1793. static const DWORD __POSITION_PRESENT = 1 << 0;
  1794. static const DWORD __BLENDWEIGHT_PRESENT = 1 << 1;
  1795. static const DWORD __BLENDINDICES_PRESENT = 1 << 2;
  1796. static const DWORD __NORMAL_PRESENT = 1 << 3;
  1797. static const DWORD __PSIZE_PRESENT = 1 << 4;
  1798. static const DWORD __DIFFUSE_PRESENT = 1 << 5;
  1799. static const DWORD __SPECULAR_PRESENT = 1 << 6;
  1800. // __TEXTURE0_PRESENT must start from 8th bit
  1801. static const DWORD __TEXTURE0_PRESENT = 1 << 8;
  1802. static const DWORD __TEXTURE1_PRESENT = 1 << 9;
  1803. static const DWORD __TEXTURE2_PRESENT = 1 << 10;
  1804. static const DWORD __TEXTURE3_PRESENT = 1 << 11;
  1805. static const DWORD __TEXTURE4_PRESENT = 1 << 12;
  1806. static const DWORD __TEXTURE5_PRESENT = 1 << 13;
  1807. static const DWORD __TEXTURE6_PRESENT = 1 << 14;
  1808. static const DWORD __TEXTURE7_PRESENT = 1 << 15;
  1809. static const DWORD __POSITION2_PRESENT = 1 << 16;
  1810. static const DWORD __NORMAL2_PRESENT = 1 << 17;
  1811. // Check if any bit left from the CurrentBit is set in PresenceBits
  1812. // PresenceBits are updated by CurrentBit.
  1813. //
  1814. inline void CheckOrder(
  1815. DWORD* pPresenceBits, // Presence bits for the declaration
  1816. DWORD CurrentBit,
  1817. BOOL* pFlag, // Out of order flag for the declaration
  1818. char* s) // Name of the field
  1819. {
  1820. if (*pPresenceBits & CurrentBit)
  1821. {
  1822. char msg[80];
  1823. sprintf(msg, "%s specified twice in the declaration", s);
  1824. D3D_THROW_FAIL(msg);
  1825. }
  1826. if (*pPresenceBits & ~(CurrentBit | (CurrentBit-1)))
  1827. {
  1828. *pFlag = FALSE;
  1829. }
  1830. *pPresenceBits |= CurrentBit;
  1831. }
  1832. void UpdateFVF(DWORD dwRegister, DWORD dwDataType,
  1833. DWORD* pdwFVF, // FVF for the current declaration
  1834. DWORD* pdwFVF2, // Presence bits for the current stream
  1835. DWORD* pnFloats,
  1836. BOOL* pbLegacyFVF)
  1837. {
  1838. switch (dwRegister)
  1839. {
  1840. case D3DVSDE_POSITION:
  1841. if (dwDataType != D3DVSDT_FLOAT3)
  1842. D3D_THROW_FAIL("Position register must be FLOAT3 for fixed-function pipeline");
  1843. CheckOrder(pdwFVF2, __POSITION_PRESENT, pbLegacyFVF, "Position");
  1844. *pdwFVF |= D3DFVF_XYZ;
  1845. break;
  1846. case D3DVSDE_POSITION2:
  1847. if (dwDataType != D3DVSDT_FLOAT3)
  1848. D3D_THROW_FAIL("Position2 register must be FLOAT3 for fixed-function pipeline");
  1849. CheckOrder(pdwFVF2, __POSITION2_PRESENT, pbLegacyFVF, "Position2");
  1850. break;
  1851. case D3DVSDE_BLENDWEIGHT:
  1852. {
  1853. CheckOrder(pdwFVF2, __BLENDWEIGHT_PRESENT, pbLegacyFVF, "Blend weight");
  1854. switch (dwDataType)
  1855. {
  1856. case D3DVSDT_FLOAT1:
  1857. (*pnFloats)++;
  1858. break;
  1859. case D3DVSDT_FLOAT2:
  1860. (*pnFloats) += 2;
  1861. break;
  1862. case D3DVSDT_FLOAT3:
  1863. (*pnFloats) += 3;
  1864. break;
  1865. case D3DVSDT_FLOAT4:
  1866. (*pnFloats) += 4;
  1867. break;
  1868. default:
  1869. D3D_THROW_FAIL("Invalid data type set for vertex blends");
  1870. break;
  1871. }
  1872. break;
  1873. }
  1874. case D3DVSDE_NORMAL:
  1875. CheckOrder(pdwFVF2, __NORMAL_PRESENT, pbLegacyFVF, "Normal");
  1876. if (dwDataType != D3DVSDT_FLOAT3)
  1877. D3D_THROW_FAIL("Normal register must be FLOAT3 for fixed-function pipeline");
  1878. *pdwFVF |= D3DFVF_NORMAL;
  1879. break;
  1880. case D3DVSDE_NORMAL2:
  1881. CheckOrder(pdwFVF2, __NORMAL2_PRESENT, pbLegacyFVF, "Normal2");
  1882. if (dwDataType != D3DVSDT_FLOAT3)
  1883. D3D_THROW_FAIL("Normal2 register must be FLOAT3 for fixed-function pipeline");
  1884. break;
  1885. case D3DVSDE_PSIZE:
  1886. CheckOrder(pdwFVF2, __PSIZE_PRESENT, pbLegacyFVF, "Point size");
  1887. if (dwDataType != D3DVSDT_FLOAT1)
  1888. D3D_THROW_FAIL("Point size register must be FLOAT1 for fixed-function pipeline");
  1889. *pdwFVF |= D3DFVF_PSIZE;
  1890. break;
  1891. case D3DVSDE_DIFFUSE:
  1892. CheckOrder(pdwFVF2, __DIFFUSE_PRESENT, pbLegacyFVF, "Diffuse");
  1893. if (dwDataType != D3DVSDT_D3DCOLOR)
  1894. D3D_THROW_FAIL("Diffuse register must be D3DCOLOR for fixed-function pipeline");
  1895. *pdwFVF |= D3DFVF_DIFFUSE;
  1896. break;
  1897. case D3DVSDE_SPECULAR:
  1898. CheckOrder(pdwFVF2, __SPECULAR_PRESENT, pbLegacyFVF, "Specular");
  1899. if (dwDataType != D3DVSDT_D3DCOLOR)
  1900. D3D_THROW_FAIL("Specular register must be D3DCOLOR for fixed-function pipeline");
  1901. *pdwFVF |= D3DFVF_SPECULAR;
  1902. break;
  1903. case D3DVSDE_BLENDINDICES:
  1904. CheckOrder(pdwFVF2, __BLENDINDICES_PRESENT, pbLegacyFVF, "Blend indices");
  1905. if (dwDataType != D3DVSDT_UBYTE4)
  1906. D3D_THROW_FAIL("Blend indices register must be D3DVSDT_UBYTE4 for fixed-function pipeline");
  1907. // Update number of floats after position
  1908. (*pnFloats)++;
  1909. break;
  1910. case D3DVSDE_TEXCOORD0:
  1911. case D3DVSDE_TEXCOORD1:
  1912. case D3DVSDE_TEXCOORD2:
  1913. case D3DVSDE_TEXCOORD3:
  1914. case D3DVSDE_TEXCOORD4:
  1915. case D3DVSDE_TEXCOORD5:
  1916. case D3DVSDE_TEXCOORD6:
  1917. case D3DVSDE_TEXCOORD7:
  1918. {
  1919. DWORD dwTextureIndex = dwRegister - D3DVSDE_TEXCOORD0;
  1920. DWORD dwBit = __TEXTURE0_PRESENT << dwTextureIndex;
  1921. CheckOrder(pdwFVF2, dwBit, pbLegacyFVF, "Texture");
  1922. switch (dwDataType)
  1923. {
  1924. case D3DVSDT_FLOAT1:
  1925. *pdwFVF |= D3DFVF_TEXCOORDSIZE1(dwTextureIndex);
  1926. break;
  1927. case D3DVSDT_FLOAT2:
  1928. *pdwFVF |= D3DFVF_TEXCOORDSIZE2(dwTextureIndex);
  1929. break;
  1930. case D3DVSDT_FLOAT3:
  1931. *pdwFVF |= D3DFVF_TEXCOORDSIZE3(dwTextureIndex);
  1932. break;
  1933. case D3DVSDT_FLOAT4:
  1934. *pdwFVF |= D3DFVF_TEXCOORDSIZE4(dwTextureIndex);
  1935. break;
  1936. default:
  1937. D3D_THROW_FAIL("Invalid data type set for texture register");
  1938. break;
  1939. }
  1940. break;
  1941. }
  1942. default:
  1943. D3D_THROW_FAIL("Invalid register set for fixed-function pipeline");
  1944. break;
  1945. }
  1946. }
  1947. //-----------------------------------------------------------------------------
  1948. void CVStreamDecl::Parse(CD3DBase* pDevice,
  1949. DWORD CONST ** ppToken, BOOL bFixedFunction,
  1950. DWORD* pdwFVF, DWORD* pdwFVF2, DWORD* pnFloats,
  1951. BOOL* pbLegacyFVF, UINT usage, BOOL bTessStream)
  1952. {
  1953. CONST DWORD* pToken = *ppToken;
  1954. // Used to compute stream stride and offset in bytes for each stream element
  1955. DWORD dwCurrentOffset = 0;
  1956. // FVF and FVF2 for this stream only. Used to check if data in the stream
  1957. // form a FVF subset
  1958. DWORD dwFVF2 = 0;
  1959. DWORD dwFVF = 0;
  1960. DWORD nFloats = 0;
  1961. // Set to TRUE, if data in the stream is an FVF subset
  1962. BOOL bFVFSubset = TRUE;
  1963. while (TRUE)
  1964. {
  1965. DWORD dwToken = *pToken++;
  1966. const DWORD dwTokenType = D3DVSD_GETTOKENTYPE(dwToken);
  1967. switch (dwTokenType)
  1968. {
  1969. case D3DVSD_TOKEN_NOP: break;
  1970. case D3DVSD_TOKEN_TESSELLATOR:
  1971. {
  1972. *pbLegacyFVF = FALSE;
  1973. bFVFSubset = FALSE;
  1974. const DWORD dwDataType = D3DVSD_GETDATATYPE(dwToken);
  1975. switch (dwDataType)
  1976. {
  1977. case D3DVSDT_FLOAT2:
  1978. case D3DVSDT_FLOAT3:
  1979. break;
  1980. }
  1981. break;
  1982. }
  1983. case D3DVSD_TOKEN_STREAMDATA:
  1984. {
  1985. switch (D3DVSD_GETDATALOADTYPE(dwToken))
  1986. {
  1987. case D3DVSD_LOADREGISTER:
  1988. {
  1989. #if DBG
  1990. if (m_dwNumElements >= __NUMELEMENTS)
  1991. {
  1992. D3D_ERR("D3DVSD_TOKEN_STREAMDATA:");
  1993. D3D_ERR(" Number of vertex elements in a stream is greater than max supported");
  1994. D3D_ERR(" Max supported number of elements is %d", __NUMELEMENTS);
  1995. D3D_THROW_FAIL("");
  1996. }
  1997. #endif
  1998. CVElement* pElement = &m_Elements[m_dwNumElements++];
  1999. const DWORD dwDataType = D3DVSD_GETDATATYPE(dwToken);
  2000. const DWORD dwRegister = D3DVSD_GETVERTEXREG(dwToken);
  2001. pElement->m_dwOffset = dwCurrentOffset;
  2002. pElement->m_dwRegister = dwRegister;
  2003. pElement->m_dwDataType = dwDataType;
  2004. switch (dwDataType)
  2005. {
  2006. case D3DVSDT_FLOAT1:
  2007. dwCurrentOffset += sizeof(float);
  2008. pElement->m_pfnCopy = (LPVOID)Copy_FLOAT1;
  2009. break;
  2010. case D3DVSDT_FLOAT2:
  2011. dwCurrentOffset += sizeof(float) * 2;
  2012. pElement->m_pfnCopy = (LPVOID)Copy_FLOAT2;
  2013. break;
  2014. case D3DVSDT_FLOAT3:
  2015. dwCurrentOffset += sizeof(float) * 3;
  2016. pElement->m_pfnCopy = (LPVOID)Copy_FLOAT3;
  2017. break;
  2018. case D3DVSDT_FLOAT4:
  2019. dwCurrentOffset += sizeof(float) * 4;
  2020. pElement->m_pfnCopy = (LPVOID)Copy_FLOAT4;
  2021. break;
  2022. case D3DVSDT_D3DCOLOR:
  2023. dwCurrentOffset += sizeof(DWORD);
  2024. pElement->m_pfnCopy = (LPVOID)Copy_D3DCOLOR;
  2025. break;
  2026. case D3DVSDT_UBYTE4:
  2027. #if DBG
  2028. // Do not fail when software processing will be used
  2029. if (pDevice->GetD3DCaps()->VertexProcessingCaps & D3DVTXPCAPS_NO_VSDT_UBYTE4 &&
  2030. !((usage & D3DUSAGE_SOFTWAREPROCESSING &&
  2031. pDevice->BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING) ||
  2032. (pDevice->BehaviorFlags() & D3DCREATE_SOFTWARE_VERTEXPROCESSING)))
  2033. {
  2034. D3D_THROW_FAIL("Device does not support UBYTE4 data type");
  2035. }
  2036. #endif // DBG
  2037. dwCurrentOffset += sizeof(DWORD);
  2038. pElement->m_pfnCopy = (LPVOID)Copy_UBYTE4;
  2039. break;
  2040. case D3DVSDT_SHORT2:
  2041. dwCurrentOffset += sizeof(short) * 2;
  2042. pElement->m_pfnCopy = (LPVOID)Copy_SHORT2;
  2043. break;
  2044. case D3DVSDT_SHORT4:
  2045. dwCurrentOffset += sizeof(short) * 4;
  2046. pElement->m_pfnCopy = (LPVOID)Copy_SHORT4;
  2047. break;
  2048. default:
  2049. D3D_ERR("D3DVSD_TOKEN_STREAMDATA: Invalid element data type: %10x", dwToken);
  2050. D3D_THROW_FAIL("");
  2051. }
  2052. // Compute input FVF for fixed-function pipeline
  2053. if (bFixedFunction)
  2054. {
  2055. // Update FVF for the declaration
  2056. UpdateFVF(dwRegister, dwDataType, pdwFVF, pdwFVF2,
  2057. pnFloats, pbLegacyFVF);
  2058. // Update FVF for the stream
  2059. UpdateFVF(dwRegister, dwDataType, &dwFVF, &dwFVF2,
  2060. &nFloats, &bFVFSubset);
  2061. }
  2062. else
  2063. if (dwRegister >= D3DVS_INPUTREG_MAX_V1_1)
  2064. D3D_THROW_FAIL("D3DVSD_TOKEN_STREAMDATA: Invalid register number");
  2065. break;
  2066. }
  2067. case D3DVSD_SKIP:
  2068. {
  2069. if (bFixedFunction)
  2070. {
  2071. D3D_THROW_FAIL("D3DVSD_SKIP is not allowed for fixed-function pipeline");
  2072. }
  2073. const DWORD dwCount = D3DVSD_GETSKIPCOUNT(dwToken);
  2074. dwCurrentOffset += dwCount * sizeof(DWORD);
  2075. break;
  2076. }
  2077. default:
  2078. D3D_ERR("Invalid data load type: %10x", dwToken);
  2079. D3D_THROW_FAIL("");
  2080. }
  2081. break;
  2082. }
  2083. default:
  2084. {
  2085. *ppToken = pToken - 1;
  2086. m_dwStride = dwCurrentOffset;
  2087. goto l_exit;
  2088. }
  2089. } // switch
  2090. } // while
  2091. l_exit:
  2092. if (bFixedFunction && !bTessStream)
  2093. {
  2094. #if DBG
  2095. m_dwFVF = dwFVF;
  2096. #endif
  2097. if (!bFVFSubset)
  2098. {
  2099. D3D_THROW_FAIL("For fixed-function pipeline each stream has to be an FVF subset");
  2100. }
  2101. if (dwFVF2 & (__POSITION2_PRESENT | __NORMAL2_PRESENT |
  2102. __PSIZE_PRESENT | __BLENDINDICES_PRESENT))
  2103. {
  2104. *pbLegacyFVF = FALSE;
  2105. }
  2106. }
  2107. }
  2108. //-----------------------------------------------------------------------------
  2109. CVDeclaration::CVDeclaration(DWORD dwNumStreams)
  2110. {
  2111. m_pConstants = NULL;
  2112. m_pConstantsTail = NULL;
  2113. m_pActiveStreams = NULL;
  2114. m_pActiveStreamsTail = NULL;
  2115. m_dwInputFVF = 0;
  2116. m_bLegacyFVF = TRUE;
  2117. m_dwNumStreams = dwNumStreams;
  2118. m_bStreamTessPresent = FALSE;
  2119. }
  2120. //-----------------------------------------------------------------------------
  2121. CVDeclaration::~CVDeclaration()
  2122. {
  2123. delete m_pActiveStreams;
  2124. delete m_pConstants;
  2125. }
  2126. //-----------------------------------------------------------------------------
  2127. void CVDeclaration::Parse(CD3DBase* pDevice, CONST DWORD* pTok, BOOL bFixedFunction,
  2128. DWORD* pDeclSize, UINT usage)
  2129. {
  2130. DWORD dwFVF = 0; // FVF for fixed-function pipeline
  2131. DWORD dwFVF2 = 0; // Texture presence bits (8 bits)
  2132. DWORD nFloats = 0; // Number of floats after position
  2133. DWORD dwStreamPresent = 0; // Bit is set if a stream is used
  2134. m_bLegacyFVF = TRUE;
  2135. CONST DWORD* pToken = pTok;
  2136. while (TRUE)
  2137. {
  2138. DWORD dwToken = *pToken++;
  2139. const DWORD dwTokenType = D3DVSD_GETTOKENTYPE(dwToken);
  2140. switch (dwTokenType)
  2141. {
  2142. case D3DVSD_TOKEN_NOP: break;
  2143. case D3DVSD_TOKEN_STREAM:
  2144. {
  2145. CVStreamDecl StreamTess;
  2146. if( D3DVSD_ISSTREAMTESS(dwToken) )
  2147. {
  2148. m_bLegacyFVF = FALSE;
  2149. if( m_bStreamTessPresent )
  2150. {
  2151. D3D_THROW(D3DERR_INVALIDCALL, "Tesselator Stream has already been defined in the declaration");
  2152. }
  2153. m_bStreamTessPresent = TRUE;
  2154. //
  2155. // For now simply skip over the Tess tokens in the
  2156. // Runtime.
  2157. StreamTess.Parse(pDevice, &pToken, bFixedFunction, &dwFVF, &dwFVF2,
  2158. &nFloats, &m_bLegacyFVF, usage, TRUE);
  2159. }
  2160. else
  2161. {
  2162. DWORD dwStream = D3DVSD_GETSTREAMNUMBER(dwToken);
  2163. if (dwStream >= m_dwNumStreams)
  2164. {
  2165. D3D_THROW_FAIL("Stream number is too big");
  2166. }
  2167. if (dwStreamPresent & (1 << dwStream))
  2168. {
  2169. D3D_THROW(D3DERR_INVALIDCALL, "Stream is already defined"
  2170. "in the declaration");
  2171. }
  2172. dwStreamPresent |= 1 << dwStream;
  2173. // There are more than one stream present, so cant be
  2174. // handled by legacy FVF.
  2175. if( dwStreamPresent & (dwStreamPresent - 1) )
  2176. m_bLegacyFVF = FALSE;
  2177. CVStreamDecl* pStream = new CVStreamDecl;
  2178. if (pStream == NULL)
  2179. {
  2180. D3D_THROW(E_OUTOFMEMORY, "Not enough memory");
  2181. }
  2182. try
  2183. {
  2184. pStream->Parse(pDevice, &pToken, bFixedFunction, &dwFVF, &dwFVF2,
  2185. &nFloats, &m_bLegacyFVF, usage);
  2186. pStream->m_dwStreamIndex = dwStream;
  2187. if (m_pActiveStreams == NULL)
  2188. {
  2189. m_pActiveStreams = pStream;
  2190. m_pActiveStreamsTail = pStream;
  2191. }
  2192. else
  2193. {
  2194. m_pActiveStreamsTail->Append(pStream);
  2195. m_pActiveStreamsTail = pStream;
  2196. }
  2197. }
  2198. catch (HRESULT e)
  2199. {
  2200. delete pStream;
  2201. throw e;
  2202. }
  2203. }
  2204. break;
  2205. }
  2206. case D3DVSD_TOKEN_STREAMDATA:
  2207. {
  2208. D3D_THROW_FAIL("D3DVSD_TOKEN_STREAMDATA could only be used after D3DVSD_TOKEN_STREAM");
  2209. }
  2210. case D3DVSD_TOKEN_CONSTMEM:
  2211. {
  2212. CVConstantData * cd = new CVConstantData;
  2213. CheckForNull(cd, __LINE__, __FILE__);
  2214. cd->m_dwCount = D3DVSD_GETCONSTCOUNT(dwToken);
  2215. cd->m_dwAddress = D3DVSD_GETCONSTADDRESS(dwToken);
  2216. UINT ValidationCount;
  2217. if (usage & D3DUSAGE_SOFTWAREPROCESSING)
  2218. ValidationCount = D3DVS_CONSTREG_MAX_V1_1;
  2219. else
  2220. ValidationCount = pDevice->GetD3DCaps()->MaxVertexShaderConst;
  2221. if ((cd->m_dwCount + cd->m_dwAddress) > ValidationCount)
  2222. D3D_THROW_FAIL("D3DVSD_TOKEN_CONSTMEM writes outside constant memory");
  2223. const DWORD dwSize = cd->m_dwCount << 2; // number of DWORDs
  2224. cd->m_pData = new DWORD[dwSize];
  2225. CheckForNull(cd->m_pData, __LINE__, __FILE__);
  2226. memcpy(cd->m_pData, pToken, dwSize << 2);
  2227. if (m_pConstants == NULL)
  2228. {
  2229. m_pConstants = cd;
  2230. m_pConstantsTail = cd;
  2231. }
  2232. else
  2233. {
  2234. m_pConstantsTail->Append(cd);
  2235. m_pConstantsTail = cd;
  2236. }
  2237. pToken += dwSize;
  2238. break;
  2239. }
  2240. case D3DVSD_TOKEN_EXT:
  2241. {
  2242. // Skip extension info
  2243. DWORD dwCount = D3DVSD_GETEXTCOUNT(dwToken);
  2244. pToken += dwCount;
  2245. break;
  2246. }
  2247. case D3DVSD_TOKEN_END:
  2248. {
  2249. goto l_End;
  2250. }
  2251. default:
  2252. {
  2253. D3D_ERR("Invalid declaration token: %10x", dwToken);
  2254. D3D_THROW_FAIL("");
  2255. }
  2256. }
  2257. }
  2258. l_End:
  2259. // Validate input for the fixed-function pipeline
  2260. if (bFixedFunction && !m_bStreamTessPresent)
  2261. {
  2262. m_dwInputFVF = dwFVF & 0xFFFF0FFF; // Remove float count
  2263. switch (nFloats)
  2264. {
  2265. case 0: m_dwInputFVF |= D3DFVF_XYZ; break;
  2266. case 1: m_dwInputFVF |= D3DFVF_XYZB1; break;
  2267. case 2: m_dwInputFVF |= D3DFVF_XYZB2; break;
  2268. case 3: m_dwInputFVF |= D3DFVF_XYZB3; break;
  2269. case 4: m_dwInputFVF |= D3DFVF_XYZB4; break;
  2270. case 5: m_dwInputFVF |= D3DFVF_XYZB5; break;
  2271. default:
  2272. D3D_THROW_FAIL("Too many floats after position");
  2273. }
  2274. // Compute number of texture coordinates
  2275. DWORD nTexCoord = 0;
  2276. DWORD dwTexturePresenceBits = (dwFVF2 >> 8) & 0xFF;
  2277. while (dwTexturePresenceBits & 1)
  2278. {
  2279. dwTexturePresenceBits >>= 1;
  2280. nTexCoord++;
  2281. }
  2282. // There should be no gaps in texture coordinates
  2283. if (dwTexturePresenceBits)
  2284. D3D_THROW_FAIL("Texture coordinates should have no gaps");
  2285. m_dwInputFVF |= nTexCoord << D3DFVF_TEXCOUNT_SHIFT;
  2286. // Position must be set
  2287. if ((dwFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ)
  2288. D3D_THROW_FAIL("Position register must be set");
  2289. }
  2290. if (pDeclSize != NULL)
  2291. {
  2292. *pDeclSize = (DWORD) (pToken - pTok) << 2;
  2293. }
  2294. }
  2295. //---------------------------------------------------------------------
  2296. CVStream::~CVStream()
  2297. {
  2298. if (m_pVB)
  2299. m_pVB->DecrementUseCount();
  2300. }
  2301. //---------------------------------------------------------------------
  2302. CVIndexStream::~CVIndexStream()
  2303. {
  2304. if (m_pVBI)
  2305. m_pVBI->DecrementUseCount();
  2306. }
  2307. //---------------------------------------------------------------------
  2308. DWORD g_PrimToVerCount[7][2] =
  2309. {
  2310. {0, 0}, // Illegal
  2311. {1, 0}, // D3DPT_POINTLIST = 1,
  2312. {2, 0}, // D3DPT_LINELIST = 2,
  2313. {1, 1}, // D3DPT_LINESTRIP = 3,
  2314. {3, 0}, // D3DPT_TRIANGLELIST = 4,
  2315. {1, 2}, // D3DPT_TRIANGLESTRIP = 5,
  2316. {1, 2}, // D3DPT_TRIANGLEFAN = 6,
  2317. };
  2318. //-----------------------------------------------------------------------------
  2319. HRESULT D3DFE_PVFUNCSI::CreateShader(CVElement* pElements, DWORD dwNumElements,
  2320. DWORD* pdwShaderCode, DWORD dwOutputFVF,
  2321. CPSGPShader** ppPSGPShader)
  2322. {
  2323. *ppPSGPShader = NULL;
  2324. try
  2325. {
  2326. *ppPSGPShader = m_VertexVM.CreateShader(pElements, dwNumElements,
  2327. pdwShaderCode);
  2328. if (*ppPSGPShader == NULL)
  2329. return D3DERR_INVALIDCALL;
  2330. }
  2331. D3D_CATCH;
  2332. return D3D_OK;
  2333. }
  2334. //-----------------------------------------------------------------------------
  2335. HRESULT D3DFE_PVFUNCSI::SetActiveShader(CPSGPShader* pPSGPShader)
  2336. {
  2337. return m_VertexVM.SetActiveShader((CVShaderCode*)pPSGPShader);
  2338. }
  2339. //-----------------------------------------------------------------------------
  2340. // Load vertex shader constants
  2341. HRESULT
  2342. D3DFE_PVFUNCSI::LoadShaderConstants(DWORD start, DWORD count, LPVOID buffer)
  2343. {
  2344. return m_VertexVM.SetData(D3DSPR_CONST, start, count, buffer);
  2345. }
  2346. //-----------------------------------------------------------------------------
  2347. // Get vertex shader constants
  2348. HRESULT
  2349. D3DFE_PVFUNCSI::GetShaderConstants(DWORD start, DWORD count, LPVOID buffer)
  2350. {
  2351. return m_VertexVM.GetData(D3DSPR_CONST, start, count, buffer);
  2352. }
  2353. //-----------------------------------------------------------------------------
  2354. #undef DPF_MODNAME
  2355. #define DPF_MODNAME "CD3DHal::GetVertexShaderConstant"
  2356. HRESULT D3DAPI
  2357. CD3DHal::GetVertexShaderConstant(DWORD Register, LPVOID pData, DWORD count)
  2358. {
  2359. API_ENTER(this);
  2360. #if DBG
  2361. // Validate Parameters
  2362. if (!VALID_WRITEPTR(pData, 4 * sizeof(DWORD) * count))
  2363. {
  2364. D3D_ERR("Invalid constant data pointer. GetVertexShaderConstant failed.");
  2365. return D3DERR_INVALIDCALL;
  2366. }
  2367. if ((GetD3DCaps()->VertexShaderVersion == D3DVS_VERSION(0,0)) &&
  2368. (BehaviorFlags() & (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE)))
  2369. {
  2370. D3D_ERR("No programmable vertex shaders are supported by this device. GetVertexShaderConstant failed.");
  2371. return D3DERR_INVALIDCALL;
  2372. }
  2373. UINT ValidationCount;
  2374. if (BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING)
  2375. ValidationCount = max(m_MaxVertexShaderConst, D3DVS_CONSTREG_MAX_V1_1);
  2376. else
  2377. if (BehaviorFlags() & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
  2378. ValidationCount = D3DVS_CONSTREG_MAX_V1_1;
  2379. else
  2380. ValidationCount = m_MaxVertexShaderConst;
  2381. if((Register + count) > ValidationCount)
  2382. {
  2383. D3D_ERR("Not that many constant registers in the vertex machine. GetVertexShaderConstant failed.");
  2384. return D3DERR_INVALIDCALL;
  2385. }
  2386. #endif
  2387. HRESULT hr;
  2388. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING ||
  2389. ((count + Register) <= D3DVS_CONSTREG_MAX_V1_1))
  2390. {
  2391. // For software vertex processing we store constant registers in PSGP if
  2392. // possible
  2393. return m_pv->pGeometryFuncs->GetShaderConstants(Register, count,
  2394. const_cast<VOID*>(pData));
  2395. }
  2396. else
  2397. {
  2398. if (Register >= D3DVS_CONSTREG_MAX_V1_1)
  2399. {
  2400. // When all modified registers are above software limit, we use Microsoft
  2401. // internal array
  2402. hr = GeometryFuncsGuaranteed->GetShaderConstants(Register, count,
  2403. const_cast<VOID*>(pData));
  2404. }
  2405. else
  2406. {
  2407. // Part of constant data is taken from PSGP array and part from
  2408. // Microsoft's array
  2409. UINT FirstCount = D3DVS_CONSTREG_MAX_V1_1 - Register;
  2410. hr = m_pv->pGeometryFuncs->GetShaderConstants(Register, FirstCount,
  2411. const_cast<VOID*>(pData));
  2412. if (FAILED(hr))
  2413. {
  2414. return hr;
  2415. }
  2416. return GeometryFuncsGuaranteed->GetShaderConstants(D3DVS_CONSTREG_MAX_V1_1,
  2417. Register + count - D3DVS_CONSTREG_MAX_V1_1,
  2418. &((DWORD*)pData)[FirstCount*4]);
  2419. }
  2420. return hr;
  2421. }
  2422. return m_pv->pGeometryFuncs->GetShaderConstants(Register, count, pData);
  2423. }
  2424. //-----------------------------------------------------------------------------
  2425. #undef DPF_MODNAME
  2426. #define DPF_MODNAME "CD3DHal::GetVertexShader"
  2427. HRESULT D3DAPI
  2428. CD3DHal::GetVertexShader(LPDWORD pdwHandle)
  2429. {
  2430. API_ENTER(this); // Takes D3D Lock if necessary
  2431. HRESULT ret = D3D_OK;
  2432. #if DBG
  2433. // Validate Parameters
  2434. if (!VALID_WRITEPTR(pdwHandle, sizeof(DWORD)))
  2435. {
  2436. D3D_ERR("Invalid handle pointer. GetVertexShader failed.");
  2437. return D3DERR_INVALIDCALL;
  2438. }
  2439. #endif
  2440. *pdwHandle = m_dwCurrentShaderHandle;
  2441. return ret;
  2442. }
  2443. //-----------------------------------------------------------------------------
  2444. #undef DPF_MODNAME
  2445. #define DPF_MODNAME "CD3DHal::GetPixelShader"
  2446. HRESULT D3DAPI
  2447. CD3DHal::GetPixelShader(LPDWORD pdwHandle)
  2448. {
  2449. API_ENTER(this); // Takes D3D Lock if necessary
  2450. HRESULT ret = D3D_OK;
  2451. #if DBG
  2452. // Validate Parameters
  2453. if (!VALID_WRITEPTR(pdwHandle, sizeof(DWORD)))
  2454. {
  2455. D3D_ERR("Invalid handle pointer. GetPixelShader failed.");
  2456. return D3DERR_INVALIDCALL;
  2457. }
  2458. #endif
  2459. *pdwHandle = m_dwCurrentPixelShaderHandle;
  2460. return ret;
  2461. }
  2462. #if DBG
  2463. //-----------------------------------------------------------------------------
  2464. #undef DPF_MODNAME
  2465. #define DPF_MODNAME "CD3DHal::ValidateRTPatch"
  2466. void CD3DHal::ValidateRTPatch()
  2467. {
  2468. if (D3DVSD_ISLEGACY(m_dwCurrentShaderHandle))
  2469. {
  2470. if (m_pStream[0].m_pVB == 0)
  2471. {
  2472. D3D_THROW_FAIL("Draw[RT]Patch should have streams set");
  2473. }
  2474. if ((m_pStream[0].m_pVB->GetBufferDesc()->Usage & D3DUSAGE_RTPATCHES) == 0)
  2475. {
  2476. D3D_THROW_FAIL("Vertex buffers used for rendering RT-Patches should have D3DUSAGE_RTPATCHES set");
  2477. }
  2478. }
  2479. else
  2480. {
  2481. CVStreamDecl* pStream;
  2482. pStream = m_pCurrentShader->m_Declaration.m_pActiveStreams;
  2483. while(pStream)
  2484. {
  2485. UINT index = pStream->m_dwStreamIndex;
  2486. CVStream* pDeviceStream = &m_pStream[index];
  2487. if (pDeviceStream->m_pVB == 0)
  2488. {
  2489. D3D_THROW_FAIL("Draw[RT]Patch should have streams set");
  2490. }
  2491. if ((pDeviceStream->m_pVB->GetBufferDesc()->Usage & D3DUSAGE_RTPATCHES) == 0)
  2492. {
  2493. D3D_THROW_FAIL("Vertex buffers used for rendering RT-Patches should have D3DUSAGE_RTPATCHES set");
  2494. }
  2495. pStream = (CVStreamDecl*)pStream->m_pNext;
  2496. }
  2497. }
  2498. }
  2499. #endif // DBG