d3dcompiler: Parse ISGN in the reflection interface.
[wine] / dlls / d3dcompiler_43 / reflection.c
1 /*
2  * Copyright 2009 Henri Verbeet for CodeWeavers
3  * Copyright 2010 Rico Schüller
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  *
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include "d3dcompiler_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(d3dcompiler);
27
28 static void free_signature(struct d3dcompiler_shader_signature *sig)
29 {
30     TRACE("Free signature %p\n", sig);
31
32     HeapFree(GetProcessHeap(), 0, sig->elements);
33     HeapFree(GetProcessHeap(), 0, sig->string_data);
34 }
35
36 static void reflection_cleanup(struct d3dcompiler_shader_reflection *ref)
37 {
38     TRACE("Cleanup %p\n", ref);
39
40     if (ref->isgn)
41     {
42         free_signature(ref->isgn);
43         HeapFree(GetProcessHeap(), 0, ref->isgn);
44     }
45 }
46
47 static inline struct d3dcompiler_shader_reflection *impl_from_ID3D11ShaderReflection(ID3D11ShaderReflection *iface)
48 {
49     return CONTAINING_RECORD(iface, struct d3dcompiler_shader_reflection, ID3D11ShaderReflection_iface);
50 }
51
52 /* IUnknown methods */
53
54 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_QueryInterface(ID3D11ShaderReflection *iface, REFIID riid, void **object)
55 {
56     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
57
58     if (IsEqualGUID(riid, &IID_ID3D11ShaderReflection)
59             || IsEqualGUID(riid, &IID_IUnknown))
60     {
61         IUnknown_AddRef(iface);
62         *object = iface;
63         return S_OK;
64     }
65
66     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
67
68     *object = NULL;
69     return E_NOINTERFACE;
70 }
71
72 static ULONG STDMETHODCALLTYPE d3dcompiler_shader_reflection_AddRef(ID3D11ShaderReflection *iface)
73 {
74     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
75     ULONG refcount = InterlockedIncrement(&This->refcount);
76
77     TRACE("%p increasing refcount to %u\n", This, refcount);
78
79     return refcount;
80 }
81
82 static ULONG STDMETHODCALLTYPE d3dcompiler_shader_reflection_Release(ID3D11ShaderReflection *iface)
83 {
84     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
85     ULONG refcount = InterlockedDecrement(&This->refcount);
86
87     TRACE("%p decreasing refcount to %u\n", This, refcount);
88
89     if (!refcount)
90     {
91         reflection_cleanup(This);
92         HeapFree(GetProcessHeap(), 0, This);
93     }
94
95     return refcount;
96 }
97
98 /* ID3D11ShaderReflection methods */
99
100 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetDesc(ID3D11ShaderReflection *iface, D3D11_SHADER_DESC *desc)
101 {
102     FIXME("iface %p, desc %p stub!\n", iface, desc);
103
104     return E_NOTIMPL;
105 }
106
107 static struct ID3D11ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetConstantBufferByIndex(
108         ID3D11ShaderReflection *iface, UINT index)
109 {
110     FIXME("iface %p, index %u stub!\n", iface, index);
111
112     return NULL;
113 }
114
115 static struct ID3D11ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetConstantBufferByName(
116         ID3D11ShaderReflection *iface, LPCSTR name)
117 {
118     FIXME("iface %p, name \"%s\" stub!\n", iface, name);
119
120     return NULL;
121 }
122
123 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetResourceBindingDesc(
124         ID3D11ShaderReflection *iface, UINT index, D3D11_SHADER_INPUT_BIND_DESC *desc)
125 {
126     FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc);
127
128     return E_NOTIMPL;
129 }
130
131 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetInputParameterDesc(
132         ID3D11ShaderReflection *iface, UINT index, D3D11_SIGNATURE_PARAMETER_DESC *desc)
133 {
134     FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc);
135
136     return E_NOTIMPL;
137 }
138
139 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetOutputParameterDesc(
140         ID3D11ShaderReflection *iface, UINT index, D3D11_SIGNATURE_PARAMETER_DESC *desc)
141 {
142     FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc);
143
144     return E_NOTIMPL;
145 }
146
147 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetPatchConstantParameterDesc(
148         ID3D11ShaderReflection *iface, UINT index, D3D11_SIGNATURE_PARAMETER_DESC *desc)
149 {
150     FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc);
151
152     return E_NOTIMPL;
153 }
154
155 static struct ID3D11ShaderReflectionVariable * STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetVariableByName(
156         ID3D11ShaderReflection *iface, LPCSTR name)
157 {
158     FIXME("iface %p, name %s stub!\n", iface, name);
159
160     return NULL;
161 }
162
163 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetResourceBindingDescByName(
164         ID3D11ShaderReflection *iface, LPCSTR name, D3D11_SHADER_INPUT_BIND_DESC *desc)
165 {
166     FIXME("iface %p, name %s, desc %p stub!\n", iface, name, desc);
167
168     return E_NOTIMPL;
169 }
170
171 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMovInstructionCount(
172         ID3D11ShaderReflection *iface)
173 {
174     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
175
176     TRACE("iface %p\n", iface);
177
178     return This->mov_instruction_count;
179 }
180
181 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMovcInstructionCount(
182         ID3D11ShaderReflection *iface)
183 {
184     FIXME("iface %p stub!\n", iface);
185
186     return 0;
187 }
188
189 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetConversionInstructionCount(
190         ID3D11ShaderReflection *iface)
191 {
192     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
193
194     TRACE("iface %p\n", iface);
195
196     return This->conversion_instruction_count;
197 }
198
199 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetBitwiseInstructionCount(
200         ID3D11ShaderReflection *iface)
201 {
202     FIXME("iface %p stub!\n", iface);
203
204     return 0;
205 }
206
207 static D3D_PRIMITIVE STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetGSInputPrimitive(
208         ID3D11ShaderReflection *iface)
209 {
210     FIXME("iface %p stub!\n", iface);
211
212     return 0;
213 }
214
215 static BOOL STDMETHODCALLTYPE d3dcompiler_shader_reflection_IsSampleFrequencyShader(
216         ID3D11ShaderReflection *iface)
217 {
218     FIXME("iface %p stub!\n", iface);
219
220     return 0;
221 }
222
223 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetNumInterfaceSlots(
224         ID3D11ShaderReflection *iface)
225 {
226     FIXME("iface %p stub!\n", iface);
227
228     return 0;
229 }
230
231 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMinFeatureLevel(
232         ID3D11ShaderReflection *iface, D3D_FEATURE_LEVEL *level)
233 {
234     FIXME("iface %p, level %p stub!\n", iface, level);
235
236     return E_NOTIMPL;
237 }
238
239 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetThreadGroupSize(
240         ID3D11ShaderReflection *iface, UINT *sizex, UINT *sizey, UINT *sizez)
241 {
242     FIXME("iface %p, sizex %p, sizey %p, sizez %p stub!\n", iface, sizex, sizey, sizez);
243
244     return 0;
245 }
246
247 const struct ID3D11ShaderReflectionVtbl d3dcompiler_shader_reflection_vtbl =
248 {
249     /* IUnknown methods */
250     d3dcompiler_shader_reflection_QueryInterface,
251     d3dcompiler_shader_reflection_AddRef,
252     d3dcompiler_shader_reflection_Release,
253     /* ID3D11ShaderReflection methods */
254     d3dcompiler_shader_reflection_GetDesc,
255     d3dcompiler_shader_reflection_GetConstantBufferByIndex,
256     d3dcompiler_shader_reflection_GetConstantBufferByName,
257     d3dcompiler_shader_reflection_GetResourceBindingDesc,
258     d3dcompiler_shader_reflection_GetInputParameterDesc,
259     d3dcompiler_shader_reflection_GetOutputParameterDesc,
260     d3dcompiler_shader_reflection_GetPatchConstantParameterDesc,
261     d3dcompiler_shader_reflection_GetVariableByName,
262     d3dcompiler_shader_reflection_GetResourceBindingDescByName,
263     d3dcompiler_shader_reflection_GetMovInstructionCount,
264     d3dcompiler_shader_reflection_GetMovcInstructionCount,
265     d3dcompiler_shader_reflection_GetConversionInstructionCount,
266     d3dcompiler_shader_reflection_GetBitwiseInstructionCount,
267     d3dcompiler_shader_reflection_GetGSInputPrimitive,
268     d3dcompiler_shader_reflection_IsSampleFrequencyShader,
269     d3dcompiler_shader_reflection_GetNumInterfaceSlots,
270     d3dcompiler_shader_reflection_GetMinFeatureLevel,
271     d3dcompiler_shader_reflection_GetThreadGroupSize,
272 };
273
274 static HRESULT d3dcompiler_parse_stat(struct d3dcompiler_shader_reflection *r, const char *data, DWORD data_size)
275 {
276     const char *ptr = data;
277     DWORD size = data_size >> 2;
278
279     TRACE("Size %u\n", size);
280
281     read_dword(&ptr, &r->instruction_count);
282     TRACE("InstructionCount: %u\n", r->instruction_count);
283
284     read_dword(&ptr, &r->temp_register_count);
285     TRACE("TempRegisterCount: %u\n", r->temp_register_count);
286
287     skip_dword_unknown(&ptr, 1);
288
289     read_dword(&ptr, &r->dcl_count);
290     TRACE("DclCount: %u\n", r->dcl_count);
291
292     read_dword(&ptr, &r->float_instruction_count);
293     TRACE("FloatInstructionCount: %u\n", r->float_instruction_count);
294
295     read_dword(&ptr, &r->int_instruction_count);
296     TRACE("IntInstructionCount: %u\n", r->int_instruction_count);
297
298     read_dword(&ptr, &r->uint_instruction_count);
299     TRACE("UintInstructionCount: %u\n", r->uint_instruction_count);
300
301     read_dword(&ptr, &r->static_flow_control_count);
302     TRACE("StaticFlowControlCount: %u\n", r->static_flow_control_count);
303
304     read_dword(&ptr, &r->dynamic_flow_control_count);
305     TRACE("DynamicFlowControlCount: %u\n", r->dynamic_flow_control_count);
306
307     skip_dword_unknown(&ptr, 1);
308
309     read_dword(&ptr, &r->temp_array_count);
310     TRACE("TempArrayCount: %u\n", r->temp_array_count);
311
312     read_dword(&ptr, &r->array_instruction_count);
313     TRACE("ArrayInstructionCount: %u\n", r->array_instruction_count);
314
315     read_dword(&ptr, &r->cut_instruction_count);
316     TRACE("CutInstructionCount: %u\n", r->cut_instruction_count);
317
318     read_dword(&ptr, &r->emit_instruction_count);
319     TRACE("EmitInstructionCount: %u\n", r->emit_instruction_count);
320
321     read_dword(&ptr, &r->texture_normal_instructions);
322     TRACE("TextureNormalInstructions: %u\n", r->texture_normal_instructions);
323
324     read_dword(&ptr, &r->texture_load_instructions);
325     TRACE("TextureLoadInstructions: %u\n", r->texture_load_instructions);
326
327     read_dword(&ptr, &r->texture_comp_instructions);
328     TRACE("TextureCompInstructions: %u\n", r->texture_comp_instructions);
329
330     read_dword(&ptr, &r->texture_bias_instructions);
331     TRACE("TextureBiasInstructions: %u\n", r->texture_bias_instructions);
332
333     read_dword(&ptr, &r->texture_gradient_instructions);
334     TRACE("TextureGradientInstructions: %u\n", r->texture_gradient_instructions);
335
336     read_dword(&ptr, &r->mov_instruction_count);
337     TRACE("MovInstructionCount: %u\n", r->mov_instruction_count);
338
339     skip_dword_unknown(&ptr, 1);
340
341     read_dword(&ptr, &r->conversion_instruction_count);
342     TRACE("ConversionInstructionCount: %u\n", r->conversion_instruction_count);
343
344     skip_dword_unknown(&ptr, 1);
345
346     read_dword(&ptr, &r->input_primitive);
347     TRACE("InputPrimitive: %x\n", r->input_primitive);
348
349     read_dword(&ptr, &r->gs_output_topology);
350     TRACE("GSOutputTopology: %x\n", r->gs_output_topology);
351
352     read_dword(&ptr, &r->gs_max_output_vertex_count);
353     TRACE("GSMaxOutputVertexCount: %u\n", r->gs_max_output_vertex_count);
354
355     skip_dword_unknown(&ptr, 3);
356
357     /* dx10 stat size */
358     if (size == 29) return S_OK;
359
360     skip_dword_unknown(&ptr, 1);
361
362     read_dword(&ptr, &r->c_control_points);
363     TRACE("cControlPoints: %u\n", r->c_control_points);
364
365     read_dword(&ptr, &r->hs_output_primitive);
366     TRACE("HSOutputPrimitive: %x\n", r->hs_output_primitive);
367
368     read_dword(&ptr, &r->hs_prtitioning);
369     TRACE("HSPartitioning: %x\n", r->hs_prtitioning);
370
371     read_dword(&ptr, &r->tessellator_domain);
372     TRACE("TessellatorDomain: %x\n", r->tessellator_domain);
373
374     skip_dword_unknown(&ptr, 3);
375
376     /* dx11 stat size */
377     if (size == 37) return S_OK;
378
379     FIXME("Unhandled size %u\n", size);
380
381     return E_FAIL;
382 }
383
384 HRESULT d3dcompiler_parse_signature(struct d3dcompiler_shader_signature *s, const char *data, DWORD data_size)
385 {
386     D3D11_SIGNATURE_PARAMETER_DESC *d;
387     unsigned int string_data_offset;
388     unsigned int string_data_size;
389     const char *ptr = data;
390     char *string_data;
391     unsigned int i;
392     DWORD count;
393
394     read_dword(&ptr, &count);
395     TRACE("%u elements\n", count);
396
397     skip_dword_unknown(&ptr, 1);
398
399     d = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*d));
400     if (!d)
401     {
402         ERR("Failed to allocate signature memory.\n");
403         return E_OUTOFMEMORY;
404     }
405
406     /* 2 DWORDs for the header, 6 for each element. */
407     string_data_offset = 2 * sizeof(DWORD) + count * 6 * sizeof(DWORD);
408     string_data_size = data_size - string_data_offset;
409     string_data = HeapAlloc(GetProcessHeap(), 0, string_data_size);
410     if (!string_data)
411     {
412         ERR("Failed to allocate string data memory.\n");
413         HeapFree(GetProcessHeap(), 0, d);
414         return E_OUTOFMEMORY;
415     }
416     memcpy(string_data, data + string_data_offset, string_data_size);
417
418     for (i = 0; i < count; ++i)
419     {
420         UINT name_offset;
421         DWORD mask;
422
423         read_dword(&ptr, &name_offset);
424         d[i].SemanticName = string_data + (name_offset - string_data_offset);
425         read_dword(&ptr, &d[i].SemanticIndex);
426         read_dword(&ptr, &d[i].SystemValueType);
427         read_dword(&ptr, &d[i].ComponentType);
428         read_dword(&ptr, &d[i].Register);
429         read_dword(&ptr, &mask);
430         d[i].ReadWriteMask = (mask >> 8) & 0xff;
431         d[i].Mask = mask & 0xff;
432
433         TRACE("semantic: %s, semantic idx: %u, sysval_semantic %#x, "
434                 "type %u, register idx: %u, use_mask %#x, input_mask %#x, stream %u\n",
435                 debugstr_a(d[i].SemanticName), d[i].SemanticIndex, d[i].SystemValueType,
436                 d[i].ComponentType, d[i].Register, d[i].Mask, d[i].ReadWriteMask, d[i].Stream);
437     }
438
439     s->elements = d;
440     s->element_count = count;
441     s->string_data = string_data;
442
443     return S_OK;
444 }
445
446 HRESULT d3dcompiler_shader_reflection_init(struct d3dcompiler_shader_reflection *reflection,
447         const void *data, SIZE_T data_size)
448 {
449     struct dxbc src_dxbc;
450     HRESULT hr;
451     unsigned int i;
452
453     reflection->ID3D11ShaderReflection_iface.lpVtbl = &d3dcompiler_shader_reflection_vtbl;
454     reflection->refcount = 1;
455
456     hr = dxbc_parse(data, data_size, &src_dxbc);
457     if (FAILED(hr))
458     {
459         WARN("Failed to parse reflection\n");
460         return hr;
461     }
462
463     for (i = 0; i < src_dxbc.count; ++i)
464     {
465         struct dxbc_section *section = &src_dxbc.sections[i];
466
467         switch (section->tag)
468         {
469             case TAG_STAT:
470                 hr = d3dcompiler_parse_stat(reflection, section->data, section->data_size);
471                 if (FAILED(hr))
472                 {
473                     WARN("Failed to parse section STAT.\n");
474                     goto err_out;
475                 }
476                 break;
477
478             case TAG_ISGN:
479                 reflection->isgn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*reflection->isgn));
480                 if (!reflection->isgn)
481                 {
482                     ERR("Failed to allocate ISGN memory.\n");
483                     hr = E_OUTOFMEMORY;
484                     goto err_out;
485                 }
486
487                 hr = d3dcompiler_parse_signature(reflection->isgn, section->data, section->data_size);
488                 if (FAILED(hr))
489                 {
490                     WARN("Failed to parse section ISGN.\n");
491                     goto err_out;
492                 }
493                 break;
494
495             default:
496                 FIXME("Unhandled section %s!\n", debugstr_an((const char *)&section->tag, 4));
497                 break;
498         }
499     }
500
501     dxbc_destroy(&src_dxbc);
502
503     return hr;
504
505 err_out:
506     reflection_cleanup(reflection);
507     dxbc_destroy(&src_dxbc);
508
509     return hr;
510 }