ProfileChecker.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. //-----------------------------------------------------------------------------
  2. // ProfileChecker.cpp
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. #include "stdafx.h"
  8. #include "ProfileChecker.h"
  9. #include "ProfileCapabilities.h"
  10. using namespace XnaGraphicsProfileChecker;
  11. // Constructor performs the caps check.
  12. ProfileChecker::ProfileChecker(GraphicsProfile profile)
  13. {
  14. errors = gcnew List<String^>();
  15. IDirect3D9* pD3D = Direct3DCreate9(D3D_SDK_VERSION);
  16. if (pD3D)
  17. {
  18. try
  19. {
  20. CheckProfileSupport(profile, pD3D);
  21. }
  22. finally
  23. {
  24. pD3D->Release();
  25. }
  26. }
  27. else
  28. {
  29. errors->Add("Direct3DCreate9 failed");
  30. }
  31. }
  32. // D3D query APIs need an adapter format, but this isn't actually relevant to what they
  33. // return on any modern hardware, so we just pass this default to keep the API happy.
  34. #define IRRELEVANT_ADAPTER_FORMAT D3DFMT_X8R8G8B8
  35. // Helper for checking a limit such as a max size.
  36. #define CHECK_LIMIT(field, limit) \
  37. { \
  38. if (caps.field < unsigned(limit)) \
  39. { \
  40. errors->Add(String::Format("{0} = {1}", #field, caps.field)); \
  41. } \
  42. }
  43. // Helper for making sure a specific caps bit is set.
  44. #define ENSURE_CAP(field, bit) \
  45. { \
  46. if (!(caps.field & bit)) \
  47. { \
  48. errors->Add(String::Format("No {0}.{1}", #field, #bit)); \
  49. } \
  50. }
  51. // Helper for making sure a specific caps bit is not set.
  52. #define REJECT_CAP(field, bit) \
  53. { \
  54. if (caps.field & bit) \
  55. { \
  56. errors->Add(String::Format("Unwanted {0}.{1}", #field, #bit)); \
  57. } \
  58. }
  59. void ProfileChecker::CheckProfileSupport(GraphicsProfile graphicsProfile, IDirect3D9* pD3D)
  60. {
  61. // Look up what caps are required by the requested profile.
  62. ProfileCapabilities^ profileCapabilities = gcnew ProfileCapabilities(graphicsProfile);
  63. // Query the D3D caps.
  64. D3DCAPS9 caps;
  65. if (FAILED(pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps)))
  66. {
  67. errors->Add("GetDeviceCaps failed");
  68. return;
  69. }
  70. // If the hardware lacks vertex processing, we fall back on
  71. // software vertex shading, so must override the relevant hardware caps.
  72. if (!(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT))
  73. {
  74. caps.VertexShaderVersion = D3DVS_VERSION(2, 0);
  75. caps.DeclTypes = D3DDTCAPS_UBYTE4 |
  76. D3DDTCAPS_UBYTE4N |
  77. D3DDTCAPS_SHORT2N |
  78. D3DDTCAPS_SHORT4N;
  79. }
  80. // Check the shader version.
  81. if ((caps.VertexShaderVersion & 0xFFFF) < profileCapabilities->VertexShaderVersion)
  82. {
  83. errors->Add("VertexShaderVersion = " + FormatShaderVersion(caps.VertexShaderVersion));
  84. }
  85. if ((caps.PixelShaderVersion & 0xFFFF) < profileCapabilities->PixelShaderVersion)
  86. {
  87. errors->Add("PixelShaderVersion = " + FormatShaderVersion(caps.PixelShaderVersion));
  88. }
  89. // Check basic rendering caps.
  90. CHECK_LIMIT(MaxPrimitiveCount, profileCapabilities->MaxPrimitiveCount);
  91. CHECK_LIMIT(MaxStreams, profileCapabilities->MaxVertexStreams);
  92. CHECK_LIMIT(MaxStreamStride, profileCapabilities->MaxStreamStride);
  93. CHECK_LIMIT(MaxVertexIndex, profileCapabilities->IndexElementSize32 ? 16777214 : 65534);
  94. ENSURE_CAP(DevCaps2, D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES);
  95. ENSURE_CAP(DevCaps2, D3DDEVCAPS2_STREAMOFFSET);
  96. ENSURE_CAP(RasterCaps, D3DPRASTERCAPS_DEPTHBIAS);
  97. ENSURE_CAP(RasterCaps, D3DPRASTERCAPS_MIPMAPLODBIAS);
  98. ENSURE_CAP(RasterCaps, D3DPRASTERCAPS_SCISSORTEST);
  99. ENSURE_CAP(RasterCaps, D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS);
  100. // Ideally we would like to check D3DPRASTERCAPS_ZTEST,
  101. // but some drivers incorrectly don't report it.
  102. ENSURE_CAP(ShadeCaps, D3DPSHADECAPS_COLORGOURAUDRGB);
  103. ENSURE_CAP(ShadeCaps, D3DPSHADECAPS_ALPHAGOURAUDBLEND);
  104. ENSURE_CAP(PrimitiveMiscCaps, D3DPMISCCAPS_MASKZ);
  105. ENSURE_CAP(PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE);
  106. ENSURE_CAP(PrimitiveMiscCaps, D3DPMISCCAPS_CULLCW);
  107. ENSURE_CAP(PrimitiveMiscCaps, D3DPMISCCAPS_CULLCCW);
  108. ENSURE_CAP(PrimitiveMiscCaps, D3DPMISCCAPS_COLORWRITEENABLE);
  109. ENSURE_CAP(PrimitiveMiscCaps, D3DPMISCCAPS_BLENDOP);
  110. ENSURE_CAP(LineCaps, D3DLINECAPS_BLEND);
  111. ENSURE_CAP(LineCaps, D3DLINECAPS_TEXTURE);
  112. ENSURE_CAP(LineCaps, D3DLINECAPS_ZTEST);
  113. // Check depth/stencil buffer caps.
  114. ENSURE_CAP(ZCmpCaps, D3DPCMPCAPS_ALWAYS);
  115. ENSURE_CAP(ZCmpCaps, D3DPCMPCAPS_EQUAL);
  116. ENSURE_CAP(ZCmpCaps, D3DPCMPCAPS_GREATER);
  117. ENSURE_CAP(ZCmpCaps, D3DPCMPCAPS_GREATEREQUAL);
  118. ENSURE_CAP(ZCmpCaps, D3DPCMPCAPS_LESS);
  119. ENSURE_CAP(ZCmpCaps, D3DPCMPCAPS_LESSEQUAL);
  120. ENSURE_CAP(ZCmpCaps, D3DPCMPCAPS_NEVER);
  121. ENSURE_CAP(ZCmpCaps, D3DPCMPCAPS_NOTEQUAL);
  122. ENSURE_CAP(StencilCaps, D3DSTENCILCAPS_KEEP);
  123. ENSURE_CAP(StencilCaps, D3DSTENCILCAPS_ZERO);
  124. ENSURE_CAP(StencilCaps, D3DSTENCILCAPS_REPLACE);
  125. ENSURE_CAP(StencilCaps, D3DSTENCILCAPS_INCRSAT);
  126. ENSURE_CAP(StencilCaps, D3DSTENCILCAPS_DECRSAT);
  127. ENSURE_CAP(StencilCaps, D3DSTENCILCAPS_INVERT);
  128. ENSURE_CAP(StencilCaps, D3DSTENCILCAPS_INCR);
  129. ENSURE_CAP(StencilCaps, D3DSTENCILCAPS_DECR);
  130. ENSURE_CAP(StencilCaps, D3DSTENCILCAPS_TWOSIDED);
  131. // Check blending caps.
  132. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_BLENDFACTOR);
  133. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_DESTALPHA);
  134. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_DESTCOLOR);
  135. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_INVDESTALPHA);
  136. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_INVDESTCOLOR);
  137. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_INVSRCALPHA);
  138. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_INVSRCCOLOR);
  139. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_ONE);
  140. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_SRCALPHA);
  141. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_SRCALPHASAT);
  142. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_SRCCOLOR);
  143. ENSURE_CAP(SrcBlendCaps, D3DPBLENDCAPS_ZERO);
  144. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_BLENDFACTOR);
  145. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_DESTALPHA);
  146. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_DESTCOLOR);
  147. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_INVDESTALPHA);
  148. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_INVDESTCOLOR);
  149. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA);
  150. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_INVSRCCOLOR);
  151. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_ONE);
  152. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_SRCALPHA);
  153. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_SRCCOLOR);
  154. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_ZERO);
  155. if (profileCapabilities->DestBlendSrcAlphaSat)
  156. {
  157. ENSURE_CAP(DestBlendCaps, D3DPBLENDCAPS_SRCALPHASAT);
  158. }
  159. if (profileCapabilities->SeparateAlphaBlend)
  160. {
  161. ENSURE_CAP(PrimitiveMiscCaps, D3DPMISCCAPS_SEPARATEALPHABLEND);
  162. }
  163. // Check multiple rendertargets.
  164. CHECK_LIMIT(NumSimultaneousRTs, profileCapabilities->MaxRenderTargets);
  165. if (profileCapabilities->MaxRenderTargets > 1)
  166. {
  167. ENSURE_CAP(PrimitiveMiscCaps, D3DPMISCCAPS_INDEPENDENTWRITEMASKS);
  168. ENSURE_CAP(PrimitiveMiscCaps, D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING);
  169. }
  170. // Check texturing abilities.
  171. CHECK_LIMIT(MaxTextureWidth, profileCapabilities->MaxTextureSize);
  172. CHECK_LIMIT(MaxTextureHeight, profileCapabilities->MaxTextureSize);
  173. // Ideally we would like to check MaxCubeSize, but for some reason that isn't part of D3DCAPS9?
  174. if (caps.MaxTextureAspectRatio > 0)
  175. {
  176. // Only check this if MaxTextureAspectRatio > 0, because some drivers erroneously leave this blank.
  177. CHECK_LIMIT(MaxTextureAspectRatio, profileCapabilities->MaxTextureAspectRatio);
  178. }
  179. ENSURE_CAP(TextureCaps, D3DPTEXTURECAPS_ALPHA);
  180. ENSURE_CAP(TextureCaps, D3DPTEXTURECAPS_MIPMAP);
  181. ENSURE_CAP(TextureCaps, D3DPTEXTURECAPS_CUBEMAP);
  182. ENSURE_CAP(TextureCaps, D3DPTEXTURECAPS_MIPCUBEMAP);
  183. ENSURE_CAP(TextureCaps, D3DPTEXTURECAPS_PERSPECTIVE);
  184. REJECT_CAP(TextureCaps, D3DPTEXTURECAPS_SQUAREONLY);
  185. ENSURE_CAP(TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP);
  186. ENSURE_CAP(TextureAddressCaps, D3DPTADDRESSCAPS_WRAP);
  187. ENSURE_CAP(TextureAddressCaps, D3DPTADDRESSCAPS_MIRROR);
  188. ENSURE_CAP(TextureAddressCaps, D3DPTADDRESSCAPS_INDEPENDENTUV);
  189. ENSURE_CAP(TextureFilterCaps, D3DPTFILTERCAPS_MAGFPOINT);
  190. ENSURE_CAP(TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR);
  191. ENSURE_CAP(TextureFilterCaps, D3DPTFILTERCAPS_MINFPOINT);
  192. ENSURE_CAP(TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR);
  193. ENSURE_CAP(TextureFilterCaps, D3DPTFILTERCAPS_MIPFPOINT);
  194. ENSURE_CAP(TextureFilterCaps, D3DPTFILTERCAPS_MIPFLINEAR);
  195. ENSURE_CAP(CubeTextureFilterCaps, D3DPTFILTERCAPS_MAGFPOINT);
  196. ENSURE_CAP(CubeTextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR);
  197. ENSURE_CAP(CubeTextureFilterCaps, D3DPTFILTERCAPS_MINFPOINT);
  198. ENSURE_CAP(CubeTextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR);
  199. ENSURE_CAP(CubeTextureFilterCaps, D3DPTFILTERCAPS_MIPFPOINT);
  200. ENSURE_CAP(CubeTextureFilterCaps, D3DPTFILTERCAPS_MIPFLINEAR);
  201. // Volume textures.
  202. if (profileCapabilities->MaxVolumeExtent > 0)
  203. {
  204. CHECK_LIMIT(MaxVolumeExtent, profileCapabilities->MaxVolumeExtent);
  205. ENSURE_CAP(TextureCaps, D3DPTEXTURECAPS_VOLUMEMAP);
  206. ENSURE_CAP(TextureCaps, D3DPTEXTURECAPS_MIPVOLUMEMAP);
  207. ENSURE_CAP(VolumeTextureAddressCaps, D3DPTADDRESSCAPS_CLAMP);
  208. ENSURE_CAP(VolumeTextureAddressCaps, D3DPTADDRESSCAPS_WRAP);
  209. ENSURE_CAP(VolumeTextureAddressCaps, D3DPTADDRESSCAPS_MIRROR);
  210. ENSURE_CAP(VolumeTextureAddressCaps, D3DPTADDRESSCAPS_INDEPENDENTUV);
  211. ENSURE_CAP(VolumeTextureFilterCaps, D3DPTFILTERCAPS_MAGFPOINT);
  212. ENSURE_CAP(VolumeTextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR);
  213. ENSURE_CAP(VolumeTextureFilterCaps, D3DPTFILTERCAPS_MINFPOINT);
  214. ENSURE_CAP(VolumeTextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR);
  215. ENSURE_CAP(VolumeTextureFilterCaps, D3DPTFILTERCAPS_MIPFPOINT);
  216. ENSURE_CAP(VolumeTextureFilterCaps, D3DPTFILTERCAPS_MIPFLINEAR);
  217. }
  218. // Non-power-of-two textures.
  219. if (profileCapabilities->NonPow2Unconditional)
  220. {
  221. REJECT_CAP(TextureCaps, D3DPTEXTURECAPS_POW2);
  222. }
  223. else
  224. {
  225. // Conditional non-pow-2 support is expressed oddly in the caps.
  226. // If the POW2 flag is not set, we are always good. But when POW2
  227. // is set, we must make sure NONPOW2CONDITIONAL is also set.
  228. if (caps.TextureCaps & D3DPTEXTURECAPS_POW2)
  229. {
  230. ENSURE_CAP(TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
  231. }
  232. }
  233. if (profileCapabilities->NonPow2Cube)
  234. {
  235. REJECT_CAP(TextureCaps, D3DPTEXTURECAPS_CUBEMAP_POW2);
  236. }
  237. if (profileCapabilities->NonPow2Volume)
  238. {
  239. REJECT_CAP(TextureCaps, D3DPTEXTURECAPS_VOLUMEMAP_POW2);
  240. }
  241. // Vertex texturing.
  242. if (profileCapabilities->MaxVertexSamplers > 0)
  243. {
  244. ENSURE_CAP(VertexTextureFilterCaps, D3DPTFILTERCAPS_MAGFPOINT);
  245. ENSURE_CAP(VertexTextureFilterCaps, D3DPTFILTERCAPS_MINFPOINT);
  246. }
  247. // Vertex element formats.
  248. for each (VertexElementFormat format in profileCapabilities->ValidVertexFormats)
  249. {
  250. switch (format)
  251. {
  252. case VertexElementFormat::Color: ENSURE_CAP(DeclTypes, D3DDTCAPS_UBYTE4N); break;
  253. case VertexElementFormat::Byte4: ENSURE_CAP(DeclTypes, D3DDTCAPS_UBYTE4); break;
  254. case VertexElementFormat::NormalizedShort2: ENSURE_CAP(DeclTypes, D3DDTCAPS_SHORT2N); break;
  255. case VertexElementFormat::NormalizedShort4: ENSURE_CAP(DeclTypes, D3DDTCAPS_SHORT4N); break;
  256. case VertexElementFormat::HalfVector2: ENSURE_CAP(DeclTypes, D3DDTCAPS_FLOAT16_2); break;
  257. case VertexElementFormat::HalfVector4: ENSURE_CAP(DeclTypes, D3DDTCAPS_FLOAT16_4); break;
  258. }
  259. }
  260. // Texture formats.
  261. for each (SurfaceFormat format in profileCapabilities->ValidTextureFormats)
  262. {
  263. CheckTextureFormat(profileCapabilities, pD3D, D3DRTYPE_TEXTURE, format);
  264. }
  265. // Cubemap formats.
  266. for each (SurfaceFormat format in profileCapabilities->ValidCubeFormats)
  267. {
  268. CheckTextureFormat(profileCapabilities, pD3D, D3DRTYPE_CUBETEXTURE, format);
  269. }
  270. // Volume texture formats.
  271. for each (SurfaceFormat format in profileCapabilities->ValidVolumeFormats)
  272. {
  273. CheckTextureFormat(profileCapabilities, pD3D, D3DRTYPE_VOLUMETEXTURE, format);
  274. }
  275. // Vertex texture formats.
  276. for each (SurfaceFormat format in profileCapabilities->ValidVertexTextureFormats)
  277. {
  278. CheckVertexTextureFormat(profileCapabilities, pD3D, format);
  279. }
  280. // Rendertarget formats are mostly optional, but Color must always be available.
  281. CheckRenderTargetFormat(profileCapabilities, pD3D, SurfaceFormat::Color);
  282. // HiDef also requires HdrBlendable rendertargets.
  283. if (profileCapabilities->ValidTextureFormats->Contains(SurfaceFormat::HdrBlendable))
  284. {
  285. CheckRenderTargetFormat(profileCapabilities, pD3D, SurfaceFormat::HdrBlendable);
  286. }
  287. }
  288. void ProfileChecker::CheckTextureFormat(ProfileCapabilities^ profileCapabilities, IDirect3D9* pD3D, D3DRESOURCETYPE resourceType, SurfaceFormat format)
  289. {
  290. D3DFORMAT d3dFormat = ConvertXnaFormatToDx(format);
  291. // Is this format supported?
  292. if (FAILED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, IRRELEVANT_ADAPTER_FORMAT, 0, resourceType, d3dFormat)))
  293. {
  294. errors->Add(String::Format("No {0} format {1}", FormatResourceType(resourceType), format));
  295. return;
  296. }
  297. // Does this format support mipmapping?
  298. if (FAILED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, IRRELEVANT_ADAPTER_FORMAT, D3DUSAGE_QUERY_WRAPANDMIP, resourceType, d3dFormat)))
  299. {
  300. errors->Add(String::Format("No mipmapping for {0} format {1}", FormatResourceType(resourceType), format));
  301. }
  302. // Does this format support filtering?
  303. if (!profileCapabilities->InvalidFilterFormats->Contains(format))
  304. {
  305. if (FAILED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, IRRELEVANT_ADAPTER_FORMAT, D3DUSAGE_QUERY_FILTER, resourceType, d3dFormat)))
  306. {
  307. errors->Add(String::Format("No filtering for {0} format {1}", FormatResourceType(resourceType), format));
  308. }
  309. }
  310. }
  311. void ProfileChecker::CheckVertexTextureFormat(ProfileCapabilities^ profileCapabilities, IDirect3D9* pD3D, SurfaceFormat format)
  312. {
  313. D3DFORMAT d3dFormat = ConvertXnaFormatToDx(format);
  314. // What usage flags does this profile require?
  315. UINT queryUsage = D3DUSAGE_QUERY_VERTEXTEXTURE | D3DUSAGE_QUERY_WRAPANDMIP;
  316. if (!profileCapabilities->InvalidFilterFormats->Contains(format))
  317. {
  318. queryUsage |= D3DUSAGE_QUERY_FILTER;
  319. }
  320. // 2D vertex texture?
  321. if (FAILED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, IRRELEVANT_ADAPTER_FORMAT, queryUsage, D3DRTYPE_TEXTURE, d3dFormat)))
  322. {
  323. errors->Add(String::Format("No vertex texture format {0}", format));
  324. return;
  325. }
  326. // Cubemap vertex texture?
  327. if (FAILED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, IRRELEVANT_ADAPTER_FORMAT, queryUsage, D3DRTYPE_CUBETEXTURE, d3dFormat)))
  328. {
  329. errors->Add(String::Format("No vertex cube texture format {0}", format));
  330. }
  331. // Volume vertex texture?
  332. if (FAILED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, IRRELEVANT_ADAPTER_FORMAT, queryUsage, D3DRTYPE_VOLUMETEXTURE, d3dFormat)))
  333. {
  334. errors->Add(String::Format("No vertex volume texture format {0}", format));
  335. }
  336. }
  337. void ProfileChecker::CheckRenderTargetFormat(ProfileCapabilities^ profileCapabilities, IDirect3D9* pD3D, SurfaceFormat format)
  338. {
  339. UINT queryUsage = D3DUSAGE_RENDERTARGET;
  340. if (!profileCapabilities->InvalidBlendFormats->Contains(format))
  341. {
  342. queryUsage |= D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  343. }
  344. if (FAILED(pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, IRRELEVANT_ADAPTER_FORMAT, queryUsage, D3DRTYPE_SURFACE, ConvertXnaFormatToDx(format))))
  345. {
  346. errors->Add(String::Format("No rendertarget format {0}", format));
  347. }
  348. }
  349. D3DFORMAT ProfileChecker::ConvertXnaFormatToDx(SurfaceFormat format)
  350. {
  351. switch (format)
  352. {
  353. // Note: we map Color to D3DFMT_A8R8G8B8, which uses a BGRA byte ordering,
  354. // even though our managed Color type is RGBA. We do this because D3DFMT_A8R8G8B8
  355. // is universally supported on all DX9 parts, while D3DFMT_A8B8G8R8 (which
  356. // properly matches our Color type) is not always available. The resulting
  357. // format mismatch is handled internally by the XNA Framework.
  358. case SurfaceFormat::Color: return D3DFMT_A8R8G8B8;
  359. case SurfaceFormat::Bgr565: return D3DFMT_R5G6B5;
  360. case SurfaceFormat::Bgra5551: return D3DFMT_A1R5G5B5;
  361. case SurfaceFormat::Bgra4444: return D3DFMT_A4R4G4B4;
  362. case SurfaceFormat::Dxt1: return D3DFMT_DXT1;
  363. case SurfaceFormat::Dxt3: return D3DFMT_DXT3;
  364. case SurfaceFormat::Dxt5: return D3DFMT_DXT5;
  365. case SurfaceFormat::NormalizedByte2: return D3DFMT_V8U8;
  366. case SurfaceFormat::NormalizedByte4: return D3DFMT_Q8W8V8U8;
  367. case SurfaceFormat::Rgba1010102: return D3DFMT_A2B10G10R10;
  368. case SurfaceFormat::Rg32: return D3DFMT_G16R16;
  369. case SurfaceFormat::Rgba64: return D3DFMT_A16B16G16R16;
  370. case SurfaceFormat::Alpha8: return D3DFMT_A8;
  371. case SurfaceFormat::Single: return D3DFMT_R32F;
  372. case SurfaceFormat::Vector2: return D3DFMT_G32R32F;
  373. case SurfaceFormat::Vector4: return D3DFMT_A32B32G32R32F;
  374. case SurfaceFormat::HalfSingle: return D3DFMT_R16F;
  375. case SurfaceFormat::HalfVector2: return D3DFMT_G16R16F;
  376. case SurfaceFormat::HalfVector4: return D3DFMT_A16B16G16R16F;
  377. case SurfaceFormat::HdrBlendable: return D3DFMT_A16B16G16R16F;
  378. default: return D3DFMT_UNKNOWN;
  379. }
  380. }
  381. // Converts a resource type enum to readable string format.
  382. String^ ProfileChecker::FormatResourceType(D3DRESOURCETYPE resourceType)
  383. {
  384. switch (resourceType)
  385. {
  386. case D3DRTYPE_TEXTURE: return "texture";
  387. case D3DRTYPE_CUBETEXTURE: return "cube texture";
  388. case D3DRTYPE_VOLUMETEXTURE: return "volume texture";
  389. default:
  390. throw gcnew ArgumentOutOfRangeException("resourceType");
  391. }
  392. }
  393. // Converts a shader version number to readable string format.
  394. String^ ProfileChecker::FormatShaderVersion(unsigned shaderVersion)
  395. {
  396. return String::Format("{0}.{1}", (shaderVersion >> 8) & 0xFF, shaderVersion & 0xFF);
  397. }