mshtml: Pass DispatchEx pointer instead of outer IUnknown to DispatchEx's vtbl functions.
[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     if (ref->osgn)
47     {
48         free_signature(ref->osgn);
49         HeapFree(GetProcessHeap(), 0, ref->osgn);
50     }
51
52     if (ref->pcsg)
53     {
54         free_signature(ref->pcsg);
55         HeapFree(GetProcessHeap(), 0, ref->pcsg);
56     }
57 }
58
59 static inline struct d3dcompiler_shader_reflection *impl_from_ID3D11ShaderReflection(ID3D11ShaderReflection *iface)
60 {
61     return CONTAINING_RECORD(iface, struct d3dcompiler_shader_reflection, ID3D11ShaderReflection_iface);
62 }
63
64 /* IUnknown methods */
65
66 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_QueryInterface(ID3D11ShaderReflection *iface, REFIID riid, void **object)
67 {
68     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
69
70     if (IsEqualGUID(riid, &IID_ID3D11ShaderReflection)
71             || IsEqualGUID(riid, &IID_IUnknown))
72     {
73         IUnknown_AddRef(iface);
74         *object = iface;
75         return S_OK;
76     }
77
78     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
79
80     *object = NULL;
81     return E_NOINTERFACE;
82 }
83
84 static ULONG STDMETHODCALLTYPE d3dcompiler_shader_reflection_AddRef(ID3D11ShaderReflection *iface)
85 {
86     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
87     ULONG refcount = InterlockedIncrement(&This->refcount);
88
89     TRACE("%p increasing refcount to %u\n", This, refcount);
90
91     return refcount;
92 }
93
94 static ULONG STDMETHODCALLTYPE d3dcompiler_shader_reflection_Release(ID3D11ShaderReflection *iface)
95 {
96     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
97     ULONG refcount = InterlockedDecrement(&This->refcount);
98
99     TRACE("%p decreasing refcount to %u\n", This, refcount);
100
101     if (!refcount)
102     {
103         reflection_cleanup(This);
104         HeapFree(GetProcessHeap(), 0, This);
105     }
106
107     return refcount;
108 }
109
110 /* ID3D11ShaderReflection methods */
111
112 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetDesc(ID3D11ShaderReflection *iface, D3D11_SHADER_DESC *desc)
113 {
114     FIXME("iface %p, desc %p stub!\n", iface, desc);
115
116     return E_NOTIMPL;
117 }
118
119 static struct ID3D11ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetConstantBufferByIndex(
120         ID3D11ShaderReflection *iface, UINT index)
121 {
122     FIXME("iface %p, index %u stub!\n", iface, index);
123
124     return NULL;
125 }
126
127 static struct ID3D11ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetConstantBufferByName(
128         ID3D11ShaderReflection *iface, LPCSTR name)
129 {
130     FIXME("iface %p, name \"%s\" stub!\n", iface, name);
131
132     return NULL;
133 }
134
135 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetResourceBindingDesc(
136         ID3D11ShaderReflection *iface, UINT index, D3D11_SHADER_INPUT_BIND_DESC *desc)
137 {
138     FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc);
139
140     return E_NOTIMPL;
141 }
142
143 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetInputParameterDesc(
144         ID3D11ShaderReflection *iface, UINT index, D3D11_SIGNATURE_PARAMETER_DESC *desc)
145 {
146     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
147
148     TRACE("iface %p, index %u, desc %p\n", iface, index, desc);
149
150     if (!desc || !This->isgn || index >= This->isgn->element_count)
151     {
152         WARN("Invalid argument specified\n");
153         return E_INVALIDARG;
154     }
155
156     *desc = This->isgn->elements[index];
157
158     return S_OK;
159 }
160
161 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetOutputParameterDesc(
162         ID3D11ShaderReflection *iface, UINT index, D3D11_SIGNATURE_PARAMETER_DESC *desc)
163 {
164     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
165
166     TRACE("iface %p, index %u, desc %p\n", iface, index, desc);
167
168     if (!desc || !This->osgn || index >= This->osgn->element_count)
169     {
170         WARN("Invalid argument specified\n");
171         return E_INVALIDARG;
172     }
173
174     *desc = This->osgn->elements[index];
175
176     return S_OK;
177 }
178
179 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetPatchConstantParameterDesc(
180         ID3D11ShaderReflection *iface, UINT index, D3D11_SIGNATURE_PARAMETER_DESC *desc)
181 {
182     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
183
184     TRACE("iface %p, index %u, desc %p\n", iface, index, desc);
185
186     if (!desc || !This->pcsg || index >= This->pcsg->element_count)
187     {
188         WARN("Invalid argument specified\n");
189         return E_INVALIDARG;
190     }
191
192     *desc = This->pcsg->elements[index];
193
194     return S_OK;
195 }
196
197 static struct ID3D11ShaderReflectionVariable * STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetVariableByName(
198         ID3D11ShaderReflection *iface, LPCSTR name)
199 {
200     FIXME("iface %p, name %s stub!\n", iface, name);
201
202     return NULL;
203 }
204
205 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetResourceBindingDescByName(
206         ID3D11ShaderReflection *iface, LPCSTR name, D3D11_SHADER_INPUT_BIND_DESC *desc)
207 {
208     FIXME("iface %p, name %s, desc %p stub!\n", iface, name, desc);
209
210     return E_NOTIMPL;
211 }
212
213 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMovInstructionCount(
214         ID3D11ShaderReflection *iface)
215 {
216     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
217
218     TRACE("iface %p\n", iface);
219
220     return This->mov_instruction_count;
221 }
222
223 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMovcInstructionCount(
224         ID3D11ShaderReflection *iface)
225 {
226     FIXME("iface %p stub!\n", iface);
227
228     return 0;
229 }
230
231 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetConversionInstructionCount(
232         ID3D11ShaderReflection *iface)
233 {
234     struct d3dcompiler_shader_reflection *This = impl_from_ID3D11ShaderReflection(iface);
235
236     TRACE("iface %p\n", iface);
237
238     return This->conversion_instruction_count;
239 }
240
241 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetBitwiseInstructionCount(
242         ID3D11ShaderReflection *iface)
243 {
244     FIXME("iface %p stub!\n", iface);
245
246     return 0;
247 }
248
249 static D3D_PRIMITIVE STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetGSInputPrimitive(
250         ID3D11ShaderReflection *iface)
251 {
252     FIXME("iface %p stub!\n", iface);
253
254     return 0;
255 }
256
257 static BOOL STDMETHODCALLTYPE d3dcompiler_shader_reflection_IsSampleFrequencyShader(
258         ID3D11ShaderReflection *iface)
259 {
260     FIXME("iface %p stub!\n", iface);
261
262     return 0;
263 }
264
265 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetNumInterfaceSlots(
266         ID3D11ShaderReflection *iface)
267 {
268     FIXME("iface %p stub!\n", iface);
269
270     return 0;
271 }
272
273 static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMinFeatureLevel(
274         ID3D11ShaderReflection *iface, D3D_FEATURE_LEVEL *level)
275 {
276     FIXME("iface %p, level %p stub!\n", iface, level);
277
278     return E_NOTIMPL;
279 }
280
281 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetThreadGroupSize(
282         ID3D11ShaderReflection *iface, UINT *sizex, UINT *sizey, UINT *sizez)
283 {
284     FIXME("iface %p, sizex %p, sizey %p, sizez %p stub!\n", iface, sizex, sizey, sizez);
285
286     return 0;
287 }
288
289 const struct ID3D11ShaderReflectionVtbl d3dcompiler_shader_reflection_vtbl =
290 {
291     /* IUnknown methods */
292     d3dcompiler_shader_reflection_QueryInterface,
293     d3dcompiler_shader_reflection_AddRef,
294     d3dcompiler_shader_reflection_Release,
295     /* ID3D11ShaderReflection methods */
296     d3dcompiler_shader_reflection_GetDesc,
297     d3dcompiler_shader_reflection_GetConstantBufferByIndex,
298     d3dcompiler_shader_reflection_GetConstantBufferByName,
299     d3dcompiler_shader_reflection_GetResourceBindingDesc,
300     d3dcompiler_shader_reflection_GetInputParameterDesc,
301     d3dcompiler_shader_reflection_GetOutputParameterDesc,
302     d3dcompiler_shader_reflection_GetPatchConstantParameterDesc,
303     d3dcompiler_shader_reflection_GetVariableByName,
304     d3dcompiler_shader_reflection_GetResourceBindingDescByName,
305     d3dcompiler_shader_reflection_GetMovInstructionCount,
306     d3dcompiler_shader_reflection_GetMovcInstructionCount,
307     d3dcompiler_shader_reflection_GetConversionInstructionCount,
308     d3dcompiler_shader_reflection_GetBitwiseInstructionCount,
309     d3dcompiler_shader_reflection_GetGSInputPrimitive,
310     d3dcompiler_shader_reflection_IsSampleFrequencyShader,
311     d3dcompiler_shader_reflection_GetNumInterfaceSlots,
312     d3dcompiler_shader_reflection_GetMinFeatureLevel,
313     d3dcompiler_shader_reflection_GetThreadGroupSize,
314 };
315
316 static HRESULT d3dcompiler_parse_stat(struct d3dcompiler_shader_reflection *r, const char *data, DWORD data_size)
317 {
318     const char *ptr = data;
319     DWORD size = data_size >> 2;
320
321     TRACE("Size %u\n", size);
322
323     read_dword(&ptr, &r->instruction_count);
324     TRACE("InstructionCount: %u\n", r->instruction_count);
325
326     read_dword(&ptr, &r->temp_register_count);
327     TRACE("TempRegisterCount: %u\n", r->temp_register_count);
328
329     skip_dword_unknown(&ptr, 1);
330
331     read_dword(&ptr, &r->dcl_count);
332     TRACE("DclCount: %u\n", r->dcl_count);
333
334     read_dword(&ptr, &r->float_instruction_count);
335     TRACE("FloatInstructionCount: %u\n", r->float_instruction_count);
336
337     read_dword(&ptr, &r->int_instruction_count);
338     TRACE("IntInstructionCount: %u\n", r->int_instruction_count);
339
340     read_dword(&ptr, &r->uint_instruction_count);
341     TRACE("UintInstructionCount: %u\n", r->uint_instruction_count);
342
343     read_dword(&ptr, &r->static_flow_control_count);
344     TRACE("StaticFlowControlCount: %u\n", r->static_flow_control_count);
345
346     read_dword(&ptr, &r->dynamic_flow_control_count);
347     TRACE("DynamicFlowControlCount: %u\n", r->dynamic_flow_control_count);
348
349     skip_dword_unknown(&ptr, 1);
350
351     read_dword(&ptr, &r->temp_array_count);
352     TRACE("TempArrayCount: %u\n", r->temp_array_count);
353
354     read_dword(&ptr, &r->array_instruction_count);
355     TRACE("ArrayInstructionCount: %u\n", r->array_instruction_count);
356
357     read_dword(&ptr, &r->cut_instruction_count);
358     TRACE("CutInstructionCount: %u\n", r->cut_instruction_count);
359
360     read_dword(&ptr, &r->emit_instruction_count);
361     TRACE("EmitInstructionCount: %u\n", r->emit_instruction_count);
362
363     read_dword(&ptr, &r->texture_normal_instructions);
364     TRACE("TextureNormalInstructions: %u\n", r->texture_normal_instructions);
365
366     read_dword(&ptr, &r->texture_load_instructions);
367     TRACE("TextureLoadInstructions: %u\n", r->texture_load_instructions);
368
369     read_dword(&ptr, &r->texture_comp_instructions);
370     TRACE("TextureCompInstructions: %u\n", r->texture_comp_instructions);
371
372     read_dword(&ptr, &r->texture_bias_instructions);
373     TRACE("TextureBiasInstructions: %u\n", r->texture_bias_instructions);
374
375     read_dword(&ptr, &r->texture_gradient_instructions);
376     TRACE("TextureGradientInstructions: %u\n", r->texture_gradient_instructions);
377
378     read_dword(&ptr, &r->mov_instruction_count);
379     TRACE("MovInstructionCount: %u\n", r->mov_instruction_count);
380
381     skip_dword_unknown(&ptr, 1);
382
383     read_dword(&ptr, &r->conversion_instruction_count);
384     TRACE("ConversionInstructionCount: %u\n", r->conversion_instruction_count);
385
386     skip_dword_unknown(&ptr, 1);
387
388     read_dword(&ptr, &r->input_primitive);
389     TRACE("InputPrimitive: %x\n", r->input_primitive);
390
391     read_dword(&ptr, &r->gs_output_topology);
392     TRACE("GSOutputTopology: %x\n", r->gs_output_topology);
393
394     read_dword(&ptr, &r->gs_max_output_vertex_count);
395     TRACE("GSMaxOutputVertexCount: %u\n", r->gs_max_output_vertex_count);
396
397     skip_dword_unknown(&ptr, 3);
398
399     /* dx10 stat size */
400     if (size == 29) return S_OK;
401
402     skip_dword_unknown(&ptr, 1);
403
404     read_dword(&ptr, &r->c_control_points);
405     TRACE("cControlPoints: %u\n", r->c_control_points);
406
407     read_dword(&ptr, &r->hs_output_primitive);
408     TRACE("HSOutputPrimitive: %x\n", r->hs_output_primitive);
409
410     read_dword(&ptr, &r->hs_prtitioning);
411     TRACE("HSPartitioning: %x\n", r->hs_prtitioning);
412
413     read_dword(&ptr, &r->tessellator_domain);
414     TRACE("TessellatorDomain: %x\n", r->tessellator_domain);
415
416     skip_dword_unknown(&ptr, 3);
417
418     /* dx11 stat size */
419     if (size == 37) return S_OK;
420
421     FIXME("Unhandled size %u\n", size);
422
423     return E_FAIL;
424 }
425
426 HRESULT d3dcompiler_parse_signature(struct d3dcompiler_shader_signature *s, const char *data, DWORD data_size)
427 {
428     D3D11_SIGNATURE_PARAMETER_DESC *d;
429     unsigned int string_data_offset;
430     unsigned int string_data_size;
431     const char *ptr = data;
432     char *string_data;
433     unsigned int i;
434     DWORD count;
435
436     read_dword(&ptr, &count);
437     TRACE("%u elements\n", count);
438
439     skip_dword_unknown(&ptr, 1);
440
441     d = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*d));
442     if (!d)
443     {
444         ERR("Failed to allocate signature memory.\n");
445         return E_OUTOFMEMORY;
446     }
447
448     /* 2 DWORDs for the header, 6 for each element. */
449     string_data_offset = 2 * sizeof(DWORD) + count * 6 * sizeof(DWORD);
450     string_data_size = data_size - string_data_offset;
451     string_data = HeapAlloc(GetProcessHeap(), 0, string_data_size);
452     if (!string_data)
453     {
454         ERR("Failed to allocate string data memory.\n");
455         HeapFree(GetProcessHeap(), 0, d);
456         return E_OUTOFMEMORY;
457     }
458     memcpy(string_data, data + string_data_offset, string_data_size);
459
460     for (i = 0; i < count; ++i)
461     {
462         UINT name_offset;
463         DWORD mask;
464
465         /* todo: Parse stream in shaderblobs v5 (dx11) */
466         d[i].Stream = 0;
467
468         read_dword(&ptr, &name_offset);
469         d[i].SemanticName = string_data + (name_offset - string_data_offset);
470         read_dword(&ptr, &d[i].SemanticIndex);
471         read_dword(&ptr, &d[i].SystemValueType);
472         read_dword(&ptr, &d[i].ComponentType);
473         read_dword(&ptr, &d[i].Register);
474         read_dword(&ptr, &mask);
475         d[i].ReadWriteMask = (mask >> 8) & 0xff;
476         d[i].Mask = mask & 0xff;
477
478         TRACE("semantic: %s, semantic idx: %u, sysval_semantic %#x, "
479                 "type %u, register idx: %u, use_mask %#x, input_mask %#x, stream %u\n",
480                 debugstr_a(d[i].SemanticName), d[i].SemanticIndex, d[i].SystemValueType,
481                 d[i].ComponentType, d[i].Register, d[i].Mask, d[i].ReadWriteMask, d[i].Stream);
482     }
483
484     s->elements = d;
485     s->element_count = count;
486     s->string_data = string_data;
487
488     return S_OK;
489 }
490
491 HRESULT d3dcompiler_shader_reflection_init(struct d3dcompiler_shader_reflection *reflection,
492         const void *data, SIZE_T data_size)
493 {
494     struct dxbc src_dxbc;
495     HRESULT hr;
496     unsigned int i;
497
498     reflection->ID3D11ShaderReflection_iface.lpVtbl = &d3dcompiler_shader_reflection_vtbl;
499     reflection->refcount = 1;
500
501     hr = dxbc_parse(data, data_size, &src_dxbc);
502     if (FAILED(hr))
503     {
504         WARN("Failed to parse reflection\n");
505         return hr;
506     }
507
508     for (i = 0; i < src_dxbc.count; ++i)
509     {
510         struct dxbc_section *section = &src_dxbc.sections[i];
511
512         switch (section->tag)
513         {
514             case TAG_STAT:
515                 hr = d3dcompiler_parse_stat(reflection, section->data, section->data_size);
516                 if (FAILED(hr))
517                 {
518                     WARN("Failed to parse section STAT.\n");
519                     goto err_out;
520                 }
521                 break;
522
523             case TAG_ISGN:
524                 reflection->isgn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*reflection->isgn));
525                 if (!reflection->isgn)
526                 {
527                     ERR("Failed to allocate ISGN memory.\n");
528                     hr = E_OUTOFMEMORY;
529                     goto err_out;
530                 }
531
532                 hr = d3dcompiler_parse_signature(reflection->isgn, section->data, section->data_size);
533                 if (FAILED(hr))
534                 {
535                     WARN("Failed to parse section ISGN.\n");
536                     goto err_out;
537                 }
538                 break;
539
540             case TAG_OSGN:
541                 reflection->osgn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*reflection->osgn));
542                 if (!reflection->osgn)
543                 {
544                     ERR("Failed to allocate OSGN memory.\n");
545                     hr = E_OUTOFMEMORY;
546                     goto err_out;
547                 }
548
549                 hr = d3dcompiler_parse_signature(reflection->osgn, section->data, section->data_size);
550                 if (FAILED(hr))
551                 {
552                     WARN("Failed to parse section OSGN.\n");
553                     goto err_out;
554                 }
555                 break;
556
557             case TAG_PCSG:
558                 reflection->pcsg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*reflection->pcsg));
559                 if (!reflection->pcsg)
560                 {
561                     ERR("Failed to allocate PCSG memory.\n");
562                     hr = E_OUTOFMEMORY;
563                     goto err_out;
564                 }
565
566                 hr = d3dcompiler_parse_signature(reflection->pcsg, section->data, section->data_size);
567                 if (FAILED(hr))
568                 {
569                     WARN("Failed to parse section PCSG.\n");
570                     goto err_out;
571                 }
572                 break;
573
574             default:
575                 FIXME("Unhandled section %s!\n", debugstr_an((const char *)&section->tag, 4));
576                 break;
577         }
578     }
579
580     dxbc_destroy(&src_dxbc);
581
582     return hr;
583
584 err_out:
585     reflection_cleanup(reflection);
586     dxbc_destroy(&src_dxbc);
587
588     return hr;
589 }