server: Create the initial thread as a separate request.
[wine.git] / dlls / d3d11 / shader.c
blobc8d512f4d18f435dea65d60edc9f383964a4f37a
1 /*
2 * Copyright 2009 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include "d3d11_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d11);
27 struct aon9_header
29 DWORD chunk_size;
30 DWORD shader_version;
31 DWORD unknown;
32 DWORD byte_code_offset;
35 struct shader_handler_context
37 D3D_FEATURE_LEVEL feature_level;
38 struct wined3d_shader_desc *desc;
41 static HRESULT shdr_handler(const char *data, DWORD data_size, DWORD tag, void *context)
43 const struct shader_handler_context *ctx = context;
44 struct wined3d_shader_desc *desc = ctx->desc;
45 HRESULT hr;
47 switch (tag)
49 case TAG_ISGN:
50 if (ctx->feature_level <= D3D_FEATURE_LEVEL_9_3)
52 TRACE("Skipping shader input signature on feature level %#x.\n", ctx->feature_level);
53 break;
55 if (desc->input_signature.elements)
57 FIXME("Multiple input signatures.\n");
58 break;
60 if (FAILED(hr = shader_parse_signature(tag, data, data_size, &desc->input_signature)))
61 return hr;
62 break;
64 case TAG_OSGN:
65 case TAG_OSG5:
66 if (ctx->feature_level <= D3D_FEATURE_LEVEL_9_3)
68 TRACE("Skipping shader output signature on feature level %#x.\n", ctx->feature_level);
69 break;
71 if (desc->output_signature.elements)
73 FIXME("Multiple output signatures.\n");
74 break;
76 if (FAILED(hr = shader_parse_signature(tag, data, data_size, &desc->output_signature)))
77 return hr;
78 break;
80 case TAG_PCSG:
81 if (desc->patch_constant_signature.elements)
83 FIXME("Multiple patch constant signatures.\n");
84 break;
86 if (FAILED(hr = shader_parse_signature(tag, data, data_size, &desc->patch_constant_signature)))
87 return hr;
88 break;
90 case TAG_SHDR:
91 case TAG_SHEX:
92 if (ctx->feature_level <= D3D_FEATURE_LEVEL_9_3)
94 TRACE("Skipping SM4+ shader code on feature level %#x.\n", ctx->feature_level);
95 break;
97 if (desc->byte_code)
98 FIXME("Multiple shader code chunks.\n");
99 desc->byte_code = (const DWORD *)data;
100 desc->byte_code_size = data_size;
101 desc->format = WINED3D_SHADER_BYTE_CODE_FORMAT_SM4;
102 break;
104 case TAG_AON9:
105 if (ctx->feature_level <= D3D_FEATURE_LEVEL_9_3)
107 const struct aon9_header *header = (const struct aon9_header *)data;
108 unsigned int unknown_dword_count;
109 const char *byte_code;
111 if (data_size < sizeof(*header))
113 WARN("Invalid Aon9 data size %#x.\n", data_size);
114 return E_FAIL;
116 byte_code = data + header->byte_code_offset;
117 unknown_dword_count = (header->byte_code_offset - sizeof(*header)) / sizeof(DWORD);
119 if (data_size - 2 * sizeof(DWORD) < header->byte_code_offset)
121 WARN("Invalid byte code offset %#x (size %#x).\n", header->byte_code_offset, data_size);
122 return E_FAIL;
124 FIXME("Skipping %u unknown DWORDs.\n", unknown_dword_count);
126 if (desc->byte_code)
127 FIXME("Multiple shader code chunks.\n");
128 desc->byte_code = (const DWORD *)byte_code;
129 desc->byte_code_size = data_size - header->byte_code_offset;
130 desc->format = WINED3D_SHADER_BYTE_CODE_FORMAT_SM1;
131 TRACE("Feature level 9 shader version 0%08x, 0%08x.\n", header->shader_version, *desc->byte_code);
133 else
135 TRACE("Skipping feature level 9 shader code on feature level %#x.\n", ctx->feature_level);
137 break;
139 case TAG_RDEF:
140 case TAG_STAT:
141 break;
143 default:
144 FIXME("Unhandled chunk %s.\n", debugstr_an((const char *)&tag, 4));
145 break;
148 return S_OK;
151 static void free_shader_desc(struct wined3d_shader_desc *desc)
153 shader_free_signature(&desc->input_signature);
154 shader_free_signature(&desc->output_signature);
155 shader_free_signature(&desc->patch_constant_signature);
158 static HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length,
159 struct wined3d_shader_desc *desc, D3D_FEATURE_LEVEL feature_level)
161 struct shader_handler_context ctx = {feature_level, desc};
162 HRESULT hr;
164 desc->byte_code = NULL;
165 desc->byte_code_size = 0;
166 memset(&desc->input_signature, 0, sizeof(desc->input_signature));
167 memset(&desc->output_signature, 0, sizeof(desc->output_signature));
168 memset(&desc->patch_constant_signature, 0, sizeof(desc->patch_constant_signature));
170 hr = parse_dxbc(dxbc, dxbc_length, shdr_handler, &ctx);
171 if (!desc->byte_code)
172 hr = E_INVALIDARG;
174 if (FAILED(hr))
176 FIXME("Failed to parse shader, hr %#x.\n", hr);
177 free_shader_desc(desc);
180 return hr;
183 static const char *shader_get_string(const char *data, size_t data_size, DWORD offset)
185 size_t len, max_len;
187 if (offset >= data_size)
189 WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size);
190 return NULL;
193 max_len = data_size - offset;
194 len = strnlen(data + offset, max_len);
196 if (len == max_len)
197 return NULL;
199 return data + offset;
202 HRESULT shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
203 struct wined3d_shader_signature *s)
205 struct wined3d_shader_signature_element *e;
206 const char *ptr = data;
207 unsigned int i;
208 DWORD count;
210 if (!require_space(0, 2, sizeof(DWORD), data_size))
212 WARN("Invalid data size %#x.\n", data_size);
213 return E_INVALIDARG;
216 read_dword(&ptr, &count);
217 TRACE("%u elements.\n", count);
219 skip_dword_unknown(&ptr, 1); /* It seems to always be 0x00000008. */
221 if (!require_space(ptr - data, count, 6 * sizeof(DWORD), data_size))
223 WARN("Invalid count %#x (data size %#x).\n", count, data_size);
224 return E_INVALIDARG;
227 if (!(e = heap_calloc(count, sizeof(*e))))
229 ERR("Failed to allocate input signature memory.\n");
230 return E_OUTOFMEMORY;
233 for (i = 0; i < count; ++i)
235 DWORD name_offset;
237 if (tag == TAG_OSG5)
238 read_dword(&ptr, &e[i].stream_idx);
239 else
240 e[i].stream_idx = 0;
241 read_dword(&ptr, &name_offset);
242 if (!(e[i].semantic_name = shader_get_string(data, data_size, name_offset)))
244 WARN("Invalid name offset %#x (data size %#x).\n", name_offset, data_size);
245 heap_free(e);
246 return E_INVALIDARG;
248 read_dword(&ptr, &e[i].semantic_idx);
249 read_dword(&ptr, &e[i].sysval_semantic);
250 read_dword(&ptr, &e[i].component_type);
251 read_dword(&ptr, &e[i].register_idx);
252 read_dword(&ptr, &e[i].mask);
254 TRACE("Stream: %u, semantic: %s, semantic idx: %u, sysval_semantic %#x, "
255 "type %u, register idx: %u, use_mask %#x, input_mask %#x.\n",
256 e[i].stream_idx, debugstr_a(e[i].semantic_name), e[i].semantic_idx, e[i].sysval_semantic,
257 e[i].component_type, e[i].register_idx, (e[i].mask >> 8) & 0xff, e[i].mask & 0xff);
260 s->elements = e;
261 s->element_count = count;
263 return S_OK;
266 struct wined3d_shader_signature_element *shader_find_signature_element(const struct wined3d_shader_signature *s,
267 const char *semantic_name, unsigned int semantic_idx, unsigned int stream_idx)
269 struct wined3d_shader_signature_element *e = s->elements;
270 unsigned int i;
272 for (i = 0; i < s->element_count; ++i)
274 if (!strcasecmp(e[i].semantic_name, semantic_name) && e[i].semantic_idx == semantic_idx
275 && e[i].stream_idx == stream_idx)
276 return &e[i];
279 return NULL;
282 void shader_free_signature(struct wined3d_shader_signature *s)
284 heap_free(s->elements);
287 /* ID3D11VertexShader methods */
289 static inline struct d3d_vertex_shader *impl_from_ID3D11VertexShader(ID3D11VertexShader *iface)
291 return CONTAINING_RECORD(iface, struct d3d_vertex_shader, ID3D11VertexShader_iface);
294 static HRESULT STDMETHODCALLTYPE d3d11_vertex_shader_QueryInterface(ID3D11VertexShader *iface,
295 REFIID riid, void **object)
297 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
299 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
301 if (IsEqualGUID(riid, &IID_ID3D11VertexShader)
302 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
303 || IsEqualGUID(riid, &IID_IUnknown))
305 ID3D11VertexShader_AddRef(iface);
306 *object = iface;
307 return S_OK;
310 if (IsEqualGUID(riid, &IID_ID3D10VertexShader)
311 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
313 IUnknown_AddRef(&shader->ID3D10VertexShader_iface);
314 *object = &shader->ID3D10VertexShader_iface;
315 return S_OK;
318 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
320 *object = NULL;
321 return E_NOINTERFACE;
324 static ULONG STDMETHODCALLTYPE d3d11_vertex_shader_AddRef(ID3D11VertexShader *iface)
326 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
327 ULONG refcount = InterlockedIncrement(&shader->refcount);
329 TRACE("%p increasing refcount to %u.\n", shader, refcount);
331 if (refcount == 1)
333 ID3D11Device2_AddRef(shader->device);
334 wined3d_mutex_lock();
335 wined3d_shader_incref(shader->wined3d_shader);
336 wined3d_mutex_unlock();
339 return refcount;
342 static ULONG STDMETHODCALLTYPE d3d11_vertex_shader_Release(ID3D11VertexShader *iface)
344 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
345 ULONG refcount = InterlockedDecrement(&shader->refcount);
347 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
349 if (!refcount)
351 ID3D11Device2 *device = shader->device;
353 wined3d_mutex_lock();
354 wined3d_shader_decref(shader->wined3d_shader);
355 wined3d_mutex_unlock();
356 /* Release the device last, it may cause the wined3d device to be
357 * destroyed. */
358 ID3D11Device2_Release(device);
361 return refcount;
364 static void STDMETHODCALLTYPE d3d11_vertex_shader_GetDevice(ID3D11VertexShader *iface,
365 ID3D11Device **device)
367 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
369 TRACE("iface %p, device %p.\n", iface, device);
371 *device = (ID3D11Device *)shader->device;
372 ID3D11Device_AddRef(*device);
375 static HRESULT STDMETHODCALLTYPE d3d11_vertex_shader_GetPrivateData(ID3D11VertexShader *iface,
376 REFGUID guid, UINT *data_size, void *data)
378 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
380 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
382 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
385 static HRESULT STDMETHODCALLTYPE d3d11_vertex_shader_SetPrivateData(ID3D11VertexShader *iface,
386 REFGUID guid, UINT data_size, const void *data)
388 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
390 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
392 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
395 static HRESULT STDMETHODCALLTYPE d3d11_vertex_shader_SetPrivateDataInterface(ID3D11VertexShader *iface,
396 REFGUID guid, const IUnknown *data)
398 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
400 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
402 return d3d_set_private_data_interface(&shader->private_store, guid, data);
405 static const struct ID3D11VertexShaderVtbl d3d11_vertex_shader_vtbl =
407 /* IUnknown methods */
408 d3d11_vertex_shader_QueryInterface,
409 d3d11_vertex_shader_AddRef,
410 d3d11_vertex_shader_Release,
411 /* ID3D11DeviceChild methods */
412 d3d11_vertex_shader_GetDevice,
413 d3d11_vertex_shader_GetPrivateData,
414 d3d11_vertex_shader_SetPrivateData,
415 d3d11_vertex_shader_SetPrivateDataInterface,
418 /* ID3D10VertexShader methods */
420 static inline struct d3d_vertex_shader *impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
422 return CONTAINING_RECORD(iface, struct d3d_vertex_shader, ID3D10VertexShader_iface);
425 /* IUnknown methods */
427 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_QueryInterface(ID3D10VertexShader *iface,
428 REFIID riid, void **object)
430 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
432 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
434 return d3d11_vertex_shader_QueryInterface(&shader->ID3D11VertexShader_iface, riid, object);
437 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_AddRef(ID3D10VertexShader *iface)
439 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
441 TRACE("iface %p.\n", iface);
443 return d3d11_vertex_shader_AddRef(&shader->ID3D11VertexShader_iface);
446 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_Release(ID3D10VertexShader *iface)
448 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
450 TRACE("iface %p.\n", iface);
452 return d3d11_vertex_shader_Release(&shader->ID3D11VertexShader_iface);
455 /* ID3D10DeviceChild methods */
457 static void STDMETHODCALLTYPE d3d10_vertex_shader_GetDevice(ID3D10VertexShader *iface, ID3D10Device **device)
459 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
461 TRACE("iface %p, device %p.\n", iface, device);
463 ID3D11Device2_QueryInterface(shader->device, &IID_ID3D10Device, (void **)device);
466 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_GetPrivateData(ID3D10VertexShader *iface,
467 REFGUID guid, UINT *data_size, void *data)
469 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
471 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
472 iface, debugstr_guid(guid), data_size, data);
474 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
477 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateData(ID3D10VertexShader *iface,
478 REFGUID guid, UINT data_size, const void *data)
480 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
482 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
483 iface, debugstr_guid(guid), data_size, data);
485 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
488 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateDataInterface(ID3D10VertexShader *iface,
489 REFGUID guid, const IUnknown *data)
491 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
493 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
495 return d3d_set_private_data_interface(&shader->private_store, guid, data);
498 static const struct ID3D10VertexShaderVtbl d3d10_vertex_shader_vtbl =
500 /* IUnknown methods */
501 d3d10_vertex_shader_QueryInterface,
502 d3d10_vertex_shader_AddRef,
503 d3d10_vertex_shader_Release,
504 /* ID3D10DeviceChild methods */
505 d3d10_vertex_shader_GetDevice,
506 d3d10_vertex_shader_GetPrivateData,
507 d3d10_vertex_shader_SetPrivateData,
508 d3d10_vertex_shader_SetPrivateDataInterface,
511 static void STDMETHODCALLTYPE d3d_vertex_shader_wined3d_object_destroyed(void *parent)
513 struct d3d_vertex_shader *shader = parent;
515 wined3d_private_store_cleanup(&shader->private_store);
516 heap_free(parent);
519 static const struct wined3d_parent_ops d3d_vertex_shader_wined3d_parent_ops =
521 d3d_vertex_shader_wined3d_object_destroyed,
524 static unsigned int d3d_sm_from_feature_level(D3D_FEATURE_LEVEL feature_level)
526 switch (feature_level)
528 case D3D_FEATURE_LEVEL_11_1:
529 case D3D_FEATURE_LEVEL_11_0:
530 return 5;
531 case D3D_FEATURE_LEVEL_10_1:
532 case D3D_FEATURE_LEVEL_10_0:
533 return 4;
534 case D3D_FEATURE_LEVEL_9_3:
535 return 3;
536 case D3D_FEATURE_LEVEL_9_2:
537 case D3D_FEATURE_LEVEL_9_1:
538 return 2;
539 default:
540 ERR("Unexpected feature_level %#x.\n", feature_level);
542 return 0;
545 static HRESULT d3d_vertex_shader_init(struct d3d_vertex_shader *shader, struct d3d_device *device,
546 const void *byte_code, SIZE_T byte_code_length)
548 struct wined3d_shader_desc desc;
549 HRESULT hr;
551 shader->ID3D11VertexShader_iface.lpVtbl = &d3d11_vertex_shader_vtbl;
552 shader->ID3D10VertexShader_iface.lpVtbl = &d3d10_vertex_shader_vtbl;
553 shader->refcount = 1;
554 wined3d_mutex_lock();
555 wined3d_private_store_init(&shader->private_store);
557 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
559 WARN("Failed to extract shader, hr %#x.\n", hr);
560 wined3d_private_store_cleanup(&shader->private_store);
561 wined3d_mutex_unlock();
562 return hr;
564 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
566 hr = wined3d_shader_create_vs(device->wined3d_device, &desc, shader,
567 &d3d_vertex_shader_wined3d_parent_ops, &shader->wined3d_shader);
568 free_shader_desc(&desc);
569 if (FAILED(hr))
571 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
572 wined3d_private_store_cleanup(&shader->private_store);
573 wined3d_mutex_unlock();
574 return E_INVALIDARG;
576 wined3d_mutex_unlock();
578 ID3D11Device2_AddRef(shader->device = &device->ID3D11Device2_iface);
580 return S_OK;
583 HRESULT d3d_vertex_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
584 struct d3d_vertex_shader **shader)
586 struct d3d_vertex_shader *object;
587 HRESULT hr;
589 if (!(object = heap_alloc_zero(sizeof(*object))))
590 return E_OUTOFMEMORY;
592 if (FAILED(hr = d3d_vertex_shader_init(object, device, byte_code, byte_code_length)))
594 WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
595 heap_free(object);
596 return hr;
599 TRACE("Created vertex shader %p.\n", object);
600 *shader = object;
602 return S_OK;
605 struct d3d_vertex_shader *unsafe_impl_from_ID3D11VertexShader(ID3D11VertexShader *iface)
607 if (!iface)
608 return NULL;
609 assert(iface->lpVtbl == &d3d11_vertex_shader_vtbl);
611 return impl_from_ID3D11VertexShader(iface);
614 struct d3d_vertex_shader *unsafe_impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
616 if (!iface)
617 return NULL;
618 assert(iface->lpVtbl == &d3d10_vertex_shader_vtbl);
620 return impl_from_ID3D10VertexShader(iface);
623 /* ID3D11HullShader methods */
625 static inline struct d3d11_hull_shader *impl_from_ID3D11HullShader(ID3D11HullShader *iface)
627 return CONTAINING_RECORD(iface, struct d3d11_hull_shader, ID3D11HullShader_iface);
630 static HRESULT STDMETHODCALLTYPE d3d11_hull_shader_QueryInterface(ID3D11HullShader *iface,
631 REFIID riid, void **object)
633 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
635 if (IsEqualGUID(riid, &IID_ID3D11HullShader)
636 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
637 || IsEqualGUID(riid, &IID_IUnknown))
639 ID3D11HullShader_AddRef(iface);
640 *object = iface;
641 return S_OK;
644 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
646 *object = NULL;
647 return E_NOINTERFACE;
650 static ULONG STDMETHODCALLTYPE d3d11_hull_shader_AddRef(ID3D11HullShader *iface)
652 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
653 ULONG refcount = InterlockedIncrement(&shader->refcount);
655 TRACE("%p increasing refcount to %u.\n", shader, refcount);
657 if (refcount == 1)
659 ID3D11Device2_AddRef(shader->device);
660 wined3d_mutex_lock();
661 wined3d_shader_incref(shader->wined3d_shader);
662 wined3d_mutex_unlock();
665 return refcount;
668 static ULONG STDMETHODCALLTYPE d3d11_hull_shader_Release(ID3D11HullShader *iface)
670 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
671 ULONG refcount = InterlockedDecrement(&shader->refcount);
673 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
675 if (!refcount)
677 ID3D11Device2 *device = shader->device;
679 wined3d_mutex_lock();
680 wined3d_shader_decref(shader->wined3d_shader);
681 wined3d_mutex_unlock();
683 /* Release the device last, it may cause the wined3d device to be
684 * destroyed. */
685 ID3D11Device2_Release(device);
688 return refcount;
691 static void STDMETHODCALLTYPE d3d11_hull_shader_GetDevice(ID3D11HullShader *iface,
692 ID3D11Device **device)
694 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
696 TRACE("iface %p, device %p.\n", iface, device);
698 *device = (ID3D11Device *)shader->device;
699 ID3D11Device_AddRef(*device);
702 static HRESULT STDMETHODCALLTYPE d3d11_hull_shader_GetPrivateData(ID3D11HullShader *iface,
703 REFGUID guid, UINT *data_size, void *data)
705 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
707 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
709 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
712 static HRESULT STDMETHODCALLTYPE d3d11_hull_shader_SetPrivateData(ID3D11HullShader *iface,
713 REFGUID guid, UINT data_size, const void *data)
715 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
717 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
719 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
722 static HRESULT STDMETHODCALLTYPE d3d11_hull_shader_SetPrivateDataInterface(ID3D11HullShader *iface,
723 REFGUID guid, const IUnknown *data)
725 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
727 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
729 return d3d_set_private_data_interface(&shader->private_store, guid, data);
732 static const struct ID3D11HullShaderVtbl d3d11_hull_shader_vtbl =
734 /* IUnknown methods */
735 d3d11_hull_shader_QueryInterface,
736 d3d11_hull_shader_AddRef,
737 d3d11_hull_shader_Release,
738 /* ID3D11DeviceChild methods */
739 d3d11_hull_shader_GetDevice,
740 d3d11_hull_shader_GetPrivateData,
741 d3d11_hull_shader_SetPrivateData,
742 d3d11_hull_shader_SetPrivateDataInterface,
745 static void STDMETHODCALLTYPE d3d11_hull_shader_wined3d_object_destroyed(void *parent)
747 struct d3d11_hull_shader *shader = parent;
749 wined3d_private_store_cleanup(&shader->private_store);
750 heap_free(parent);
753 static const struct wined3d_parent_ops d3d11_hull_shader_wined3d_parent_ops =
755 d3d11_hull_shader_wined3d_object_destroyed,
758 static HRESULT d3d11_hull_shader_init(struct d3d11_hull_shader *shader, struct d3d_device *device,
759 const void *byte_code, SIZE_T byte_code_length)
761 struct wined3d_shader_desc desc;
762 HRESULT hr;
764 shader->ID3D11HullShader_iface.lpVtbl = &d3d11_hull_shader_vtbl;
765 shader->refcount = 1;
766 wined3d_mutex_lock();
767 wined3d_private_store_init(&shader->private_store);
769 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
771 WARN("Failed to extract shader, hr %#x.\n", hr);
772 wined3d_private_store_cleanup(&shader->private_store);
773 wined3d_mutex_unlock();
774 return hr;
776 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
778 hr = wined3d_shader_create_hs(device->wined3d_device, &desc, shader,
779 &d3d11_hull_shader_wined3d_parent_ops, &shader->wined3d_shader);
780 free_shader_desc(&desc);
781 if (FAILED(hr))
783 WARN("Failed to create wined3d hull shader, hr %#x.\n", hr);
784 wined3d_private_store_cleanup(&shader->private_store);
785 wined3d_mutex_unlock();
786 return E_INVALIDARG;
788 wined3d_mutex_unlock();
790 ID3D11Device2_AddRef(shader->device = &device->ID3D11Device2_iface);
792 return S_OK;
795 HRESULT d3d11_hull_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
796 struct d3d11_hull_shader **shader)
798 struct d3d11_hull_shader *object;
799 HRESULT hr;
801 if (!(object = heap_alloc_zero(sizeof(*object))))
802 return E_OUTOFMEMORY;
804 if (FAILED(hr = d3d11_hull_shader_init(object, device, byte_code, byte_code_length)))
806 heap_free(object);
807 return hr;
810 TRACE("Created hull shader %p.\n", object);
811 *shader = object;
813 return S_OK;
816 struct d3d11_hull_shader *unsafe_impl_from_ID3D11HullShader(ID3D11HullShader *iface)
818 if (!iface)
819 return NULL;
820 assert(iface->lpVtbl == &d3d11_hull_shader_vtbl);
822 return impl_from_ID3D11HullShader(iface);
825 /* ID3D11DomainShader methods */
827 static inline struct d3d11_domain_shader *impl_from_ID3D11DomainShader(ID3D11DomainShader *iface)
829 return CONTAINING_RECORD(iface, struct d3d11_domain_shader, ID3D11DomainShader_iface);
832 static HRESULT STDMETHODCALLTYPE d3d11_domain_shader_QueryInterface(ID3D11DomainShader *iface,
833 REFIID riid, void **object)
835 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
837 if (IsEqualGUID(riid, &IID_ID3D11DomainShader)
838 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
839 || IsEqualGUID(riid, &IID_IUnknown))
841 ID3D11DomainShader_AddRef(iface);
842 *object = iface;
843 return S_OK;
846 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
848 *object = NULL;
849 return E_NOINTERFACE;
852 static ULONG STDMETHODCALLTYPE d3d11_domain_shader_AddRef(ID3D11DomainShader *iface)
854 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
855 ULONG refcount = InterlockedIncrement(&shader->refcount);
857 TRACE("%p increasing refcount to %u.\n", shader, refcount);
859 if (refcount == 1)
861 ID3D11Device2_AddRef(shader->device);
862 wined3d_mutex_lock();
863 wined3d_shader_incref(shader->wined3d_shader);
864 wined3d_mutex_unlock();
867 return refcount;
870 static ULONG STDMETHODCALLTYPE d3d11_domain_shader_Release(ID3D11DomainShader *iface)
872 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
873 ULONG refcount = InterlockedDecrement(&shader->refcount);
875 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
877 if (!refcount)
879 ID3D11Device2 *device = shader->device;
881 wined3d_mutex_lock();
882 wined3d_shader_decref(shader->wined3d_shader);
883 wined3d_mutex_unlock();
885 /* Release the device last, it may cause the wined3d device to be
886 * destroyed. */
887 ID3D11Device2_Release(device);
890 return refcount;
893 static void STDMETHODCALLTYPE d3d11_domain_shader_GetDevice(ID3D11DomainShader *iface,
894 ID3D11Device **device)
896 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
898 TRACE("iface %p, device %p.\n", iface, device);
900 *device = (ID3D11Device *)shader->device;
901 ID3D11Device_AddRef(*device);
904 static HRESULT STDMETHODCALLTYPE d3d11_domain_shader_GetPrivateData(ID3D11DomainShader *iface,
905 REFGUID guid, UINT *data_size, void *data)
907 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
909 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
911 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
914 static HRESULT STDMETHODCALLTYPE d3d11_domain_shader_SetPrivateData(ID3D11DomainShader *iface,
915 REFGUID guid, UINT data_size, const void *data)
917 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
919 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
921 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
924 static HRESULT STDMETHODCALLTYPE d3d11_domain_shader_SetPrivateDataInterface(ID3D11DomainShader *iface,
925 REFGUID guid, const IUnknown *data)
927 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
929 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
931 return d3d_set_private_data_interface(&shader->private_store, guid, data);
934 static const struct ID3D11DomainShaderVtbl d3d11_domain_shader_vtbl =
936 /* IUnknown methods */
937 d3d11_domain_shader_QueryInterface,
938 d3d11_domain_shader_AddRef,
939 d3d11_domain_shader_Release,
940 /* ID3D11DeviceChild methods */
941 d3d11_domain_shader_GetDevice,
942 d3d11_domain_shader_GetPrivateData,
943 d3d11_domain_shader_SetPrivateData,
944 d3d11_domain_shader_SetPrivateDataInterface,
947 static void STDMETHODCALLTYPE d3d11_domain_shader_wined3d_object_destroyed(void *parent)
949 struct d3d11_domain_shader *shader = parent;
951 wined3d_private_store_cleanup(&shader->private_store);
952 heap_free(parent);
955 static const struct wined3d_parent_ops d3d11_domain_shader_wined3d_parent_ops =
957 d3d11_domain_shader_wined3d_object_destroyed,
960 static HRESULT d3d11_domain_shader_init(struct d3d11_domain_shader *shader, struct d3d_device *device,
961 const void *byte_code, SIZE_T byte_code_length)
963 struct wined3d_shader_desc desc;
964 HRESULT hr;
966 shader->ID3D11DomainShader_iface.lpVtbl = &d3d11_domain_shader_vtbl;
967 shader->refcount = 1;
968 wined3d_mutex_lock();
969 wined3d_private_store_init(&shader->private_store);
971 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
973 WARN("Failed to extract shader, hr %#x.\n", hr);
974 wined3d_private_store_cleanup(&shader->private_store);
975 wined3d_mutex_unlock();
976 return hr;
978 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
980 hr = wined3d_shader_create_ds(device->wined3d_device, &desc, shader,
981 &d3d11_domain_shader_wined3d_parent_ops, &shader->wined3d_shader);
982 free_shader_desc(&desc);
983 if (FAILED(hr))
985 WARN("Failed to create wined3d domain shader, hr %#x.\n", hr);
986 wined3d_private_store_cleanup(&shader->private_store);
987 wined3d_mutex_unlock();
988 return E_INVALIDARG;
990 wined3d_mutex_unlock();
992 ID3D11Device2_AddRef(shader->device = &device->ID3D11Device2_iface);
994 return S_OK;
997 HRESULT d3d11_domain_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
998 struct d3d11_domain_shader **shader)
1000 struct d3d11_domain_shader *object;
1001 HRESULT hr;
1003 if (!(object = heap_alloc_zero(sizeof(*object))))
1004 return E_OUTOFMEMORY;
1006 if (FAILED(hr = d3d11_domain_shader_init(object, device, byte_code, byte_code_length)))
1008 heap_free(object);
1009 return hr;
1012 TRACE("Created domain shader %p.\n", object);
1013 *shader = object;
1015 return S_OK;
1018 struct d3d11_domain_shader *unsafe_impl_from_ID3D11DomainShader(ID3D11DomainShader *iface)
1020 if (!iface)
1021 return NULL;
1022 assert(iface->lpVtbl == &d3d11_domain_shader_vtbl);
1024 return impl_from_ID3D11DomainShader(iface);
1027 /* ID3D11GeometryShader methods */
1029 static inline struct d3d_geometry_shader *impl_from_ID3D11GeometryShader(ID3D11GeometryShader *iface)
1031 return CONTAINING_RECORD(iface, struct d3d_geometry_shader, ID3D11GeometryShader_iface);
1034 static HRESULT STDMETHODCALLTYPE d3d11_geometry_shader_QueryInterface(ID3D11GeometryShader *iface,
1035 REFIID riid, void **object)
1037 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1039 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1041 if (IsEqualGUID(riid, &IID_ID3D11GeometryShader)
1042 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1043 || IsEqualGUID(riid, &IID_IUnknown))
1045 ID3D11GeometryShader_AddRef(iface);
1046 *object = iface;
1047 return S_OK;
1050 if (IsEqualGUID(riid, &IID_ID3D10GeometryShader)
1051 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
1053 ID3D10GeometryShader_AddRef(&shader->ID3D10GeometryShader_iface);
1054 *object = &shader->ID3D10GeometryShader_iface;
1055 return S_OK;
1058 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1060 *object = NULL;
1061 return E_NOINTERFACE;
1064 static ULONG STDMETHODCALLTYPE d3d11_geometry_shader_AddRef(ID3D11GeometryShader *iface)
1066 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1067 ULONG refcount = InterlockedIncrement(&shader->refcount);
1069 TRACE("%p increasing refcount to %u.\n", shader, refcount);
1071 if (refcount == 1)
1073 ID3D11Device2_AddRef(shader->device);
1074 wined3d_mutex_lock();
1075 wined3d_shader_incref(shader->wined3d_shader);
1076 wined3d_mutex_unlock();
1079 return refcount;
1082 static ULONG STDMETHODCALLTYPE d3d11_geometry_shader_Release(ID3D11GeometryShader *iface)
1084 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1085 ULONG refcount = InterlockedDecrement(&shader->refcount);
1087 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
1089 if (!refcount)
1091 ID3D11Device2 *device = shader->device;
1093 wined3d_mutex_lock();
1094 wined3d_shader_decref(shader->wined3d_shader);
1095 wined3d_mutex_unlock();
1097 /* Release the device last, it may cause the wined3d device to be
1098 * destroyed. */
1099 ID3D11Device2_Release(device);
1102 return refcount;
1105 static void STDMETHODCALLTYPE d3d11_geometry_shader_GetDevice(ID3D11GeometryShader *iface,
1106 ID3D11Device **device)
1108 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1110 TRACE("iface %p, device %p.\n", iface, device);
1112 *device = (ID3D11Device *)shader->device;
1113 ID3D11Device_AddRef(*device);
1116 static HRESULT STDMETHODCALLTYPE d3d11_geometry_shader_GetPrivateData(ID3D11GeometryShader *iface,
1117 REFGUID guid, UINT *data_size, void *data)
1119 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1121 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1123 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
1126 static HRESULT STDMETHODCALLTYPE d3d11_geometry_shader_SetPrivateData(ID3D11GeometryShader *iface,
1127 REFGUID guid, UINT data_size, const void *data)
1129 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1131 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1133 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
1136 static HRESULT STDMETHODCALLTYPE d3d11_geometry_shader_SetPrivateDataInterface(ID3D11GeometryShader *iface,
1137 REFGUID guid, const IUnknown *data)
1139 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1141 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1143 return d3d_set_private_data_interface(&shader->private_store, guid, data);
1146 static const struct ID3D11GeometryShaderVtbl d3d11_geometry_shader_vtbl =
1148 /* IUnknown methods */
1149 d3d11_geometry_shader_QueryInterface,
1150 d3d11_geometry_shader_AddRef,
1151 d3d11_geometry_shader_Release,
1152 /* ID3D11DeviceChild methods */
1153 d3d11_geometry_shader_GetDevice,
1154 d3d11_geometry_shader_GetPrivateData,
1155 d3d11_geometry_shader_SetPrivateData,
1156 d3d11_geometry_shader_SetPrivateDataInterface,
1159 /* ID3D10GeometryShader methods */
1161 static inline struct d3d_geometry_shader *impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface)
1163 return CONTAINING_RECORD(iface, struct d3d_geometry_shader, ID3D10GeometryShader_iface);
1166 /* IUnknown methods */
1168 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_QueryInterface(ID3D10GeometryShader *iface,
1169 REFIID riid, void **object)
1171 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1173 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1175 return d3d11_geometry_shader_QueryInterface(&shader->ID3D11GeometryShader_iface, riid, object);
1178 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_AddRef(ID3D10GeometryShader *iface)
1180 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1182 TRACE("iface %p.\n", iface);
1184 return d3d11_geometry_shader_AddRef(&shader->ID3D11GeometryShader_iface);
1187 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_Release(ID3D10GeometryShader *iface)
1189 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1191 TRACE("iface %p.\n", iface);
1193 return d3d11_geometry_shader_Release(&shader->ID3D11GeometryShader_iface);
1196 /* ID3D10DeviceChild methods */
1198 static void STDMETHODCALLTYPE d3d10_geometry_shader_GetDevice(ID3D10GeometryShader *iface, ID3D10Device **device)
1200 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1202 TRACE("iface %p, device %p.\n", iface, device);
1204 ID3D11Device2_QueryInterface(shader->device, &IID_ID3D10Device, (void **)device);
1207 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_GetPrivateData(ID3D10GeometryShader *iface,
1208 REFGUID guid, UINT *data_size, void *data)
1210 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1212 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1213 iface, debugstr_guid(guid), data_size, data);
1215 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
1218 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateData(ID3D10GeometryShader *iface,
1219 REFGUID guid, UINT data_size, const void *data)
1221 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1223 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1224 iface, debugstr_guid(guid), data_size, data);
1226 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
1229 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateDataInterface(ID3D10GeometryShader *iface,
1230 REFGUID guid, const IUnknown *data)
1232 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1234 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1236 return d3d_set_private_data_interface(&shader->private_store, guid, data);
1239 static const struct ID3D10GeometryShaderVtbl d3d10_geometry_shader_vtbl =
1241 /* IUnknown methods */
1242 d3d10_geometry_shader_QueryInterface,
1243 d3d10_geometry_shader_AddRef,
1244 d3d10_geometry_shader_Release,
1245 /* ID3D10DeviceChild methods */
1246 d3d10_geometry_shader_GetDevice,
1247 d3d10_geometry_shader_GetPrivateData,
1248 d3d10_geometry_shader_SetPrivateData,
1249 d3d10_geometry_shader_SetPrivateDataInterface,
1252 static void STDMETHODCALLTYPE d3d_geometry_shader_wined3d_object_destroyed(void *parent)
1254 struct d3d_geometry_shader *shader = parent;
1256 wined3d_private_store_cleanup(&shader->private_store);
1257 heap_free(parent);
1260 static const struct wined3d_parent_ops d3d_geometry_shader_wined3d_parent_ops =
1262 d3d_geometry_shader_wined3d_object_destroyed,
1265 static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_output_element *elements,
1266 const D3D11_SO_DECLARATION_ENTRY *entries, unsigned int entry_count,
1267 const unsigned int *buffer_strides, unsigned int buffer_stride_count,
1268 const struct wined3d_shader_signature *os, D3D_FEATURE_LEVEL feature_level)
1270 unsigned int i, j, mask;
1272 for (i = 0; i < entry_count; ++i)
1274 struct wined3d_stream_output_element *e = &elements[i];
1275 const D3D11_SO_DECLARATION_ENTRY *f = &entries[i];
1276 struct wined3d_shader_signature_element *output;
1278 TRACE("Stream: %u, semantic: %s, semantic idx: %u, start component: %u, "
1279 "component count %u, output slot %u.\n",
1280 f->Stream, debugstr_a(f->SemanticName), f->SemanticIndex,
1281 f->StartComponent, f->ComponentCount, f->OutputSlot);
1283 if (f->Stream >= D3D11_SO_STREAM_COUNT)
1285 WARN("Invalid stream %u.\n", f->Stream);
1286 return E_INVALIDARG;
1288 if (f->Stream && feature_level < D3D_FEATURE_LEVEL_11_0)
1290 WARN("Invalid stream %u for feature level %#x.\n", f->Stream, feature_level);
1291 return E_INVALIDARG;
1293 if (f->Stream)
1295 FIXME("Streams not implemented yet.\n");
1296 return E_INVALIDARG;
1298 if (f->OutputSlot >= D3D11_SO_BUFFER_SLOT_COUNT)
1300 WARN("Invalid output slot %u.\n", f->OutputSlot);
1301 return E_INVALIDARG;
1304 e->stream_idx = f->Stream;
1305 e->component_idx = f->StartComponent;
1306 e->component_count = f->ComponentCount;
1307 e->output_slot = f->OutputSlot;
1309 if (!f->SemanticName)
1311 if (f->SemanticIndex)
1313 WARN("Invalid semantic idx %u for stream output gap.\n", f->SemanticIndex);
1314 return E_INVALIDARG;
1316 if (e->component_idx || !e->component_count)
1318 WARN("Invalid stream output gap %u-%u.\n", e->component_idx, e->component_count);
1319 return E_INVALIDARG;
1322 e->register_idx = WINED3D_STREAM_OUTPUT_GAP;
1324 else if ((output = shader_find_signature_element(os, f->SemanticName, f->SemanticIndex, f->Stream)))
1326 if (e->component_idx > 3 || e->component_count > 4 || !e->component_count
1327 || e->component_idx + e->component_count > 4)
1329 WARN("Invalid component range %u-%u.\n", e->component_idx, e->component_count);
1330 return E_INVALIDARG;
1333 for (j = 0; j < 4; ++j)
1335 if ((1u << j) & output->mask)
1336 break;
1338 e->component_idx += j;
1339 mask = ((1u << e->component_count) - 1) << e->component_idx;
1340 if ((output->mask & 0xff & mask) != mask)
1342 WARN("Invalid component range %u-%u (mask %#x), output mask %#x.\n",
1343 e->component_idx, e->component_count, mask, output->mask & 0xff);
1344 return E_INVALIDARG;
1347 e->register_idx = output->register_idx;
1348 TRACE("Register idx: %u, register component idx %u, register mask %#x.\n",
1349 e->register_idx, e->component_idx, mask);
1351 else
1353 WARN("Failed to find output signature element for stream output entry.\n");
1354 return E_INVALIDARG;
1358 for (i = 0; i < entry_count; ++i)
1360 const struct wined3d_stream_output_element *e1 = &elements[i];
1361 if (e1->register_idx == WINED3D_STREAM_OUTPUT_GAP)
1362 continue;
1364 for (j = i + 1; j < entry_count; ++j)
1366 const struct wined3d_stream_output_element *e2 = &elements[j];
1368 if (e1->register_idx == e2->register_idx
1369 && e1->component_idx < e2->component_idx + e2->component_count
1370 && e1->component_idx + e1->component_count > e2->component_idx)
1372 WARN("Stream output elements %u and %u overlap.\n", i, j);
1373 return E_INVALIDARG;
1378 for (i = 0; i < D3D11_SO_STREAM_COUNT; ++i)
1380 unsigned int current_stride[D3D11_SO_BUFFER_SLOT_COUNT] = {0};
1381 unsigned int element_count[D3D11_SO_BUFFER_SLOT_COUNT] = {0};
1382 unsigned int gap_count[D3D11_SO_BUFFER_SLOT_COUNT] = {0};
1384 for (j = 0; j < entry_count; ++j)
1386 const struct wined3d_stream_output_element *e = &elements[j];
1388 if (e->stream_idx != i)
1389 continue;
1390 current_stride[e->output_slot] += 4 * e->component_count;
1391 ++element_count[e->output_slot];
1392 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
1393 ++gap_count[e->output_slot];
1396 for (j = 0; j < D3D11_SO_BUFFER_SLOT_COUNT; ++j)
1398 if (!element_count[j])
1399 continue;
1400 if (element_count[j] == gap_count[j])
1402 WARN("Stream %u, output slot %u contains only gaps.\n", i, j);
1403 return E_INVALIDARG;
1405 if (buffer_stride_count)
1407 if (buffer_stride_count <= j)
1409 WARN("Buffer strides are required for all buffer slots.\n");
1410 return E_INVALIDARG;
1412 if (buffer_strides[j] < current_stride[j] || buffer_strides[j] % 4)
1414 WARN("Invalid stride %u for buffer slot %u.\n", buffer_strides[j], j);
1415 return E_INVALIDARG;
1420 if (!i && feature_level < D3D_FEATURE_LEVEL_11_0 && element_count[0] != entry_count)
1422 for (j = 0; j < ARRAY_SIZE(element_count); ++j)
1424 if (element_count[j] > 1)
1426 WARN("Only one element per output slot is allowed.\n");
1427 return E_INVALIDARG;
1433 return S_OK;
1436 static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader,
1437 struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
1438 const D3D11_SO_DECLARATION_ENTRY *so_entries, unsigned int so_entry_count,
1439 const unsigned int *buffer_strides, unsigned int buffer_stride_count,
1440 unsigned int rasterizer_stream)
1442 struct wined3d_stream_output_desc so_desc;
1443 struct wined3d_shader_desc desc;
1444 unsigned int i;
1445 HRESULT hr;
1447 if (so_entry_count > D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT)
1449 WARN("Entry count %u is greater than %u.\n",
1450 so_entry_count, D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT);
1451 return E_INVALIDARG;
1453 if (so_entries && !so_entry_count)
1455 WARN("Invalid SO entry count %u.\n", so_entry_count);
1456 return E_INVALIDARG;
1458 if (rasterizer_stream != D3D11_SO_NO_RASTERIZED_STREAM && rasterizer_stream >= D3D11_SO_STREAM_COUNT)
1460 WARN("Invalid rasterizer stream %u.\n", rasterizer_stream);
1461 return E_INVALIDARG;
1463 if (device->feature_level < D3D_FEATURE_LEVEL_11_0)
1465 if (rasterizer_stream)
1467 WARN("Invalid rasterizer stream %u for feature level %#x.\n",
1468 rasterizer_stream, device->feature_level);
1469 return E_INVALIDARG;
1471 if (buffer_stride_count && buffer_stride_count != 1)
1473 WARN("Invalid buffer stride count %u for feature level %#x.\n",
1474 buffer_stride_count, device->feature_level);
1475 return E_INVALIDARG;
1479 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
1481 WARN("Failed to extract shader, hr %#x.\n", hr);
1482 return hr;
1484 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
1486 memset(&so_desc, 0, sizeof(so_desc));
1487 if (so_entries)
1489 so_desc.element_count = so_entry_count;
1490 for (i = 0; i < min(buffer_stride_count, ARRAY_SIZE(so_desc.buffer_strides)); ++i)
1491 so_desc.buffer_strides[i] = buffer_strides[i];
1492 so_desc.buffer_stride_count = buffer_stride_count;
1493 so_desc.rasterizer_stream_idx = rasterizer_stream;
1495 if (!(so_desc.elements = heap_calloc(so_entry_count, sizeof(*so_desc.elements))))
1497 ERR("Failed to allocate wined3d stream output element array memory.\n");
1498 free_shader_desc(&desc);
1499 return E_OUTOFMEMORY;
1501 if (FAILED(hr = wined3d_so_elements_from_d3d11_so_entries(so_desc.elements,
1502 so_entries, so_entry_count, buffer_strides, buffer_stride_count,
1503 &desc.output_signature, device->feature_level)))
1505 heap_free(so_desc.elements);
1506 free_shader_desc(&desc);
1507 return hr;
1511 shader->ID3D11GeometryShader_iface.lpVtbl = &d3d11_geometry_shader_vtbl;
1512 shader->ID3D10GeometryShader_iface.lpVtbl = &d3d10_geometry_shader_vtbl;
1513 shader->refcount = 1;
1514 wined3d_mutex_lock();
1515 wined3d_private_store_init(&shader->private_store);
1517 hr = wined3d_shader_create_gs(device->wined3d_device, &desc, so_entries ? &so_desc : NULL,
1518 shader, &d3d_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader);
1519 heap_free(so_desc.elements);
1520 free_shader_desc(&desc);
1521 if (FAILED(hr))
1523 WARN("Failed to create wined3d geometry shader, hr %#x.\n", hr);
1524 wined3d_private_store_cleanup(&shader->private_store);
1525 wined3d_mutex_unlock();
1526 return E_INVALIDARG;
1528 wined3d_mutex_unlock();
1530 ID3D11Device2_AddRef(shader->device = &device->ID3D11Device2_iface);
1532 return S_OK;
1535 HRESULT d3d_geometry_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
1536 const D3D11_SO_DECLARATION_ENTRY *so_entries, unsigned int so_entry_count,
1537 const unsigned int *buffer_strides, unsigned int buffer_stride_count, unsigned int rasterizer_stream,
1538 struct d3d_geometry_shader **shader)
1540 struct d3d_geometry_shader *object;
1541 HRESULT hr;
1543 if (!(object = heap_alloc_zero(sizeof(*object))))
1544 return E_OUTOFMEMORY;
1546 if (FAILED(hr = d3d_geometry_shader_init(object, device, byte_code, byte_code_length,
1547 so_entries, so_entry_count, buffer_strides, buffer_stride_count, rasterizer_stream)))
1549 WARN("Failed to initialize geometry shader, hr %#x.\n", hr);
1550 heap_free(object);
1551 return hr;
1554 TRACE("Created geometry shader %p.\n", object);
1555 *shader = object;
1557 return S_OK;
1560 struct d3d_geometry_shader *unsafe_impl_from_ID3D11GeometryShader(ID3D11GeometryShader *iface)
1562 if (!iface)
1563 return NULL;
1564 assert(iface->lpVtbl == &d3d11_geometry_shader_vtbl);
1566 return impl_from_ID3D11GeometryShader(iface);
1569 struct d3d_geometry_shader *unsafe_impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface)
1571 if (!iface)
1572 return NULL;
1573 assert(iface->lpVtbl == &d3d10_geometry_shader_vtbl);
1575 return impl_from_ID3D10GeometryShader(iface);
1578 /* ID3D11PixelShader methods */
1580 static inline struct d3d_pixel_shader *impl_from_ID3D11PixelShader(ID3D11PixelShader *iface)
1582 return CONTAINING_RECORD(iface, struct d3d_pixel_shader, ID3D11PixelShader_iface);
1585 static HRESULT STDMETHODCALLTYPE d3d11_pixel_shader_QueryInterface(ID3D11PixelShader *iface,
1586 REFIID riid, void **object)
1588 struct d3d_pixel_shader *shader = impl_from_ID3D11PixelShader(iface);
1590 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1592 if (IsEqualGUID(riid, &IID_ID3D11PixelShader)
1593 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1594 || IsEqualGUID(riid, &IID_IUnknown))
1596 ID3D11PixelShader_AddRef(iface);
1597 *object = iface;
1598 return S_OK;
1601 if (IsEqualGUID(riid, &IID_ID3D10PixelShader)
1602 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
1604 IUnknown_AddRef(&shader->ID3D10PixelShader_iface);
1605 *object = &shader->ID3D10PixelShader_iface;
1606 return S_OK;
1609 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1611 *object = NULL;
1612 return E_NOINTERFACE;
1615 static ULONG STDMETHODCALLTYPE d3d11_pixel_shader_AddRef(ID3D11PixelShader *iface)
1617 struct d3d_pixel_shader *shader = impl_from_ID3D11PixelShader(iface);
1618 ULONG refcount = InterlockedIncrement(&shader->refcount);
1620 TRACE("%p increasing refcount to %u.\n", shader, refcount);
1622 if (refcount == 1)
1624 ID3D11Device2_AddRef(shader->device);
1625 wined3d_mutex_lock();
1626 wined3d_shader_incref(shader->wined3d_shader);
1627 wined3d_mutex_unlock();
1630 return refcount;
1633 static ULONG STDMETHODCALLTYPE d3d11_pixel_shader_Release(ID3D11PixelShader *iface)
1635 struct d3d_pixel_shader *shader = impl_from_ID3D11PixelShader(iface);
1636 ULONG refcount = InterlockedDecrement(&shader->refcount);
1638 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
1640 if (!refcount)
1642 ID3D11Device2 *device = shader->device;
1644 wined3d_mutex_lock();
1645 wined3d_shader_decref(shader->wined3d_shader);
1646 wined3d_mutex_unlock();
1647 /* Release the device last, it may cause the wined3d device to be
1648 * destroyed. */
1649 ID3D11Device2_Release(device);
1652 return refcount;
1655 static void STDMETHODCALLTYPE d3d11_pixel_shader_GetDevice(ID3D11PixelShader *iface,
1656 ID3D11Device **device)
1658 struct d3d_pixel_shader *shader = impl_from_ID3D11PixelShader(iface);
1660 TRACE("iface %p, device %p.\n", iface, device);
1662 *device = (ID3D11Device *)shader->device;
1663 ID3D11Device_AddRef(*device);
1666 static HRESULT STDMETHODCALLTYPE d3d11_pixel_shader_GetPrivateData(ID3D11PixelShader *iface,
1667 REFGUID guid, UINT *data_size, void *data)
1669 struct d3d_pixel_shader *shader = impl_from_ID3D11PixelShader(iface);
1671 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1673 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
1676 static HRESULT STDMETHODCALLTYPE d3d11_pixel_shader_SetPrivateData(ID3D11PixelShader *iface,
1677 REFGUID guid, UINT data_size, const void *data)
1679 struct d3d_pixel_shader *shader = impl_from_ID3D11PixelShader(iface);
1681 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1683 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
1686 static HRESULT STDMETHODCALLTYPE d3d11_pixel_shader_SetPrivateDataInterface(ID3D11PixelShader *iface,
1687 REFGUID guid, const IUnknown *data)
1689 struct d3d_pixel_shader *shader = impl_from_ID3D11PixelShader(iface);
1691 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1693 return d3d_set_private_data_interface(&shader->private_store, guid, data);
1696 static const struct ID3D11PixelShaderVtbl d3d11_pixel_shader_vtbl =
1698 /* IUnknown methods */
1699 d3d11_pixel_shader_QueryInterface,
1700 d3d11_pixel_shader_AddRef,
1701 d3d11_pixel_shader_Release,
1702 /* ID3D11DeviceChild methods */
1703 d3d11_pixel_shader_GetDevice,
1704 d3d11_pixel_shader_GetPrivateData,
1705 d3d11_pixel_shader_SetPrivateData,
1706 d3d11_pixel_shader_SetPrivateDataInterface,
1709 /* ID3D10PixelShader methods */
1711 static inline struct d3d_pixel_shader *impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
1713 return CONTAINING_RECORD(iface, struct d3d_pixel_shader, ID3D10PixelShader_iface);
1716 /* IUnknown methods */
1718 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_QueryInterface(ID3D10PixelShader *iface,
1719 REFIID riid, void **object)
1721 struct d3d_pixel_shader *shader = impl_from_ID3D10PixelShader(iface);
1723 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1725 return d3d11_pixel_shader_QueryInterface(&shader->ID3D11PixelShader_iface, riid, object);
1728 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_AddRef(ID3D10PixelShader *iface)
1730 struct d3d_pixel_shader *shader = impl_from_ID3D10PixelShader(iface);
1732 TRACE("iface %p.\n", iface);
1734 return d3d11_pixel_shader_AddRef(&shader->ID3D11PixelShader_iface);
1737 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_Release(ID3D10PixelShader *iface)
1739 struct d3d_pixel_shader *shader = impl_from_ID3D10PixelShader(iface);
1741 TRACE("iface %p.\n", iface);
1743 return d3d11_pixel_shader_Release(&shader->ID3D11PixelShader_iface);
1746 /* ID3D10DeviceChild methods */
1748 static void STDMETHODCALLTYPE d3d10_pixel_shader_GetDevice(ID3D10PixelShader *iface, ID3D10Device **device)
1750 struct d3d_pixel_shader *shader = impl_from_ID3D10PixelShader(iface);
1752 TRACE("iface %p, device %p.\n", iface, device);
1754 ID3D11Device2_QueryInterface(shader->device, &IID_ID3D10Device, (void **)device);
1757 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_GetPrivateData(ID3D10PixelShader *iface,
1758 REFGUID guid, UINT *data_size, void *data)
1760 struct d3d_pixel_shader *shader = impl_from_ID3D10PixelShader(iface);
1762 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1763 iface, debugstr_guid(guid), data_size, data);
1765 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
1768 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateData(ID3D10PixelShader *iface,
1769 REFGUID guid, UINT data_size, const void *data)
1771 struct d3d_pixel_shader *shader = impl_from_ID3D10PixelShader(iface);
1773 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1774 iface, debugstr_guid(guid), data_size, data);
1776 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
1779 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateDataInterface(ID3D10PixelShader *iface,
1780 REFGUID guid, const IUnknown *data)
1782 struct d3d_pixel_shader *shader = impl_from_ID3D10PixelShader(iface);
1784 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1786 return d3d_set_private_data_interface(&shader->private_store, guid, data);
1789 static const struct ID3D10PixelShaderVtbl d3d10_pixel_shader_vtbl =
1791 /* IUnknown methods */
1792 d3d10_pixel_shader_QueryInterface,
1793 d3d10_pixel_shader_AddRef,
1794 d3d10_pixel_shader_Release,
1795 /* ID3D10DeviceChild methods */
1796 d3d10_pixel_shader_GetDevice,
1797 d3d10_pixel_shader_GetPrivateData,
1798 d3d10_pixel_shader_SetPrivateData,
1799 d3d10_pixel_shader_SetPrivateDataInterface,
1802 static void STDMETHODCALLTYPE d3d_pixel_shader_wined3d_object_destroyed(void *parent)
1804 struct d3d_pixel_shader *shader = parent;
1806 wined3d_private_store_cleanup(&shader->private_store);
1807 heap_free(parent);
1810 static const struct wined3d_parent_ops d3d_pixel_shader_wined3d_parent_ops =
1812 d3d_pixel_shader_wined3d_object_destroyed,
1815 static HRESULT d3d_pixel_shader_init(struct d3d_pixel_shader *shader, struct d3d_device *device,
1816 const void *byte_code, SIZE_T byte_code_length)
1818 struct wined3d_shader_desc desc;
1819 HRESULT hr;
1821 shader->ID3D11PixelShader_iface.lpVtbl = &d3d11_pixel_shader_vtbl;
1822 shader->ID3D10PixelShader_iface.lpVtbl = &d3d10_pixel_shader_vtbl;
1823 shader->refcount = 1;
1824 wined3d_mutex_lock();
1825 wined3d_private_store_init(&shader->private_store);
1827 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
1829 WARN("Failed to extract shader, hr %#x.\n", hr);
1830 wined3d_private_store_cleanup(&shader->private_store);
1831 wined3d_mutex_unlock();
1832 return hr;
1834 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
1836 hr = wined3d_shader_create_ps(device->wined3d_device, &desc, shader,
1837 &d3d_pixel_shader_wined3d_parent_ops, &shader->wined3d_shader);
1838 free_shader_desc(&desc);
1839 if (FAILED(hr))
1841 WARN("Failed to create wined3d pixel shader, hr %#x.\n", hr);
1842 wined3d_private_store_cleanup(&shader->private_store);
1843 wined3d_mutex_unlock();
1844 return E_INVALIDARG;
1846 wined3d_mutex_unlock();
1848 ID3D11Device2_AddRef(shader->device = &device->ID3D11Device2_iface);
1850 return S_OK;
1853 HRESULT d3d_pixel_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
1854 struct d3d_pixel_shader **shader)
1856 struct d3d_pixel_shader *object;
1857 HRESULT hr;
1859 if (!(object = heap_alloc_zero(sizeof(*object))))
1860 return E_OUTOFMEMORY;
1862 if (FAILED(hr = d3d_pixel_shader_init(object, device, byte_code, byte_code_length)))
1864 WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
1865 heap_free(object);
1866 return hr;
1869 TRACE("Created pixel shader %p.\n", object);
1870 *shader = object;
1872 return S_OK;
1875 struct d3d_pixel_shader *unsafe_impl_from_ID3D11PixelShader(ID3D11PixelShader *iface)
1877 if (!iface)
1878 return NULL;
1879 assert(iface->lpVtbl == &d3d11_pixel_shader_vtbl);
1881 return impl_from_ID3D11PixelShader(iface);
1884 struct d3d_pixel_shader *unsafe_impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
1886 if (!iface)
1887 return NULL;
1888 assert(iface->lpVtbl == &d3d10_pixel_shader_vtbl);
1890 return impl_from_ID3D10PixelShader(iface);
1893 /* ID3D11ComputeShader methods */
1895 static inline struct d3d11_compute_shader *impl_from_ID3D11ComputeShader(ID3D11ComputeShader *iface)
1897 return CONTAINING_RECORD(iface, struct d3d11_compute_shader, ID3D11ComputeShader_iface);
1900 static HRESULT STDMETHODCALLTYPE d3d11_compute_shader_QueryInterface(ID3D11ComputeShader *iface,
1901 REFIID riid, void **object)
1903 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1905 if (IsEqualGUID(riid, &IID_ID3D11ComputeShader)
1906 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1907 || IsEqualGUID(riid, &IID_IUnknown))
1909 ID3D11ComputeShader_AddRef(*object = iface);
1910 return S_OK;
1913 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1915 *object = NULL;
1916 return E_NOINTERFACE;
1919 static ULONG STDMETHODCALLTYPE d3d11_compute_shader_AddRef(ID3D11ComputeShader *iface)
1921 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1922 ULONG refcount = InterlockedIncrement(&shader->refcount);
1924 TRACE("%p increasing refcount to %u.\n", shader, refcount);
1926 if (refcount == 1)
1928 ID3D11Device2_AddRef(shader->device);
1929 wined3d_mutex_lock();
1930 wined3d_shader_incref(shader->wined3d_shader);
1931 wined3d_mutex_unlock();
1934 return refcount;
1937 static ULONG STDMETHODCALLTYPE d3d11_compute_shader_Release(ID3D11ComputeShader *iface)
1939 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1940 ULONG refcount = InterlockedDecrement(&shader->refcount);
1942 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
1944 if (!refcount)
1946 ID3D11Device2 *device = shader->device;
1948 wined3d_mutex_lock();
1949 wined3d_shader_decref(shader->wined3d_shader);
1950 wined3d_mutex_unlock();
1952 /* Release the device last, it may cause the wined3d device to be
1953 * destroyed. */
1954 ID3D11Device2_Release(device);
1957 return refcount;
1960 static void STDMETHODCALLTYPE d3d11_compute_shader_GetDevice(ID3D11ComputeShader *iface,
1961 ID3D11Device **device)
1963 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1965 TRACE("iface %p, device %p.\n", iface, device);
1967 ID3D11Device_AddRef(*device = (ID3D11Device *)shader->device);
1970 static HRESULT STDMETHODCALLTYPE d3d11_compute_shader_GetPrivateData(ID3D11ComputeShader *iface,
1971 REFGUID guid, UINT *data_size, void *data)
1973 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1975 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1977 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
1980 static HRESULT STDMETHODCALLTYPE d3d11_compute_shader_SetPrivateData(ID3D11ComputeShader *iface,
1981 REFGUID guid, UINT data_size, const void *data)
1983 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1985 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1987 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
1990 static HRESULT STDMETHODCALLTYPE d3d11_compute_shader_SetPrivateDataInterface(ID3D11ComputeShader *iface,
1991 REFGUID guid, const IUnknown *data)
1993 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1995 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1997 return d3d_set_private_data_interface(&shader->private_store, guid, data);
2000 static const struct ID3D11ComputeShaderVtbl d3d11_compute_shader_vtbl =
2002 /* IUnknown methods */
2003 d3d11_compute_shader_QueryInterface,
2004 d3d11_compute_shader_AddRef,
2005 d3d11_compute_shader_Release,
2006 /* ID3D11DeviceChild methods */
2007 d3d11_compute_shader_GetDevice,
2008 d3d11_compute_shader_GetPrivateData,
2009 d3d11_compute_shader_SetPrivateData,
2010 d3d11_compute_shader_SetPrivateDataInterface,
2013 static void STDMETHODCALLTYPE d3d11_compute_shader_wined3d_object_destroyed(void *parent)
2015 struct d3d11_compute_shader *shader = parent;
2017 wined3d_private_store_cleanup(&shader->private_store);
2018 heap_free(parent);
2021 static const struct wined3d_parent_ops d3d11_compute_shader_wined3d_parent_ops =
2023 d3d11_compute_shader_wined3d_object_destroyed,
2026 static HRESULT d3d11_compute_shader_init(struct d3d11_compute_shader *shader, struct d3d_device *device,
2027 const void *byte_code, SIZE_T byte_code_length)
2029 struct wined3d_shader_desc desc;
2030 HRESULT hr;
2032 shader->ID3D11ComputeShader_iface.lpVtbl = &d3d11_compute_shader_vtbl;
2033 shader->refcount = 1;
2034 wined3d_mutex_lock();
2035 wined3d_private_store_init(&shader->private_store);
2037 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
2039 WARN("Failed to extract shader, hr %#x.\n", hr);
2040 wined3d_private_store_cleanup(&shader->private_store);
2041 wined3d_mutex_unlock();
2042 return hr;
2044 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
2046 hr = wined3d_shader_create_cs(device->wined3d_device, &desc, shader,
2047 &d3d11_compute_shader_wined3d_parent_ops, &shader->wined3d_shader);
2048 free_shader_desc(&desc);
2049 if (FAILED(hr))
2051 WARN("Failed to create wined3d compute shader, hr %#x.\n", hr);
2052 wined3d_private_store_cleanup(&shader->private_store);
2053 wined3d_mutex_unlock();
2054 return E_INVALIDARG;
2056 wined3d_mutex_unlock();
2058 ID3D11Device2_AddRef(shader->device = &device->ID3D11Device2_iface);
2060 return S_OK;
2063 HRESULT d3d11_compute_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
2064 struct d3d11_compute_shader **shader)
2066 struct d3d11_compute_shader *object;
2067 HRESULT hr;
2069 if (!(object = heap_alloc_zero(sizeof(*object))))
2070 return E_OUTOFMEMORY;
2072 if (FAILED(hr = d3d11_compute_shader_init(object, device, byte_code, byte_code_length)))
2074 heap_free(object);
2075 return hr;
2078 TRACE("Created compute shader %p.\n", object);
2079 *shader = object;
2081 return S_OK;
2084 struct d3d11_compute_shader *unsafe_impl_from_ID3D11ComputeShader(ID3D11ComputeShader *iface)
2086 if (!iface)
2087 return NULL;
2088 assert(iface->lpVtbl == &d3d11_compute_shader_vtbl);
2090 return impl_from_ID3D11ComputeShader(iface);
2093 /* ID3D11ClassLinkage methods */
2095 static inline struct d3d11_class_linkage *impl_from_ID3D11ClassLinkage(ID3D11ClassLinkage *iface)
2097 return CONTAINING_RECORD(iface, struct d3d11_class_linkage, ID3D11ClassLinkage_iface);
2100 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_QueryInterface(ID3D11ClassLinkage *iface,
2101 REFIID riid, void **object)
2103 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
2105 if (IsEqualGUID(riid, &IID_ID3D11ClassLinkage)
2106 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
2107 || IsEqualGUID(riid, &IID_IUnknown))
2109 ID3D11ClassLinkage_AddRef(*object = iface);
2110 return S_OK;
2113 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
2115 *object = NULL;
2116 return E_NOINTERFACE;
2119 static ULONG STDMETHODCALLTYPE d3d11_class_linkage_AddRef(ID3D11ClassLinkage *iface)
2121 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2122 ULONG refcount = InterlockedIncrement(&class_linkage->refcount);
2124 TRACE("%p increasing refcount to %u.\n", class_linkage, refcount);
2126 return refcount;
2129 static ULONG STDMETHODCALLTYPE d3d11_class_linkage_Release(ID3D11ClassLinkage *iface)
2131 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2132 ULONG refcount = InterlockedDecrement(&class_linkage->refcount);
2134 TRACE("%p decreasing refcount to %u.\n", class_linkage, refcount);
2136 if (!refcount)
2138 ID3D11Device2 *device = class_linkage->device;
2140 wined3d_private_store_cleanup(&class_linkage->private_store);
2141 heap_free(class_linkage);
2143 ID3D11Device2_Release(device);
2146 return refcount;
2149 static void STDMETHODCALLTYPE d3d11_class_linkage_GetDevice(ID3D11ClassLinkage *iface,
2150 ID3D11Device **device)
2152 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2154 TRACE("iface %p, device %p.\n", iface, device);
2156 ID3D11Device_AddRef(*device = (ID3D11Device *)class_linkage->device);
2159 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_GetPrivateData(ID3D11ClassLinkage *iface,
2160 REFGUID guid, UINT *data_size, void *data)
2162 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2164 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
2166 return d3d_get_private_data(&class_linkage->private_store, guid, data_size, data);
2169 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_SetPrivateData(ID3D11ClassLinkage *iface,
2170 REFGUID guid, UINT data_size, const void *data)
2172 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2174 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
2176 return d3d_set_private_data(&class_linkage->private_store, guid, data_size, data);
2179 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_SetPrivateDataInterface(ID3D11ClassLinkage *iface,
2180 REFGUID guid, const IUnknown *data)
2182 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2184 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
2186 return d3d_set_private_data_interface(&class_linkage->private_store, guid, data);
2189 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_GetClassInstance(ID3D11ClassLinkage *iface,
2190 const char *instance_name, UINT instance_index, ID3D11ClassInstance **class_instance)
2192 FIXME("iface %p, instance_name %s, instance_index %u, class_instance %p stub!\n",
2193 iface, debugstr_a(instance_name), instance_index, class_instance);
2195 return E_NOTIMPL;
2198 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_CreateClassInstance(ID3D11ClassLinkage *iface,
2199 const char *type_name, UINT cb_offset, UINT cb_vector_offset, UINT texture_offset,
2200 UINT sampler_offset, ID3D11ClassInstance **class_instance)
2202 FIXME("iface %p, type_name %s, cb_offset %u, cb_vector_offset %u, texture_offset %u, "
2203 "sampler_offset %u, class_instance %p stub!\n",
2204 iface, debugstr_a(type_name), cb_offset, cb_vector_offset, texture_offset,
2205 sampler_offset, class_instance);
2207 return E_NOTIMPL;
2210 static const struct ID3D11ClassLinkageVtbl d3d11_class_linkage_vtbl =
2212 /* IUnknown methods */
2213 d3d11_class_linkage_QueryInterface,
2214 d3d11_class_linkage_AddRef,
2215 d3d11_class_linkage_Release,
2216 /* ID3D11DeviceChild methods */
2217 d3d11_class_linkage_GetDevice,
2218 d3d11_class_linkage_GetPrivateData,
2219 d3d11_class_linkage_SetPrivateData,
2220 d3d11_class_linkage_SetPrivateDataInterface,
2221 /* ID3D11ClassLinkage methods */
2222 d3d11_class_linkage_GetClassInstance,
2223 d3d11_class_linkage_CreateClassInstance,
2226 HRESULT d3d11_class_linkage_create(struct d3d_device *device, struct d3d11_class_linkage **class_linkage)
2228 struct d3d11_class_linkage *object;
2230 if (!(object = heap_alloc_zero(sizeof(*object))))
2231 return E_OUTOFMEMORY;
2233 object->ID3D11ClassLinkage_iface.lpVtbl = &d3d11_class_linkage_vtbl;
2234 object->refcount = 1;
2235 wined3d_private_store_init(&object->private_store);
2237 ID3D11Device2_AddRef(object->device = &device->ID3D11Device2_iface);
2239 TRACE("Created class linkage %p.\n", object);
2240 *class_linkage = object;
2242 return S_OK;