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