Leaked source code of windows server 2003
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.

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