d3dcompiler: Implement ID3D11ShaderReflection::GetConstantBufferByName().
[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 enum D3DCOMPILER_SIGNATURE_ELEMENT_SIZE
29 {
30     D3DCOMPILER_SIGNATURE_ELEMENT_SIZE6 = 6,
31     D3DCOMPILER_SIGNATURE_ELEMENT_SIZE7 = 7,
32 };
33
34 const struct ID3D11ShaderReflectionConstantBufferVtbl d3dcompiler_shader_reflection_constant_buffer_vtbl;
35
36 /* null objects - needed for invalid calls */
37 static struct d3dcompiler_shader_reflection_constant_buffer null_constant_buffer = {{&d3dcompiler_shader_reflection_constant_buffer_vtbl}};
38
39 static BOOL copy_name(const char *ptr, char **name)
40 {
41     size_t name_len;
42
43     if (!ptr) return TRUE;
44
45     name_len = strlen(ptr) + 1;
46     if (name_len == 1)
47     {
48         return TRUE;
49     }
50
51     *name = HeapAlloc(GetProcessHeap(), 0, name_len);
52     if (!*name)
53     {
54         ERR("Failed to allocate name memory.\n");
55         return FALSE;
56     }
57
58     memcpy(*name, ptr, name_len);
59
60     return TRUE;
61 }
62
63 static void free_signature(struct d3dcompiler_shader_signature *sig)
64 {
65     TRACE("Free signature %p\n", sig);
66
67     HeapFree(GetProcessHeap(), 0, sig->elements);
68     HeapFree(GetProcessHeap(), 0, sig->string_data);
69 }
70
71 static void free_constant_buffer(struct d3dcompiler_shader_reflection_constant_buffer *cb)
72 {
73     HeapFree(GetProcessHeap(), 0, cb->name);
74 }
75
76 static void reflection_cleanup(struct d3dcompiler_shader_reflection *ref)
77 {
78     TRACE("Cleanup %p\n", ref);
79
80     if (ref->isgn)
81     {
82         free_signature(ref->isgn);
83         HeapFree(GetProcessHeap(), 0, ref->isgn);
84     }
85
86     if (ref->osgn)
87     {
88         free_signature(ref->osgn);
89         HeapFree(GetProcessHeap(), 0, ref->osgn);
90     }
91
92     if (ref->pcsg)
93     {
94         free_signature(ref->pcsg);
95         HeapFree(GetProcessHeap(), 0, ref->pcsg);
96     }
97
98     if (ref->constant_buffers)
99     {
100         unsigned int i;
101
102         for (i = 0; i < ref->constant_buffer_count; ++i)
103         {
104             free_constant_buffer(&ref->constant_buffers[i]);
105         }
106     }
107
108     HeapFree(GetProcessHeap(), 0, ref->constant_buffers);
109     HeapFree(GetProcessHeap(), 0, ref->bound_resources);
110     HeapFree(GetProcessHeap(), 0, ref->resource_string);
111     HeapFree(GetProcessHeap(), 0, ref->creator);
112 }
113
114 static inline struct d3dcompiler_shader_reflection *impl_from_ID3D11ShaderReflection(ID3D11ShaderReflection *iface)
115 {
116     return CONTAINING_RECORD(iface, struct d3dcompiler_shader_reflection, ID3D11ShaderReflection_iface);
117 }
118
119 /* IUnknown methods */
120
121 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_QueryInterface(ID3D11ShaderReflection *iface, REFIID riid, void **object)
122 {
123     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
124
125     if (IsEqualGUID(riid, &IID_ID3D11ShaderReflection)
126             || IsEqualGUID(riid, &IID_IUnknown))
127     {
128         IUnknown_AddRef(iface);
129         *object = iface;
130         return S_OK;
131     }
132
133     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
134
135     *object = NULL;
136     return E_NOINTERFACE;
137 }
138
139 static ULONG STDMETHODCALLTYPE d3dcompiler_shader_reflection_AddRef(ID3D11ShaderReflection *iface)
140 {
141     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
142     ULONG refcount = InterlockedIncrement(&This->refcount);
143
144     TRACE("%p increasing refcount to %u\n", This, refcount);
145
146     return refcount;
147 }
148
149 static ULONG STDMETHODCALLTYPE d3dcompiler_shader_reflection_Release(ID3D11ShaderReflection *iface)
150 {
151     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
152     ULONG refcount = InterlockedDecrement(&This->refcount);
153
154     TRACE("%p decreasing refcount to %u\n", This, refcount);
155
156     if (!refcount)
157     {
158         reflection_cleanup(This);
159         HeapFree(GetProcessHeap(), 0, This);
160     }
161
162     return refcount;
163 }
164
165 /* ID3D11ShaderReflection methods */
166
167 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetDesc(ID3D11ShaderReflection *iface, D3D11_SHADER_DESC *desc)
168 {
169     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
170
171     FIXME("iface %p, desc %p partial stub!\n", iface, desc);
172
173     if (!desc)
174     {
175         WARN("Invalid argument specified\n");
176         return E_FAIL;
177     }
178
179     desc->Version = This->version;
180     desc->Creator = This->creator;
181     desc->Flags = This->flags;
182     desc->ConstantBuffers = This->constant_buffer_count;
183     desc->BoundResources = This->bound_resource_count;
184     desc->InputParameters = This->isgn ? This->isgn->element_count : 0;
185     desc->OutputParameters = This->osgn ? This->osgn->element_count : 0;
186     desc->InstructionCount = This->instruction_count;
187     desc->TempRegisterCount = This->temp_register_count;
188     desc->TempArrayCount = This->temp_array_count;
189     desc->DefCount = 0;
190     desc->DclCount = This->dcl_count;
191     desc->TextureNormalInstructions = This->texture_normal_instructions;
192     desc->TextureLoadInstructions = This->texture_load_instructions;
193     desc->TextureCompInstructions = This->texture_comp_instructions;
194     desc->TextureBiasInstructions = This->texture_bias_instructions;
195     desc->TextureGradientInstructions = This->texture_gradient_instructions;
196     desc->FloatInstructionCount = This->float_instruction_count;
197     desc->IntInstructionCount = This->int_instruction_count;
198     desc->UintInstructionCount = This->uint_instruction_count;
199     desc->StaticFlowControlCount = This->static_flow_control_count;
200     desc->DynamicFlowControlCount = This->dynamic_flow_control_count;
201     desc->MacroInstructionCount = 0;
202     desc->ArrayInstructionCount = This->array_instruction_count;
203     desc->CutInstructionCount = This->cut_instruction_count;
204     desc->EmitInstructionCount = This->emit_instruction_count;
205     desc->GSOutputTopology = This->gs_output_topology;
206     desc->GSMaxOutputVertexCount = This->gs_max_output_vertex_count;
207     desc->InputPrimitive = This->input_primitive;
208     desc->PatchConstantParameters = This->pcsg ? This->pcsg->element_count : 0;
209     desc->cGSInstanceCount = 0;
210     desc->cControlPoints = This->c_control_points;
211     desc->HSOutputPrimitive = This->hs_output_primitive;
212     desc->HSPartitioning = This->hs_prtitioning;
213     desc->TessellatorDomain = This->tessellator_domain;
214     desc->cBarrierInstructions = 0;
215     desc->cInterlockedInstructions = 0;
216     desc->cTextureStoreInstructions = 0;
217
218     return S_OK;
219 }
220
221 static struct ID3D11ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetConstantBufferByIndex(
222         ID3D11ShaderReflection *iface, UINT index)
223 {
224     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
225
226     TRACE("iface %p, index %u\n", iface, index);
227
228     if (index >= This->constant_buffer_count)
229     {
230         WARN("Invalid argument specified\n");
231         return &null_constant_buffer.ID3D11ShaderReflectionConstantBuffer_iface;
232     }
233
234     return &This->constant_buffers[index].ID3D11ShaderReflectionConstantBuffer_iface;
235 }
236
237 static struct ID3D11ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetConstantBufferByName(
238         ID3D11ShaderReflection *iface, LPCSTR name)
239 {
240     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
241     unsigned int i;
242
243     TRACE("iface %p, name %s\n", iface, debugstr_a(name));
244
245     if (!name)
246     {
247         WARN("Invalid argument specified\n");
248         return &null_constant_buffer.ID3D11ShaderReflectionConstantBuffer_iface;
249     }
250
251     for (i = 0; i < This->constant_buffer_count; ++i)
252     {
253         struct d3dcompiler_shader_reflection_constant_buffer *d = &This->constant_buffers[i];
254
255         if (!strcmp(d->name, name))
256         {
257             TRACE("Returning ID3D11ShaderReflectionConstantBuffer %p.\n", d);
258             return &d->ID3D11ShaderReflectionConstantBuffer_iface;
259         }
260     }
261
262     WARN("Invalid name specified\n");
263
264     return &null_constant_buffer.ID3D11ShaderReflectionConstantBuffer_iface;
265 }
266
267 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetResourceBindingDesc(
268         ID3D11ShaderReflection *iface, UINT index, D3D11_SHADER_INPUT_BIND_DESC *desc)
269 {
270     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
271
272     TRACE("iface %p, index %u, desc %p\n", iface, index, desc);
273
274     if (!desc || index >= This->bound_resource_count)
275     {
276         WARN("Invalid argument specified\n");
277         return E_INVALIDARG;
278     }
279
280     *desc = This->bound_resources[index];
281
282     return S_OK;
283 }
284
285 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetInputParameterDesc(
286         ID3D11ShaderReflection *iface, UINT index, D3D11_SIGNATURE_PARAMETER_DESC *desc)
287 {
288     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
289
290     TRACE("iface %p, index %u, desc %p\n", iface, index, desc);
291
292     if (!desc || !This->isgn || index >= This->isgn->element_count)
293     {
294         WARN("Invalid argument specified\n");
295         return E_INVALIDARG;
296     }
297
298     *desc = This->isgn->elements[index];
299
300     return S_OK;
301 }
302
303 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetOutputParameterDesc(
304         ID3D11ShaderReflection *iface, UINT index, D3D11_SIGNATURE_PARAMETER_DESC *desc)
305 {
306     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
307
308     TRACE("iface %p, index %u, desc %p\n", iface, index, desc);
309
310     if (!desc || !This->osgn || index >= This->osgn->element_count)
311     {
312         WARN("Invalid argument specified\n");
313         return E_INVALIDARG;
314     }
315
316     *desc = This->osgn->elements[index];
317
318     return S_OK;
319 }
320
321 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetPatchConstantParameterDesc(
322         ID3D11ShaderReflection *iface, UINT index, D3D11_SIGNATURE_PARAMETER_DESC *desc)
323 {
324     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
325
326     TRACE("iface %p, index %u, desc %p\n", iface, index, desc);
327
328     if (!desc || !This->pcsg || index >= This->pcsg->element_count)
329     {
330         WARN("Invalid argument specified\n");
331         return E_INVALIDARG;
332     }
333
334     *desc = This->pcsg->elements[index];
335
336     return S_OK;
337 }
338
339 static struct ID3D11ShaderReflectionVariable * STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetVariableByName(
340         ID3D11ShaderReflection *iface, LPCSTR name)
341 {
342     FIXME("iface %p, name %s stub!\n", iface, name);
343
344     return NULL;
345 }
346
347 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetResourceBindingDescByName(
348         ID3D11ShaderReflection *iface, LPCSTR name, D3D11_SHADER_INPUT_BIND_DESC *desc)
349 {
350     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
351     unsigned int i;
352
353     TRACE("iface %p, name %s, desc %p\n", iface, debugstr_a(name), desc);
354
355     if (!desc || !name)
356     {
357         WARN("Invalid argument specified\n");
358         return E_INVALIDARG;
359     }
360
361     for (i = 0; i < This->bound_resource_count; ++i)
362     {
363         D3D11_SHADER_INPUT_BIND_DESC *d = &This->bound_resources[i];
364
365         if (!strcmp(d->Name, name))
366         {
367             TRACE("Returning D3D11_SHADER_INPUT_BIND_DESC %p.\n", d);
368             *desc = *d;
369             return S_OK;
370         }
371     }
372
373     WARN("Invalid name specified\n");
374
375     return E_INVALIDARG;
376 }
377
378 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMovInstructionCount(
379         ID3D11ShaderReflection *iface)
380 {
381     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
382
383     TRACE("iface %p\n", iface);
384
385     return This->mov_instruction_count;
386 }
387
388 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMovcInstructionCount(
389         ID3D11ShaderReflection *iface)
390 {
391     FIXME("iface %p stub!\n", iface);
392
393     return 0;
394 }
395
396 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetConversionInstructionCount(
397         ID3D11ShaderReflection *iface)
398 {
399     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
400
401     TRACE("iface %p\n", iface);
402
403     return This->conversion_instruction_count;
404 }
405
406 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetBitwiseInstructionCount(
407         ID3D11ShaderReflection *iface)
408 {
409     FIXME("iface %p stub!\n", iface);
410
411     return 0;
412 }
413
414 static D3D_PRIMITIVE STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetGSInputPrimitive(
415         ID3D11ShaderReflection *iface)
416 {
417     FIXME("iface %p stub!\n", iface);
418
419     return 0;
420 }
421
422 static BOOL STDMETHODCALLTYPE d3dcompiler_shader_reflection_IsSampleFrequencyShader(
423         ID3D11ShaderReflection *iface)
424 {
425     FIXME("iface %p stub!\n", iface);
426
427     return 0;
428 }
429
430 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetNumInterfaceSlots(
431         ID3D11ShaderReflection *iface)
432 {
433     FIXME("iface %p stub!\n", iface);
434
435     return 0;
436 }
437
438 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMinFeatureLevel(
439         ID3D11ShaderReflection *iface, D3D_FEATURE_LEVEL *level)
440 {
441     FIXME("iface %p, level %p stub!\n", iface, level);
442
443     return E_NOTIMPL;
444 }
445
446 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetThreadGroupSize(
447         ID3D11ShaderReflection *iface, UINT *sizex, UINT *sizey, UINT *sizez)
448 {
449     FIXME("iface %p, sizex %p, sizey %p, sizez %p stub!\n", iface, sizex, sizey, sizez);
450
451     return 0;
452 }
453
454 const struct ID3D11ShaderReflectionVtbl d3dcompiler_shader_reflection_vtbl =
455 {
456     /* IUnknown methods */
457     d3dcompiler_shader_reflection_QueryInterface,
458     d3dcompiler_shader_reflection_AddRef,
459     d3dcompiler_shader_reflection_Release,
460     /* ID3D11ShaderReflection methods */
461     d3dcompiler_shader_reflection_GetDesc,
462     d3dcompiler_shader_reflection_GetConstantBufferByIndex,
463     d3dcompiler_shader_reflection_GetConstantBufferByName,
464     d3dcompiler_shader_reflection_GetResourceBindingDesc,
465     d3dcompiler_shader_reflection_GetInputParameterDesc,
466     d3dcompiler_shader_reflection_GetOutputParameterDesc,
467     d3dcompiler_shader_reflection_GetPatchConstantParameterDesc,
468     d3dcompiler_shader_reflection_GetVariableByName,
469     d3dcompiler_shader_reflection_GetResourceBindingDescByName,
470     d3dcompiler_shader_reflection_GetMovInstructionCount,
471     d3dcompiler_shader_reflection_GetMovcInstructionCount,
472     d3dcompiler_shader_reflection_GetConversionInstructionCount,
473     d3dcompiler_shader_reflection_GetBitwiseInstructionCount,
474     d3dcompiler_shader_reflection_GetGSInputPrimitive,
475     d3dcompiler_shader_reflection_IsSampleFrequencyShader,
476     d3dcompiler_shader_reflection_GetNumInterfaceSlots,
477     d3dcompiler_shader_reflection_GetMinFeatureLevel,
478     d3dcompiler_shader_reflection_GetThreadGroupSize,
479 };
480
481 /* ID3D11ShaderReflectionConstantBuffer methods */
482
483 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_constant_buffer_GetDesc(
484         ID3D11ShaderReflectionConstantBuffer *iface, D3D11_SHADER_BUFFER_DESC *desc)
485 {
486     FIXME("iface %p, desc %p stub!\n", iface, desc);
487
488     return E_NOTIMPL;
489 }
490
491 static ID3D11ShaderReflectionVariable * STDMETHODCALLTYPE d3dcompiler_shader_reflection_constant_buffer_GetVariableByIndex(
492         ID3D11ShaderReflectionConstantBuffer *iface, UINT index)
493 {
494     FIXME("iface %p, index %u stub!\n", iface, index);
495
496     return NULL;
497 }
498
499 static ID3D11ShaderReflectionVariable * STDMETHODCALLTYPE d3dcompiler_shader_reflection_constant_buffer_GetVariableByName(
500         ID3D11ShaderReflectionConstantBuffer *iface, LPCSTR name)
501 {
502     FIXME("iface %p, name %s stub!\n", iface, name);
503
504     return NULL;
505 }
506
507 const struct ID3D11ShaderReflectionConstantBufferVtbl d3dcompiler_shader_reflection_constant_buffer_vtbl =
508 {
509     /* ID3D11ShaderReflectionConstantBuffer methods */
510     d3dcompiler_shader_reflection_constant_buffer_GetDesc,
511     d3dcompiler_shader_reflection_constant_buffer_GetVariableByIndex,
512     d3dcompiler_shader_reflection_constant_buffer_GetVariableByName,
513 };
514
515 static HRESULT d3dcompiler_parse_stat(struct d3dcompiler_shader_reflection *r, const char *data, DWORD data_size)
516 {
517     const char *ptr = data;
518     DWORD size = data_size >> 2;
519
520     TRACE("Size %u\n", size);
521
522     read_dword(&ptr, &r->instruction_count);
523     TRACE("InstructionCount: %u\n", r->instruction_count);
524
525     read_dword(&ptr, &r->temp_register_count);
526     TRACE("TempRegisterCount: %u\n", r->temp_register_count);
527
528     skip_dword_unknown(&ptr, 1);
529
530     read_dword(&ptr, &r->dcl_count);
531     TRACE("DclCount: %u\n", r->dcl_count);
532
533     read_dword(&ptr, &r->float_instruction_count);
534     TRACE("FloatInstructionCount: %u\n", r->float_instruction_count);
535
536     read_dword(&ptr, &r->int_instruction_count);
537     TRACE("IntInstructionCount: %u\n", r->int_instruction_count);
538
539     read_dword(&ptr, &r->uint_instruction_count);
540     TRACE("UintInstructionCount: %u\n", r->uint_instruction_count);
541
542     read_dword(&ptr, &r->static_flow_control_count);
543     TRACE("StaticFlowControlCount: %u\n", r->static_flow_control_count);
544
545     read_dword(&ptr, &r->dynamic_flow_control_count);
546     TRACE("DynamicFlowControlCount: %u\n", r->dynamic_flow_control_count);
547
548     skip_dword_unknown(&ptr, 1);
549
550     read_dword(&ptr, &r->temp_array_count);
551     TRACE("TempArrayCount: %u\n", r->temp_array_count);
552
553     read_dword(&ptr, &r->array_instruction_count);
554     TRACE("ArrayInstructionCount: %u\n", r->array_instruction_count);
555
556     read_dword(&ptr, &r->cut_instruction_count);
557     TRACE("CutInstructionCount: %u\n", r->cut_instruction_count);
558
559     read_dword(&ptr, &r->emit_instruction_count);
560     TRACE("EmitInstructionCount: %u\n", r->emit_instruction_count);
561
562     read_dword(&ptr, &r->texture_normal_instructions);
563     TRACE("TextureNormalInstructions: %u\n", r->texture_normal_instructions);
564
565     read_dword(&ptr, &r->texture_load_instructions);
566     TRACE("TextureLoadInstructions: %u\n", r->texture_load_instructions);
567
568     read_dword(&ptr, &r->texture_comp_instructions);
569     TRACE("TextureCompInstructions: %u\n", r->texture_comp_instructions);
570
571     read_dword(&ptr, &r->texture_bias_instructions);
572     TRACE("TextureBiasInstructions: %u\n", r->texture_bias_instructions);
573
574     read_dword(&ptr, &r->texture_gradient_instructions);
575     TRACE("TextureGradientInstructions: %u\n", r->texture_gradient_instructions);
576
577     read_dword(&ptr, &r->mov_instruction_count);
578     TRACE("MovInstructionCount: %u\n", r->mov_instruction_count);
579
580     skip_dword_unknown(&ptr, 1);
581
582     read_dword(&ptr, &r->conversion_instruction_count);
583     TRACE("ConversionInstructionCount: %u\n", r->conversion_instruction_count);
584
585     skip_dword_unknown(&ptr, 1);
586
587     read_dword(&ptr, &r->input_primitive);
588     TRACE("InputPrimitive: %x\n", r->input_primitive);
589
590     read_dword(&ptr, &r->gs_output_topology);
591     TRACE("GSOutputTopology: %x\n", r->gs_output_topology);
592
593     read_dword(&ptr, &r->gs_max_output_vertex_count);
594     TRACE("GSMaxOutputVertexCount: %u\n", r->gs_max_output_vertex_count);
595
596     skip_dword_unknown(&ptr, 3);
597
598     /* dx10 stat size */
599     if (size == 29) return S_OK;
600
601     skip_dword_unknown(&ptr, 1);
602
603     read_dword(&ptr, &r->c_control_points);
604     TRACE("cControlPoints: %u\n", r->c_control_points);
605
606     read_dword(&ptr, &r->hs_output_primitive);
607     TRACE("HSOutputPrimitive: %x\n", r->hs_output_primitive);
608
609     read_dword(&ptr, &r->hs_prtitioning);
610     TRACE("HSPartitioning: %x\n", r->hs_prtitioning);
611
612     read_dword(&ptr, &r->tessellator_domain);
613     TRACE("TessellatorDomain: %x\n", r->tessellator_domain);
614
615     skip_dword_unknown(&ptr, 3);
616
617     /* dx11 stat size */
618     if (size == 37) return S_OK;
619
620     FIXME("Unhandled size %u\n", size);
621
622     return E_FAIL;
623 }
624
625 static HRESULT d3dcompiler_parse_rdef(struct d3dcompiler_shader_reflection *r, const char *data, DWORD data_size)
626 {
627     const char *ptr = data;
628     DWORD size = data_size >> 2;
629     DWORD offset, cbuffer_offset, resource_offset, creator_offset;
630     unsigned int i, string_data_offset, string_data_size;
631     char *string_data = NULL, *creator = NULL;
632     D3D11_SHADER_INPUT_BIND_DESC *bound_resources = NULL;
633     struct d3dcompiler_shader_reflection_constant_buffer *constant_buffers = NULL;
634     HRESULT hr;
635
636     TRACE("Size %u\n", size);
637
638     read_dword(&ptr, &r->constant_buffer_count);
639     TRACE("Constant buffer count: %u\n", r->constant_buffer_count);
640
641     read_dword(&ptr, &cbuffer_offset);
642     TRACE("Constant buffer offset: %#x\n", cbuffer_offset);
643
644     read_dword(&ptr, &r->bound_resource_count);
645     TRACE("Bound resource count: %u\n", r->bound_resource_count);
646
647     read_dword(&ptr, &resource_offset);
648     TRACE("Bound resource offset: %#x\n", resource_offset);
649
650     read_dword(&ptr, &r->target);
651     TRACE("Target: %#x\n", r->target);
652
653     read_dword(&ptr, &r->flags);
654     TRACE("Flags: %u\n", r->flags);
655
656     read_dword(&ptr, &creator_offset);
657     TRACE("Creator at offset %#x.\n", creator_offset);
658
659     if (!copy_name(data + creator_offset, &creator))
660     {
661         ERR("Failed to copy name.\n");
662         return E_OUTOFMEMORY;
663     }
664     TRACE("Creator: %s.\n", debugstr_a(creator));
665
666     /* todo: Parse RD11 */
667     if ((r->target & 0x0000ffff) >= 0x500)
668     {
669         skip_dword_unknown(&ptr, 8);
670     }
671
672     if (r->bound_resource_count)
673     {
674         /* 8 for each bind desc */
675         string_data_offset = resource_offset + r->bound_resource_count * 8 * sizeof(DWORD);
676         string_data_size = (cbuffer_offset ? cbuffer_offset : creator_offset) - string_data_offset;
677
678         string_data = HeapAlloc(GetProcessHeap(), 0, string_data_size);
679         if (!string_data)
680         {
681             ERR("Failed to allocate string data memory.\n");
682             hr = E_OUTOFMEMORY;
683             goto err_out;
684         }
685         memcpy(string_data, data + string_data_offset, string_data_size);
686
687         bound_resources = HeapAlloc(GetProcessHeap(), 0, r->bound_resource_count * sizeof(*bound_resources));
688         if (!bound_resources)
689         {
690             ERR("Failed to allocate resources memory.\n");
691             hr = E_OUTOFMEMORY;
692             goto err_out;
693         }
694
695         ptr = data + resource_offset;
696         for (i = 0; i < r->bound_resource_count; i++)
697         {
698             D3D11_SHADER_INPUT_BIND_DESC *desc = &bound_resources[i];
699
700             read_dword(&ptr, &offset);
701             desc->Name = string_data + (offset - string_data_offset);
702             TRACE("Input bind Name: %s\n", debugstr_a(desc->Name));
703
704             read_dword(&ptr, &desc->Type);
705             TRACE("Input bind Type: %#x\n", desc->Type);
706
707             read_dword(&ptr, &desc->ReturnType);
708             TRACE("Input bind ReturnType: %#x\n", desc->ReturnType);
709
710             read_dword(&ptr, &desc->Dimension);
711             TRACE("Input bind Dimension: %#x\n", desc->Dimension);
712
713             read_dword(&ptr, &desc->NumSamples);
714             TRACE("Input bind NumSamples: %u\n", desc->NumSamples);
715
716             read_dword(&ptr, &desc->BindPoint);
717             TRACE("Input bind BindPoint: %u\n", desc->BindPoint);
718
719             read_dword(&ptr, &desc->BindCount);
720             TRACE("Input bind BindCount: %u\n", desc->BindCount);
721
722             read_dword(&ptr, &desc->uFlags);
723             TRACE("Input bind uFlags: %u\n", desc->uFlags);
724         }
725     }
726
727     if (r->constant_buffer_count)
728     {
729         constant_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, r->constant_buffer_count * sizeof(*constant_buffers));
730         if (!constant_buffers)
731         {
732             ERR("Failed to allocate constant buffer memory.\n");
733             hr = E_OUTOFMEMORY;
734             goto err_out;
735         }
736
737         ptr = data + cbuffer_offset;
738         for (i = 0; i < r->constant_buffer_count; i++)
739         {
740             struct d3dcompiler_shader_reflection_constant_buffer *cb = &constant_buffers[i];
741
742             cb->ID3D11ShaderReflectionConstantBuffer_iface.lpVtbl = &d3dcompiler_shader_reflection_constant_buffer_vtbl;
743             cb->reflection = r;
744
745             read_dword(&ptr, &offset);
746             if (!copy_name(data + offset, &cb->name))
747             {
748                 ERR("Failed to copy name.\n");
749                 hr = E_OUTOFMEMORY;
750                 goto err_out;
751             }
752             TRACE("Name: %s.\n", debugstr_a(cb->name));
753
754             read_dword(&ptr, &cb->variable_count);
755             TRACE("Variable count: %u\n", cb->variable_count);
756
757             /* todo: Parse variables */
758             read_dword(&ptr, &offset);
759             FIXME("Variable offset: %x\n", offset);
760
761             read_dword(&ptr, &cb->size);
762             TRACE("Cbuffer size: %u\n", cb->size);
763
764             read_dword(&ptr, &cb->flags);
765             TRACE("Cbuffer flags: %u\n", cb->flags);
766
767             read_dword(&ptr, &cb->type);
768             TRACE("Cbuffer type: %#x\n", cb->type);
769         }
770     }
771
772     r->creator = creator;
773     r->resource_string = string_data;
774     r->bound_resources = bound_resources;
775     r->constant_buffers = constant_buffers;
776
777     return S_OK;
778
779 err_out:
780     for (i = 0; i < r->constant_buffer_count; ++i)
781     {
782         free_constant_buffer(&constant_buffers[i]);
783     }
784     HeapFree(GetProcessHeap(), 0, constant_buffers);
785     HeapFree(GetProcessHeap(), 0, bound_resources);
786     HeapFree(GetProcessHeap(), 0, string_data);
787     HeapFree(GetProcessHeap(), 0, creator);
788
789     return hr;
790 }
791
792 HRESULT d3dcompiler_parse_signature(struct d3dcompiler_shader_signature *s, struct dxbc_section *section)
793 {
794     D3D11_SIGNATURE_PARAMETER_DESC *d;
795     unsigned int string_data_offset;
796     unsigned int string_data_size;
797     const char *ptr = section->data;
798     char *string_data;
799     unsigned int i;
800     DWORD count;
801     enum D3DCOMPILER_SIGNATURE_ELEMENT_SIZE element_size;
802
803     switch (section->tag)
804     {
805         case TAG_OSG5:
806             element_size = D3DCOMPILER_SIGNATURE_ELEMENT_SIZE7;
807             break;
808
809         case TAG_ISGN:
810         case TAG_OSGN:
811         case TAG_PCSG:
812             element_size = D3DCOMPILER_SIGNATURE_ELEMENT_SIZE6;
813             break;
814
815         default:
816             FIXME("Unhandled section %s!\n", debugstr_an((const char *)&section->tag, 4));
817             element_size = D3DCOMPILER_SIGNATURE_ELEMENT_SIZE6;
818             break;
819     }
820
821     read_dword(&ptr, &count);
822     TRACE("%u elements\n", count);
823
824     skip_dword_unknown(&ptr, 1);
825
826     d = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*d));
827     if (!d)
828     {
829         ERR("Failed to allocate signature memory.\n");
830         return E_OUTOFMEMORY;
831     }
832
833     /* 2 DWORDs for the header, element_size for each element. */
834     string_data_offset = 2 * sizeof(DWORD) + count * element_size * sizeof(DWORD);
835     string_data_size = section->data_size - string_data_offset;
836
837     string_data = HeapAlloc(GetProcessHeap(), 0, string_data_size);
838     if (!string_data)
839     {
840         ERR("Failed to allocate string data memory.\n");
841         HeapFree(GetProcessHeap(), 0, d);
842         return E_OUTOFMEMORY;
843     }
844     memcpy(string_data, section->data + string_data_offset, string_data_size);
845
846     for (i = 0; i < count; ++i)
847     {
848         UINT name_offset;
849         DWORD mask;
850
851         if (element_size == D3DCOMPILER_SIGNATURE_ELEMENT_SIZE7)
852         {
853             read_dword(&ptr, &d[i].Stream);
854         }
855         else
856         {
857             d[i].Stream = 0;
858         }
859
860         read_dword(&ptr, &name_offset);
861         d[i].SemanticName = string_data + (name_offset - string_data_offset);
862         read_dword(&ptr, &d[i].SemanticIndex);
863         read_dword(&ptr, &d[i].SystemValueType);
864         read_dword(&ptr, &d[i].ComponentType);
865         read_dword(&ptr, &d[i].Register);
866         read_dword(&ptr, &mask);
867         d[i].ReadWriteMask = (mask >> 8) & 0xff;
868         d[i].Mask = mask & 0xff;
869
870         TRACE("semantic: %s, semantic idx: %u, sysval_semantic %#x, "
871                 "type %u, register idx: %u, use_mask %#x, input_mask %#x, stream %u\n",
872                 debugstr_a(d[i].SemanticName), d[i].SemanticIndex, d[i].SystemValueType,
873                 d[i].ComponentType, d[i].Register, d[i].Mask, d[i].ReadWriteMask, d[i].Stream);
874     }
875
876     s->elements = d;
877     s->element_count = count;
878     s->string_data = string_data;
879
880     return S_OK;
881 }
882
883 static HRESULT d3dcompiler_parse_shdr(struct d3dcompiler_shader_reflection *r, const char *data, DWORD data_size)
884 {
885     const char *ptr = data;
886
887     read_dword(&ptr, &r->version);
888     TRACE("Shader version: %u\n", r->version);
889
890     /* todo: Check if anything else is needed from the shdr or shex blob. */
891
892     return S_OK;
893 }
894
895 HRESULT d3dcompiler_shader_reflection_init(struct d3dcompiler_shader_reflection *reflection,
896         const void *data, SIZE_T data_size)
897 {
898     struct dxbc src_dxbc;
899     HRESULT hr;
900     unsigned int i;
901
902     reflection->ID3D11ShaderReflection_iface.lpVtbl = &d3dcompiler_shader_reflection_vtbl;
903     reflection->refcount = 1;
904
905     hr = dxbc_parse(data, data_size, &src_dxbc);
906     if (FAILED(hr))
907     {
908         WARN("Failed to parse reflection\n");
909         return hr;
910     }
911
912     for (i = 0; i < src_dxbc.count; ++i)
913     {
914         struct dxbc_section *section = &src_dxbc.sections[i];
915
916         switch (section->tag)
917         {
918             case TAG_STAT:
919                 hr = d3dcompiler_parse_stat(reflection, section->data, section->data_size);
920                 if (FAILED(hr))
921                 {
922                     WARN("Failed to parse section STAT.\n");
923                     goto err_out;
924                 }
925                 break;
926
927             case TAG_SHEX:
928             case TAG_SHDR:
929                 hr = d3dcompiler_parse_shdr(reflection, section->data, section->data_size);
930                 if (FAILED(hr))
931                 {
932                     WARN("Failed to parse SHDR section.\n");
933                     goto err_out;
934                 }
935                 break;
936
937             case TAG_RDEF:
938                 hr = d3dcompiler_parse_rdef(reflection, section->data, section->data_size);
939                 if (FAILED(hr))
940                 {
941                     WARN("Failed to parse RDEF section.\n");
942                     goto err_out;
943                 }
944                 break;
945
946             case TAG_ISGN:
947                 reflection->isgn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*reflection->isgn));
948                 if (!reflection->isgn)
949                 {
950                     ERR("Failed to allocate ISGN memory.\n");
951                     hr = E_OUTOFMEMORY;
952                     goto err_out;
953                 }
954
955                 hr = d3dcompiler_parse_signature(reflection->isgn, section);
956                 if (FAILED(hr))
957                 {
958                     WARN("Failed to parse section ISGN.\n");
959                     goto err_out;
960                 }
961                 break;
962
963             case TAG_OSG5:
964             case TAG_OSGN:
965                 reflection->osgn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*reflection->osgn));
966                 if (!reflection->osgn)
967                 {
968                     ERR("Failed to allocate OSGN memory.\n");
969                     hr = E_OUTOFMEMORY;
970                     goto err_out;
971                 }
972
973                 hr = d3dcompiler_parse_signature(reflection->osgn, section);
974                 if (FAILED(hr))
975                 {
976                     WARN("Failed to parse section OSGN.\n");
977                     goto err_out;
978                 }
979                 break;
980
981             case TAG_PCSG:
982                 reflection->pcsg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*reflection->pcsg));
983                 if (!reflection->pcsg)
984                 {
985                     ERR("Failed to allocate PCSG memory.\n");
986                     hr = E_OUTOFMEMORY;
987                     goto err_out;
988                 }
989
990                 hr = d3dcompiler_parse_signature(reflection->pcsg, section);
991                 if (FAILED(hr))
992                 {
993                     WARN("Failed to parse section PCSG.\n");
994                     goto err_out;
995                 }
996                 break;
997
998             default:
999                 FIXME("Unhandled section %s!\n", debugstr_an((const char *)&section->tag, 4));
1000                 break;
1001         }
1002     }
1003
1004     dxbc_destroy(&src_dxbc);
1005
1006     return hr;
1007
1008 err_out:
1009     reflection_cleanup(reflection);
1010     dxbc_destroy(&src_dxbc);
1011
1012     return hr;
1013 }