SOParser.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. //--------------------------------------------------------------------------------------
  2. // File: SOParser.h
  3. //
  4. // Direct3D 11 Effects Stream Out Decl Parser
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //
  11. // Copyright (c) Microsoft Corporation. All rights reserved.
  12. //
  13. // http://go.microsoft.com/fwlink/p/?LinkId=271568
  14. //--------------------------------------------------------------------------------------
  15. #pragma once
  16. #include <stdio.h>
  17. #include <string.h>
  18. namespace D3DX11Effects
  19. {
  20. //////////////////////////////////////////////////////////////////////////
  21. // CSOParser
  22. //////////////////////////////////////////////////////////////////////////
  23. class CSOParser
  24. {
  25. CEffectVector<D3D11_SO_DECLARATION_ENTRY> m_vDecls; // Set of parsed decl entries
  26. D3D11_SO_DECLARATION_ENTRY m_newEntry; // Currently parsing entry
  27. LPSTR m_SemanticString[D3D11_SO_BUFFER_SLOT_COUNT]; // Copy of strings
  28. static const size_t MAX_ERROR_SIZE = 254;
  29. char m_pError[ MAX_ERROR_SIZE + 1 ]; // Error buffer
  30. public:
  31. CSOParser()
  32. {
  33. ZeroMemory(&m_newEntry, sizeof(m_newEntry));
  34. ZeroMemory(m_SemanticString, sizeof(m_SemanticString));
  35. m_pError[0] = 0;
  36. }
  37. ~CSOParser()
  38. {
  39. for( size_t Stream = 0; Stream < D3D11_SO_STREAM_COUNT; ++Stream )
  40. {
  41. SAFE_DELETE_ARRAY( m_SemanticString[Stream] );
  42. }
  43. }
  44. // Parse a single string, assuming stream 0
  45. HRESULT Parse( _In_z_ LPCSTR pString )
  46. {
  47. m_vDecls.Clear();
  48. return Parse( 0, pString );
  49. }
  50. // Parse all 4 streams
  51. HRESULT Parse( _In_z_ LPSTR pStreams[D3D11_SO_STREAM_COUNT] )
  52. {
  53. HRESULT hr = S_OK;
  54. m_vDecls.Clear();
  55. for( uint32_t iDecl=0; iDecl < D3D11_SO_STREAM_COUNT; ++iDecl )
  56. {
  57. hr = Parse( iDecl, pStreams[iDecl] );
  58. if( FAILED(hr) )
  59. {
  60. char str[16];
  61. sprintf_s( str, 16, " in stream %u.", iDecl );
  62. str[15] = 0;
  63. strcat_s( m_pError, MAX_ERROR_SIZE, str );
  64. return hr;
  65. }
  66. }
  67. return hr;
  68. }
  69. // Return resulting declarations
  70. D3D11_SO_DECLARATION_ENTRY *GetDeclArray()
  71. {
  72. return &m_vDecls[0];
  73. }
  74. char* GetErrorString()
  75. {
  76. return m_pError;
  77. }
  78. uint32_t GetDeclCount() const
  79. {
  80. return m_vDecls.GetSize();
  81. }
  82. // Return resulting buffer strides
  83. void GetStrides( uint32_t strides[4] )
  84. {
  85. size_t len = GetDeclCount();
  86. strides[0] = strides[1] = strides[2] = strides[3] = 0;
  87. for( size_t i=0; i < len; i++ )
  88. {
  89. strides[m_vDecls[i].OutputSlot] += m_vDecls[i].ComponentCount * sizeof(float);
  90. }
  91. }
  92. protected:
  93. // Parse a single string "[<slot> :] <semantic>[<index>][.<mask>]; [[<slot> :] <semantic>[<index>][.<mask>][;]]"
  94. HRESULT Parse( _In_ uint32_t Stream, _In_z_ LPCSTR pString )
  95. {
  96. HRESULT hr = S_OK;
  97. m_pError[0] = 0;
  98. if( pString == nullptr )
  99. return S_OK;
  100. uint32_t len = (uint32_t)strlen( pString );
  101. if( len == 0 )
  102. return S_OK;
  103. SAFE_DELETE_ARRAY( m_SemanticString[Stream] );
  104. VN( m_SemanticString[Stream] = new char[len + 1] );
  105. strcpy_s( m_SemanticString[Stream], len + 1, pString );
  106. LPSTR pSemantic = m_SemanticString[Stream];
  107. while( true )
  108. {
  109. // Each decl entry is delimited by a semi-colon
  110. LPSTR pSemi = strchr( pSemantic, ';' );
  111. // strip leading and trailing spaces
  112. LPSTR pEnd;
  113. if( pSemi != nullptr )
  114. {
  115. *pSemi = '\0';
  116. pEnd = pSemi - 1;
  117. }
  118. else
  119. {
  120. pEnd = pSemantic + strlen( pSemantic );
  121. }
  122. while( isspace( (unsigned char)*pSemantic ) )
  123. pSemantic++;
  124. while( pEnd > pSemantic && isspace( (unsigned char)*pEnd ) )
  125. {
  126. *pEnd = '\0';
  127. pEnd--;
  128. }
  129. if( *pSemantic != '\0' )
  130. {
  131. VH( AddSemantic( pSemantic ) );
  132. m_newEntry.Stream = Stream;
  133. VH( m_vDecls.Add( m_newEntry ) );
  134. }
  135. if( pSemi == nullptr )
  136. break;
  137. pSemantic = pSemi + 1;
  138. }
  139. lExit:
  140. return hr;
  141. }
  142. // Parse a single decl "[<slot> :] <semantic>[<index>][.<mask>]"
  143. HRESULT AddSemantic( _Inout_z_ LPSTR pSemantic )
  144. {
  145. HRESULT hr = S_OK;
  146. assert( pSemantic );
  147. ZeroMemory( &m_newEntry, sizeof(m_newEntry) );
  148. VH( ConsumeOutputSlot( &pSemantic ) );
  149. VH( ConsumeRegisterMask( pSemantic ) );
  150. VH( ConsumeSemanticIndex( pSemantic ) );
  151. // pSenantic now contains only the SemanticName (all other fields were consumed)
  152. if( strcmp( "$SKIP", pSemantic ) != 0 )
  153. {
  154. m_newEntry.SemanticName = pSemantic;
  155. }
  156. lExit:
  157. return hr;
  158. }
  159. // Parse optional mask "[.<mask>]"
  160. HRESULT ConsumeRegisterMask( _Inout_z_ LPSTR pSemantic )
  161. {
  162. HRESULT hr = S_OK;
  163. const char *pFullMask1 = "xyzw";
  164. const char *pFullMask2 = "rgba";
  165. size_t stringLength;
  166. size_t startComponent = 0;
  167. LPCSTR p;
  168. assert( pSemantic );
  169. pSemantic = strchr( pSemantic, '.' );
  170. if( pSemantic == nullptr )
  171. {
  172. m_newEntry.ComponentCount = 4;
  173. return S_OK;
  174. }
  175. *pSemantic = '\0';
  176. pSemantic++;
  177. stringLength = strlen( pSemantic );
  178. p = strstr(pFullMask1, pSemantic );
  179. if( p )
  180. {
  181. startComponent = (uint32_t)( p - pFullMask1 );
  182. }
  183. else
  184. {
  185. p = strstr( pFullMask2, pSemantic );
  186. if( p )
  187. startComponent = (uint32_t)( p - pFullMask2 );
  188. else
  189. {
  190. sprintf_s( m_pError, MAX_ERROR_SIZE, "ID3D11Effect::ParseSODecl - invalid mask declaration '%s'", pSemantic );
  191. VH( E_FAIL );
  192. }
  193. }
  194. if( stringLength == 0 )
  195. stringLength = 4;
  196. m_newEntry.StartComponent = (uint8_t)startComponent;
  197. m_newEntry.ComponentCount = (uint8_t)stringLength;
  198. lExit:
  199. return hr;
  200. }
  201. // Parse optional output slot "[<slot> :]"
  202. HRESULT ConsumeOutputSlot( _Inout_z_ LPSTR* ppSemantic )
  203. {
  204. assert( ppSemantic && *ppSemantic );
  205. _Analysis_assume_( ppSemantic && *ppSemantic );
  206. HRESULT hr = S_OK;
  207. LPSTR pColon = strchr( *ppSemantic, ':' );
  208. if( pColon == nullptr )
  209. return S_OK;
  210. if( pColon == *ppSemantic )
  211. {
  212. strcpy_s( m_pError, MAX_ERROR_SIZE,
  213. "ID3D11Effect::ParseSODecl - Invalid output slot" );
  214. VH( E_FAIL );
  215. }
  216. *pColon = '\0';
  217. int outputSlot = atoi( *ppSemantic );
  218. if( outputSlot < 0 || outputSlot > 255 )
  219. {
  220. strcpy_s( m_pError, MAX_ERROR_SIZE,
  221. "ID3D11Effect::ParseSODecl - Invalid output slot" );
  222. VH( E_FAIL );
  223. }
  224. m_newEntry.OutputSlot = (uint8_t)outputSlot;
  225. while( *ppSemantic < pColon )
  226. {
  227. if( !isdigit( (unsigned char)**ppSemantic ) )
  228. {
  229. sprintf_s( m_pError, MAX_ERROR_SIZE, "ID3D11Effect::ParseSODecl - Non-digit '%c' in output slot", **ppSemantic );
  230. VH( E_FAIL );
  231. }
  232. (*ppSemantic)++;
  233. }
  234. // skip the colon (which is now '\0')
  235. (*ppSemantic)++;
  236. while( isspace( (unsigned char)**ppSemantic ) )
  237. (*ppSemantic)++;
  238. lExit:
  239. return hr;
  240. }
  241. // Parse optional index "[<index>]"
  242. HRESULT ConsumeSemanticIndex( _Inout_z_ LPSTR pSemantic )
  243. {
  244. assert( pSemantic );
  245. uint32_t uLen = (uint32_t)strlen( pSemantic );
  246. // Grab semantic index
  247. while( uLen > 0 && isdigit( (unsigned char)pSemantic[uLen - 1] ) )
  248. uLen--;
  249. if( isdigit( (unsigned char)pSemantic[uLen] ) )
  250. {
  251. m_newEntry.SemanticIndex = atoi( pSemantic + uLen );
  252. pSemantic[uLen] = '\0';
  253. }
  254. else
  255. {
  256. m_newEntry.SemanticIndex = 0;
  257. }
  258. return S_OK;
  259. }
  260. };
  261. } // end namespace D3DX11Effects