gphoto2.ds: Set supported groups.
[wine.git] / dlls / d3d11 / shader.c
blobbd9eb6609e7cabcb2b942c91ca5d9fb3e1f7edd8
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 default:
140 FIXME("Unhandled chunk %s.\n", debugstr_an((const char *)&tag, 4));
141 break;
144 return S_OK;
147 static void free_shader_desc(struct wined3d_shader_desc *desc)
149 shader_free_signature(&desc->input_signature);
150 shader_free_signature(&desc->output_signature);
151 shader_free_signature(&desc->patch_constant_signature);
154 static HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length,
155 struct wined3d_shader_desc *desc, D3D_FEATURE_LEVEL feature_level)
157 struct shader_handler_context ctx = {feature_level, desc};
158 HRESULT hr;
160 desc->byte_code = NULL;
161 desc->byte_code_size = 0;
162 memset(&desc->input_signature, 0, sizeof(desc->input_signature));
163 memset(&desc->output_signature, 0, sizeof(desc->output_signature));
164 memset(&desc->patch_constant_signature, 0, sizeof(desc->patch_constant_signature));
166 hr = parse_dxbc(dxbc, dxbc_length, shdr_handler, &ctx);
167 if (!desc->byte_code)
168 hr = E_INVALIDARG;
170 if (FAILED(hr))
172 FIXME("Failed to parse shader, hr %#x.\n", hr);
173 free_shader_desc(desc);
176 return hr;
179 static const char *shader_get_string(const char *data, size_t data_size, DWORD offset)
181 size_t len, max_len;
183 if (offset >= data_size)
185 WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size);
186 return NULL;
189 max_len = data_size - offset;
190 len = strnlen(data + offset, max_len);
192 if (len == max_len)
193 return NULL;
195 return data + offset;
198 HRESULT shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
199 struct wined3d_shader_signature *s)
201 struct wined3d_shader_signature_element *e;
202 const char *ptr = data;
203 unsigned int i;
204 DWORD count;
206 if (!require_space(0, 2, sizeof(DWORD), data_size))
208 WARN("Invalid data size %#x.\n", data_size);
209 return E_INVALIDARG;
212 read_dword(&ptr, &count);
213 TRACE("%u elements.\n", count);
215 skip_dword_unknown(&ptr, 1); /* It seems to always be 0x00000008. */
217 if (!require_space(ptr - data, count, 6 * sizeof(DWORD), data_size))
219 WARN("Invalid count %#x (data size %#x).\n", count, data_size);
220 return E_INVALIDARG;
223 if (!(e = d3d11_calloc(count, sizeof(*e))))
225 ERR("Failed to allocate input signature memory.\n");
226 return E_OUTOFMEMORY;
229 for (i = 0; i < count; ++i)
231 DWORD name_offset;
233 if (tag == TAG_OSG5)
234 read_dword(&ptr, &e[i].stream_idx);
235 else
236 e[i].stream_idx = 0;
237 read_dword(&ptr, &name_offset);
238 if (!(e[i].semantic_name = shader_get_string(data, data_size, name_offset)))
240 WARN("Invalid name offset %#x (data size %#x).\n", name_offset, data_size);
241 HeapFree(GetProcessHeap(), 0, e);
242 return E_INVALIDARG;
244 read_dword(&ptr, &e[i].semantic_idx);
245 read_dword(&ptr, &e[i].sysval_semantic);
246 read_dword(&ptr, &e[i].component_type);
247 read_dword(&ptr, &e[i].register_idx);
248 read_dword(&ptr, &e[i].mask);
250 TRACE("Stream: %u, semantic: %s, semantic idx: %u, sysval_semantic %#x, "
251 "type %u, register idx: %u, use_mask %#x, input_mask %#x.\n",
252 e[i].stream_idx, debugstr_a(e[i].semantic_name), e[i].semantic_idx, e[i].sysval_semantic,
253 e[i].component_type, e[i].register_idx, (e[i].mask >> 8) & 0xff, e[i].mask & 0xff);
256 s->elements = e;
257 s->element_count = count;
259 return S_OK;
262 struct wined3d_shader_signature_element *shader_find_signature_element(const struct wined3d_shader_signature *s,
263 const char *semantic_name, unsigned int semantic_idx, unsigned int stream_idx)
265 struct wined3d_shader_signature_element *e = s->elements;
266 unsigned int i;
268 for (i = 0; i < s->element_count; ++i)
270 if (!strcasecmp(e[i].semantic_name, semantic_name) && e[i].semantic_idx == semantic_idx
271 && e[i].stream_idx == stream_idx)
272 return &e[i];
275 return NULL;
278 void shader_free_signature(struct wined3d_shader_signature *s)
280 HeapFree(GetProcessHeap(), 0, s->elements);
283 /* ID3D11VertexShader methods */
285 static inline struct d3d_vertex_shader *impl_from_ID3D11VertexShader(ID3D11VertexShader *iface)
287 return CONTAINING_RECORD(iface, struct d3d_vertex_shader, ID3D11VertexShader_iface);
290 static HRESULT STDMETHODCALLTYPE d3d11_vertex_shader_QueryInterface(ID3D11VertexShader *iface,
291 REFIID riid, void **object)
293 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
295 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
297 if (IsEqualGUID(riid, &IID_ID3D11VertexShader)
298 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
299 || IsEqualGUID(riid, &IID_IUnknown))
301 ID3D11VertexShader_AddRef(iface);
302 *object = iface;
303 return S_OK;
306 if (IsEqualGUID(riid, &IID_ID3D10VertexShader)
307 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
309 IUnknown_AddRef(&shader->ID3D10VertexShader_iface);
310 *object = &shader->ID3D10VertexShader_iface;
311 return S_OK;
314 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
316 *object = NULL;
317 return E_NOINTERFACE;
320 static ULONG STDMETHODCALLTYPE d3d11_vertex_shader_AddRef(ID3D11VertexShader *iface)
322 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
323 ULONG refcount = InterlockedIncrement(&shader->refcount);
325 TRACE("%p increasing refcount to %u.\n", shader, refcount);
327 if (refcount == 1)
329 ID3D11Device_AddRef(shader->device);
330 wined3d_mutex_lock();
331 wined3d_shader_incref(shader->wined3d_shader);
332 wined3d_mutex_unlock();
335 return refcount;
338 static ULONG STDMETHODCALLTYPE d3d11_vertex_shader_Release(ID3D11VertexShader *iface)
340 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
341 ULONG refcount = InterlockedDecrement(&shader->refcount);
343 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
345 if (!refcount)
347 ID3D11Device *device = shader->device;
349 wined3d_mutex_lock();
350 wined3d_shader_decref(shader->wined3d_shader);
351 wined3d_mutex_unlock();
352 /* Release the device last, it may cause the wined3d device to be
353 * destroyed. */
354 ID3D11Device_Release(device);
357 return refcount;
360 static void STDMETHODCALLTYPE d3d11_vertex_shader_GetDevice(ID3D11VertexShader *iface,
361 ID3D11Device **device)
363 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
365 TRACE("iface %p, device %p.\n", iface, device);
367 *device = shader->device;
368 ID3D11Device_AddRef(*device);
371 static HRESULT STDMETHODCALLTYPE d3d11_vertex_shader_GetPrivateData(ID3D11VertexShader *iface,
372 REFGUID guid, UINT *data_size, void *data)
374 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
376 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
378 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
381 static HRESULT STDMETHODCALLTYPE d3d11_vertex_shader_SetPrivateData(ID3D11VertexShader *iface,
382 REFGUID guid, UINT data_size, const void *data)
384 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
386 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
388 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
391 static HRESULT STDMETHODCALLTYPE d3d11_vertex_shader_SetPrivateDataInterface(ID3D11VertexShader *iface,
392 REFGUID guid, const IUnknown *data)
394 struct d3d_vertex_shader *shader = impl_from_ID3D11VertexShader(iface);
396 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
398 return d3d_set_private_data_interface(&shader->private_store, guid, data);
401 static const struct ID3D11VertexShaderVtbl d3d11_vertex_shader_vtbl =
403 /* IUnknown methods */
404 d3d11_vertex_shader_QueryInterface,
405 d3d11_vertex_shader_AddRef,
406 d3d11_vertex_shader_Release,
407 /* ID3D11DeviceChild methods */
408 d3d11_vertex_shader_GetDevice,
409 d3d11_vertex_shader_GetPrivateData,
410 d3d11_vertex_shader_SetPrivateData,
411 d3d11_vertex_shader_SetPrivateDataInterface,
414 /* ID3D10VertexShader methods */
416 static inline struct d3d_vertex_shader *impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
418 return CONTAINING_RECORD(iface, struct d3d_vertex_shader, ID3D10VertexShader_iface);
421 /* IUnknown methods */
423 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_QueryInterface(ID3D10VertexShader *iface,
424 REFIID riid, void **object)
426 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
428 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
430 return d3d11_vertex_shader_QueryInterface(&shader->ID3D11VertexShader_iface, riid, object);
433 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_AddRef(ID3D10VertexShader *iface)
435 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
437 TRACE("iface %p.\n", iface);
439 return d3d11_vertex_shader_AddRef(&shader->ID3D11VertexShader_iface);
442 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_Release(ID3D10VertexShader *iface)
444 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
446 TRACE("iface %p.\n", iface);
448 return d3d11_vertex_shader_Release(&shader->ID3D11VertexShader_iface);
451 /* ID3D10DeviceChild methods */
453 static void STDMETHODCALLTYPE d3d10_vertex_shader_GetDevice(ID3D10VertexShader *iface, ID3D10Device **device)
455 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
457 TRACE("iface %p, device %p.\n", iface, device);
459 ID3D11Device_QueryInterface(shader->device, &IID_ID3D10Device, (void **)device);
462 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_GetPrivateData(ID3D10VertexShader *iface,
463 REFGUID guid, UINT *data_size, void *data)
465 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
467 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
468 iface, debugstr_guid(guid), data_size, data);
470 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
473 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateData(ID3D10VertexShader *iface,
474 REFGUID guid, UINT data_size, const void *data)
476 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
478 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
479 iface, debugstr_guid(guid), data_size, data);
481 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
484 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateDataInterface(ID3D10VertexShader *iface,
485 REFGUID guid, const IUnknown *data)
487 struct d3d_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
489 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
491 return d3d_set_private_data_interface(&shader->private_store, guid, data);
494 static const struct ID3D10VertexShaderVtbl d3d10_vertex_shader_vtbl =
496 /* IUnknown methods */
497 d3d10_vertex_shader_QueryInterface,
498 d3d10_vertex_shader_AddRef,
499 d3d10_vertex_shader_Release,
500 /* ID3D10DeviceChild methods */
501 d3d10_vertex_shader_GetDevice,
502 d3d10_vertex_shader_GetPrivateData,
503 d3d10_vertex_shader_SetPrivateData,
504 d3d10_vertex_shader_SetPrivateDataInterface,
507 static void STDMETHODCALLTYPE d3d_vertex_shader_wined3d_object_destroyed(void *parent)
509 struct d3d_vertex_shader *shader = parent;
511 wined3d_private_store_cleanup(&shader->private_store);
512 HeapFree(GetProcessHeap(), 0, parent);
515 static const struct wined3d_parent_ops d3d_vertex_shader_wined3d_parent_ops =
517 d3d_vertex_shader_wined3d_object_destroyed,
520 static unsigned int d3d_sm_from_feature_level(D3D_FEATURE_LEVEL feature_level)
522 switch (feature_level)
524 case D3D_FEATURE_LEVEL_11_1:
525 case D3D_FEATURE_LEVEL_11_0:
526 return 5;
527 case D3D_FEATURE_LEVEL_10_1:
528 case D3D_FEATURE_LEVEL_10_0:
529 return 4;
530 case D3D_FEATURE_LEVEL_9_3:
531 return 3;
532 case D3D_FEATURE_LEVEL_9_2:
533 case D3D_FEATURE_LEVEL_9_1:
534 return 2;
535 default:
536 ERR("Unexpected feature_level %#x.\n", feature_level);
538 return 0;
541 static HRESULT d3d_vertex_shader_init(struct d3d_vertex_shader *shader, struct d3d_device *device,
542 const void *byte_code, SIZE_T byte_code_length)
544 struct wined3d_shader_desc desc;
545 HRESULT hr;
547 shader->ID3D11VertexShader_iface.lpVtbl = &d3d11_vertex_shader_vtbl;
548 shader->ID3D10VertexShader_iface.lpVtbl = &d3d10_vertex_shader_vtbl;
549 shader->refcount = 1;
550 wined3d_mutex_lock();
551 wined3d_private_store_init(&shader->private_store);
553 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
555 WARN("Failed to extract shader, hr %#x.\n", hr);
556 wined3d_private_store_cleanup(&shader->private_store);
557 wined3d_mutex_unlock();
558 return hr;
560 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
562 hr = wined3d_shader_create_vs(device->wined3d_device, &desc, shader,
563 &d3d_vertex_shader_wined3d_parent_ops, &shader->wined3d_shader);
564 free_shader_desc(&desc);
565 if (FAILED(hr))
567 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
568 wined3d_private_store_cleanup(&shader->private_store);
569 wined3d_mutex_unlock();
570 return E_INVALIDARG;
572 wined3d_mutex_unlock();
574 shader->device = &device->ID3D11Device_iface;
575 ID3D11Device_AddRef(shader->device);
577 return S_OK;
580 HRESULT d3d_vertex_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
581 struct d3d_vertex_shader **shader)
583 struct d3d_vertex_shader *object;
584 HRESULT hr;
586 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
587 return E_OUTOFMEMORY;
589 if (FAILED(hr = d3d_vertex_shader_init(object, device, byte_code, byte_code_length)))
591 WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
592 HeapFree(GetProcessHeap(), 0, object);
593 return hr;
596 TRACE("Created vertex shader %p.\n", object);
597 *shader = object;
599 return S_OK;
602 struct d3d_vertex_shader *unsafe_impl_from_ID3D11VertexShader(ID3D11VertexShader *iface)
604 if (!iface)
605 return NULL;
606 assert(iface->lpVtbl == &d3d11_vertex_shader_vtbl);
608 return impl_from_ID3D11VertexShader(iface);
611 struct d3d_vertex_shader *unsafe_impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
613 if (!iface)
614 return NULL;
615 assert(iface->lpVtbl == &d3d10_vertex_shader_vtbl);
617 return impl_from_ID3D10VertexShader(iface);
620 /* ID3D11HullShader methods */
622 static inline struct d3d11_hull_shader *impl_from_ID3D11HullShader(ID3D11HullShader *iface)
624 return CONTAINING_RECORD(iface, struct d3d11_hull_shader, ID3D11HullShader_iface);
627 static HRESULT STDMETHODCALLTYPE d3d11_hull_shader_QueryInterface(ID3D11HullShader *iface,
628 REFIID riid, void **object)
630 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
632 if (IsEqualGUID(riid, &IID_ID3D11HullShader)
633 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
634 || IsEqualGUID(riid, &IID_IUnknown))
636 ID3D11HullShader_AddRef(iface);
637 *object = iface;
638 return S_OK;
641 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
643 *object = NULL;
644 return E_NOINTERFACE;
647 static ULONG STDMETHODCALLTYPE d3d11_hull_shader_AddRef(ID3D11HullShader *iface)
649 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
650 ULONG refcount = InterlockedIncrement(&shader->refcount);
652 TRACE("%p increasing refcount to %u.\n", shader, refcount);
654 if (refcount == 1)
656 ID3D11Device_AddRef(shader->device);
657 wined3d_mutex_lock();
658 wined3d_shader_incref(shader->wined3d_shader);
659 wined3d_mutex_unlock();
662 return refcount;
665 static ULONG STDMETHODCALLTYPE d3d11_hull_shader_Release(ID3D11HullShader *iface)
667 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
668 ULONG refcount = InterlockedDecrement(&shader->refcount);
670 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
672 if (!refcount)
674 ID3D11Device *device = shader->device;
676 wined3d_mutex_lock();
677 wined3d_shader_decref(shader->wined3d_shader);
678 wined3d_mutex_unlock();
680 /* Release the device last, it may cause the wined3d device to be
681 * destroyed. */
682 ID3D11Device_Release(device);
685 return refcount;
688 static void STDMETHODCALLTYPE d3d11_hull_shader_GetDevice(ID3D11HullShader *iface,
689 ID3D11Device **device)
691 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
693 TRACE("iface %p, device %p.\n", iface, device);
695 *device = shader->device;
696 ID3D11Device_AddRef(*device);
699 static HRESULT STDMETHODCALLTYPE d3d11_hull_shader_GetPrivateData(ID3D11HullShader *iface,
700 REFGUID guid, UINT *data_size, void *data)
702 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
704 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
706 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
709 static HRESULT STDMETHODCALLTYPE d3d11_hull_shader_SetPrivateData(ID3D11HullShader *iface,
710 REFGUID guid, UINT data_size, const void *data)
712 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
714 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
716 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
719 static HRESULT STDMETHODCALLTYPE d3d11_hull_shader_SetPrivateDataInterface(ID3D11HullShader *iface,
720 REFGUID guid, const IUnknown *data)
722 struct d3d11_hull_shader *shader = impl_from_ID3D11HullShader(iface);
724 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
726 return d3d_set_private_data_interface(&shader->private_store, guid, data);
729 static const struct ID3D11HullShaderVtbl d3d11_hull_shader_vtbl =
731 /* IUnknown methods */
732 d3d11_hull_shader_QueryInterface,
733 d3d11_hull_shader_AddRef,
734 d3d11_hull_shader_Release,
735 /* ID3D11DeviceChild methods */
736 d3d11_hull_shader_GetDevice,
737 d3d11_hull_shader_GetPrivateData,
738 d3d11_hull_shader_SetPrivateData,
739 d3d11_hull_shader_SetPrivateDataInterface,
742 static void STDMETHODCALLTYPE d3d11_hull_shader_wined3d_object_destroyed(void *parent)
744 struct d3d11_hull_shader *shader = parent;
746 wined3d_private_store_cleanup(&shader->private_store);
747 HeapFree(GetProcessHeap(), 0, parent);
750 static const struct wined3d_parent_ops d3d11_hull_shader_wined3d_parent_ops =
752 d3d11_hull_shader_wined3d_object_destroyed,
755 static HRESULT d3d11_hull_shader_init(struct d3d11_hull_shader *shader, struct d3d_device *device,
756 const void *byte_code, SIZE_T byte_code_length)
758 struct wined3d_shader_desc desc;
759 HRESULT hr;
761 shader->ID3D11HullShader_iface.lpVtbl = &d3d11_hull_shader_vtbl;
762 shader->refcount = 1;
763 wined3d_mutex_lock();
764 wined3d_private_store_init(&shader->private_store);
766 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
768 WARN("Failed to extract shader, hr %#x.\n", hr);
769 wined3d_private_store_cleanup(&shader->private_store);
770 wined3d_mutex_unlock();
771 return hr;
773 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
775 hr = wined3d_shader_create_hs(device->wined3d_device, &desc, shader,
776 &d3d11_hull_shader_wined3d_parent_ops, &shader->wined3d_shader);
777 free_shader_desc(&desc);
778 if (FAILED(hr))
780 WARN("Failed to create wined3d hull shader, hr %#x.\n", hr);
781 wined3d_private_store_cleanup(&shader->private_store);
782 wined3d_mutex_unlock();
783 return E_INVALIDARG;
785 wined3d_mutex_unlock();
787 shader->device = &device->ID3D11Device_iface;
788 ID3D11Device_AddRef(shader->device);
790 return S_OK;
793 HRESULT d3d11_hull_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
794 struct d3d11_hull_shader **shader)
796 struct d3d11_hull_shader *object;
797 HRESULT hr;
799 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
800 return E_OUTOFMEMORY;
802 if (FAILED(hr = d3d11_hull_shader_init(object, device, byte_code, byte_code_length)))
804 HeapFree(GetProcessHeap(), 0, object);
805 return hr;
808 TRACE("Created hull shader %p.\n", object);
809 *shader = object;
811 return S_OK;
814 struct d3d11_hull_shader *unsafe_impl_from_ID3D11HullShader(ID3D11HullShader *iface)
816 if (!iface)
817 return NULL;
818 assert(iface->lpVtbl == &d3d11_hull_shader_vtbl);
820 return impl_from_ID3D11HullShader(iface);
823 /* ID3D11DomainShader methods */
825 static inline struct d3d11_domain_shader *impl_from_ID3D11DomainShader(ID3D11DomainShader *iface)
827 return CONTAINING_RECORD(iface, struct d3d11_domain_shader, ID3D11DomainShader_iface);
830 static HRESULT STDMETHODCALLTYPE d3d11_domain_shader_QueryInterface(ID3D11DomainShader *iface,
831 REFIID riid, void **object)
833 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
835 if (IsEqualGUID(riid, &IID_ID3D11DomainShader)
836 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
837 || IsEqualGUID(riid, &IID_IUnknown))
839 ID3D11DomainShader_AddRef(iface);
840 *object = iface;
841 return S_OK;
844 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
846 *object = NULL;
847 return E_NOINTERFACE;
850 static ULONG STDMETHODCALLTYPE d3d11_domain_shader_AddRef(ID3D11DomainShader *iface)
852 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
853 ULONG refcount = InterlockedIncrement(&shader->refcount);
855 TRACE("%p increasing refcount to %u.\n", shader, refcount);
857 if (refcount == 1)
859 ID3D11Device_AddRef(shader->device);
860 wined3d_mutex_lock();
861 wined3d_shader_incref(shader->wined3d_shader);
862 wined3d_mutex_unlock();
865 return refcount;
868 static ULONG STDMETHODCALLTYPE d3d11_domain_shader_Release(ID3D11DomainShader *iface)
870 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
871 ULONG refcount = InterlockedDecrement(&shader->refcount);
873 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
875 if (!refcount)
877 ID3D11Device *device = shader->device;
879 wined3d_mutex_lock();
880 wined3d_shader_decref(shader->wined3d_shader);
881 wined3d_mutex_unlock();
883 /* Release the device last, it may cause the wined3d device to be
884 * destroyed. */
885 ID3D11Device_Release(device);
888 return refcount;
891 static void STDMETHODCALLTYPE d3d11_domain_shader_GetDevice(ID3D11DomainShader *iface,
892 ID3D11Device **device)
894 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
896 TRACE("iface %p, device %p.\n", iface, device);
898 *device = shader->device;
899 ID3D11Device_AddRef(*device);
902 static HRESULT STDMETHODCALLTYPE d3d11_domain_shader_GetPrivateData(ID3D11DomainShader *iface,
903 REFGUID guid, UINT *data_size, void *data)
905 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
907 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
909 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
912 static HRESULT STDMETHODCALLTYPE d3d11_domain_shader_SetPrivateData(ID3D11DomainShader *iface,
913 REFGUID guid, UINT data_size, const void *data)
915 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
917 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
919 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
922 static HRESULT STDMETHODCALLTYPE d3d11_domain_shader_SetPrivateDataInterface(ID3D11DomainShader *iface,
923 REFGUID guid, const IUnknown *data)
925 struct d3d11_domain_shader *shader = impl_from_ID3D11DomainShader(iface);
927 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
929 return d3d_set_private_data_interface(&shader->private_store, guid, data);
932 static const struct ID3D11DomainShaderVtbl d3d11_domain_shader_vtbl =
934 /* IUnknown methods */
935 d3d11_domain_shader_QueryInterface,
936 d3d11_domain_shader_AddRef,
937 d3d11_domain_shader_Release,
938 /* ID3D11DeviceChild methods */
939 d3d11_domain_shader_GetDevice,
940 d3d11_domain_shader_GetPrivateData,
941 d3d11_domain_shader_SetPrivateData,
942 d3d11_domain_shader_SetPrivateDataInterface,
945 static void STDMETHODCALLTYPE d3d11_domain_shader_wined3d_object_destroyed(void *parent)
947 struct d3d11_domain_shader *shader = parent;
949 wined3d_private_store_cleanup(&shader->private_store);
950 HeapFree(GetProcessHeap(), 0, parent);
953 static const struct wined3d_parent_ops d3d11_domain_shader_wined3d_parent_ops =
955 d3d11_domain_shader_wined3d_object_destroyed,
958 static HRESULT d3d11_domain_shader_init(struct d3d11_domain_shader *shader, struct d3d_device *device,
959 const void *byte_code, SIZE_T byte_code_length)
961 struct wined3d_shader_desc desc;
962 HRESULT hr;
964 shader->ID3D11DomainShader_iface.lpVtbl = &d3d11_domain_shader_vtbl;
965 shader->refcount = 1;
966 wined3d_mutex_lock();
967 wined3d_private_store_init(&shader->private_store);
969 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
971 WARN("Failed to extract shader, hr %#x.\n", hr);
972 wined3d_private_store_cleanup(&shader->private_store);
973 wined3d_mutex_unlock();
974 return hr;
976 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
978 hr = wined3d_shader_create_ds(device->wined3d_device, &desc, shader,
979 &d3d11_domain_shader_wined3d_parent_ops, &shader->wined3d_shader);
980 free_shader_desc(&desc);
981 if (FAILED(hr))
983 WARN("Failed to create wined3d domain shader, hr %#x.\n", hr);
984 wined3d_private_store_cleanup(&shader->private_store);
985 wined3d_mutex_unlock();
986 return E_INVALIDARG;
988 wined3d_mutex_unlock();
990 shader->device = &device->ID3D11Device_iface;
991 ID3D11Device_AddRef(shader->device);
993 return S_OK;
996 HRESULT d3d11_domain_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
997 struct d3d11_domain_shader **shader)
999 struct d3d11_domain_shader *object;
1000 HRESULT hr;
1002 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
1003 return E_OUTOFMEMORY;
1005 if (FAILED(hr = d3d11_domain_shader_init(object, device, byte_code, byte_code_length)))
1007 HeapFree(GetProcessHeap(), 0, object);
1008 return hr;
1011 TRACE("Created domain shader %p.\n", object);
1012 *shader = object;
1014 return S_OK;
1017 struct d3d11_domain_shader *unsafe_impl_from_ID3D11DomainShader(ID3D11DomainShader *iface)
1019 if (!iface)
1020 return NULL;
1021 assert(iface->lpVtbl == &d3d11_domain_shader_vtbl);
1023 return impl_from_ID3D11DomainShader(iface);
1026 /* ID3D11GeometryShader methods */
1028 static inline struct d3d_geometry_shader *impl_from_ID3D11GeometryShader(ID3D11GeometryShader *iface)
1030 return CONTAINING_RECORD(iface, struct d3d_geometry_shader, ID3D11GeometryShader_iface);
1033 static HRESULT STDMETHODCALLTYPE d3d11_geometry_shader_QueryInterface(ID3D11GeometryShader *iface,
1034 REFIID riid, void **object)
1036 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1038 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1040 if (IsEqualGUID(riid, &IID_ID3D11GeometryShader)
1041 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1042 || IsEqualGUID(riid, &IID_IUnknown))
1044 ID3D11GeometryShader_AddRef(iface);
1045 *object = iface;
1046 return S_OK;
1049 if (IsEqualGUID(riid, &IID_ID3D10GeometryShader)
1050 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
1052 ID3D10GeometryShader_AddRef(&shader->ID3D10GeometryShader_iface);
1053 *object = &shader->ID3D10GeometryShader_iface;
1054 return S_OK;
1057 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1059 *object = NULL;
1060 return E_NOINTERFACE;
1063 static ULONG STDMETHODCALLTYPE d3d11_geometry_shader_AddRef(ID3D11GeometryShader *iface)
1065 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1066 ULONG refcount = InterlockedIncrement(&shader->refcount);
1068 TRACE("%p increasing refcount to %u.\n", shader, refcount);
1070 if (refcount == 1)
1072 ID3D11Device_AddRef(shader->device);
1073 wined3d_mutex_lock();
1074 wined3d_shader_incref(shader->wined3d_shader);
1075 wined3d_mutex_unlock();
1078 return refcount;
1081 static ULONG STDMETHODCALLTYPE d3d11_geometry_shader_Release(ID3D11GeometryShader *iface)
1083 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1084 ULONG refcount = InterlockedDecrement(&shader->refcount);
1086 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
1088 if (!refcount)
1090 ID3D11Device *device = shader->device;
1092 wined3d_mutex_lock();
1093 wined3d_shader_decref(shader->wined3d_shader);
1094 wined3d_mutex_unlock();
1096 /* Release the device last, it may cause the wined3d device to be
1097 * destroyed. */
1098 ID3D11Device_Release(device);
1101 return refcount;
1104 static void STDMETHODCALLTYPE d3d11_geometry_shader_GetDevice(ID3D11GeometryShader *iface,
1105 ID3D11Device **device)
1107 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1109 TRACE("iface %p, device %p.\n", iface, device);
1111 *device = shader->device;
1112 ID3D11Device_AddRef(*device);
1115 static HRESULT STDMETHODCALLTYPE d3d11_geometry_shader_GetPrivateData(ID3D11GeometryShader *iface,
1116 REFGUID guid, UINT *data_size, void *data)
1118 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1120 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1122 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
1125 static HRESULT STDMETHODCALLTYPE d3d11_geometry_shader_SetPrivateData(ID3D11GeometryShader *iface,
1126 REFGUID guid, UINT data_size, const void *data)
1128 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1130 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1132 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
1135 static HRESULT STDMETHODCALLTYPE d3d11_geometry_shader_SetPrivateDataInterface(ID3D11GeometryShader *iface,
1136 REFGUID guid, const IUnknown *data)
1138 struct d3d_geometry_shader *shader = impl_from_ID3D11GeometryShader(iface);
1140 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1142 return d3d_set_private_data_interface(&shader->private_store, guid, data);
1145 static const struct ID3D11GeometryShaderVtbl d3d11_geometry_shader_vtbl =
1147 /* IUnknown methods */
1148 d3d11_geometry_shader_QueryInterface,
1149 d3d11_geometry_shader_AddRef,
1150 d3d11_geometry_shader_Release,
1151 /* ID3D11DeviceChild methods */
1152 d3d11_geometry_shader_GetDevice,
1153 d3d11_geometry_shader_GetPrivateData,
1154 d3d11_geometry_shader_SetPrivateData,
1155 d3d11_geometry_shader_SetPrivateDataInterface,
1158 /* ID3D10GeometryShader methods */
1160 static inline struct d3d_geometry_shader *impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface)
1162 return CONTAINING_RECORD(iface, struct d3d_geometry_shader, ID3D10GeometryShader_iface);
1165 /* IUnknown methods */
1167 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_QueryInterface(ID3D10GeometryShader *iface,
1168 REFIID riid, void **object)
1170 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1172 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1174 return d3d11_geometry_shader_QueryInterface(&shader->ID3D11GeometryShader_iface, riid, object);
1177 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_AddRef(ID3D10GeometryShader *iface)
1179 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1181 TRACE("iface %p.\n", iface);
1183 return d3d11_geometry_shader_AddRef(&shader->ID3D11GeometryShader_iface);
1186 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_Release(ID3D10GeometryShader *iface)
1188 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1190 TRACE("iface %p.\n", iface);
1192 return d3d11_geometry_shader_Release(&shader->ID3D11GeometryShader_iface);
1195 /* ID3D10DeviceChild methods */
1197 static void STDMETHODCALLTYPE d3d10_geometry_shader_GetDevice(ID3D10GeometryShader *iface, ID3D10Device **device)
1199 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1201 TRACE("iface %p, device %p.\n", iface, device);
1203 ID3D11Device_QueryInterface(shader->device, &IID_ID3D10Device, (void **)device);
1206 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_GetPrivateData(ID3D10GeometryShader *iface,
1207 REFGUID guid, UINT *data_size, void *data)
1209 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1211 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1212 iface, debugstr_guid(guid), data_size, data);
1214 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
1217 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateData(ID3D10GeometryShader *iface,
1218 REFGUID guid, UINT data_size, const void *data)
1220 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1222 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1223 iface, debugstr_guid(guid), data_size, data);
1225 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
1228 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateDataInterface(ID3D10GeometryShader *iface,
1229 REFGUID guid, const IUnknown *data)
1231 struct d3d_geometry_shader *shader = impl_from_ID3D10GeometryShader(iface);
1233 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1235 return d3d_set_private_data_interface(&shader->private_store, guid, data);
1238 static const struct ID3D10GeometryShaderVtbl d3d10_geometry_shader_vtbl =
1240 /* IUnknown methods */
1241 d3d10_geometry_shader_QueryInterface,
1242 d3d10_geometry_shader_AddRef,
1243 d3d10_geometry_shader_Release,
1244 /* ID3D10DeviceChild methods */
1245 d3d10_geometry_shader_GetDevice,
1246 d3d10_geometry_shader_GetPrivateData,
1247 d3d10_geometry_shader_SetPrivateData,
1248 d3d10_geometry_shader_SetPrivateDataInterface,
1251 static void STDMETHODCALLTYPE d3d_geometry_shader_wined3d_object_destroyed(void *parent)
1253 struct d3d_geometry_shader *shader = parent;
1255 wined3d_private_store_cleanup(&shader->private_store);
1256 HeapFree(GetProcessHeap(), 0, parent);
1259 static const struct wined3d_parent_ops d3d_geometry_shader_wined3d_parent_ops =
1261 d3d_geometry_shader_wined3d_object_destroyed,
1264 static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_output_element *elements,
1265 const D3D11_SO_DECLARATION_ENTRY *entries, unsigned int entry_count,
1266 const unsigned int *buffer_strides, unsigned int buffer_stride_count,
1267 const struct wined3d_shader_signature *os, D3D_FEATURE_LEVEL feature_level)
1269 unsigned int i, j, mask;
1271 for (i = 0; i < entry_count; ++i)
1273 struct wined3d_stream_output_element *e = &elements[i];
1274 const D3D11_SO_DECLARATION_ENTRY *f = &entries[i];
1275 struct wined3d_shader_signature_element *output;
1277 TRACE("Stream: %u, semantic: %s, semantic idx: %u, start component: %u, "
1278 "component count %u, output slot %u.\n",
1279 f->Stream, debugstr_a(f->SemanticName), f->SemanticIndex,
1280 f->StartComponent, f->ComponentCount, f->OutputSlot);
1282 if (f->Stream >= D3D11_SO_STREAM_COUNT)
1284 WARN("Invalid stream %u.\n", f->Stream);
1285 return E_INVALIDARG;
1287 if (f->Stream && feature_level < D3D_FEATURE_LEVEL_11_0)
1289 WARN("Invalid stream %u for feature level %#x.\n", f->Stream, feature_level);
1290 return E_INVALIDARG;
1292 if (f->Stream)
1294 FIXME("Streams not implemented yet.\n");
1295 return E_INVALIDARG;
1297 if (f->OutputSlot >= D3D11_SO_BUFFER_SLOT_COUNT)
1299 WARN("Invalid output slot %u.\n", f->OutputSlot);
1300 return E_INVALIDARG;
1303 e->stream_idx = f->Stream;
1304 e->component_idx = f->StartComponent;
1305 e->component_count = f->ComponentCount;
1306 e->output_slot = f->OutputSlot;
1308 if (!f->SemanticName)
1310 if (f->SemanticIndex)
1312 WARN("Invalid semantic idx %u for stream output gap.\n", f->SemanticIndex);
1313 return E_INVALIDARG;
1315 if (e->component_idx || !e->component_count)
1317 WARN("Invalid stream output gap %u-%u.\n", e->component_idx, e->component_count);
1318 return E_INVALIDARG;
1321 e->register_idx = WINED3D_STREAM_OUTPUT_GAP;
1323 else if ((output = shader_find_signature_element(os, f->SemanticName, f->SemanticIndex, f->Stream)))
1325 if (e->component_idx > 3 || e->component_count > 4 || !e->component_count
1326 || e->component_idx + e->component_count > 4)
1328 WARN("Invalid component range %u-%u.\n", e->component_idx, e->component_count);
1329 return E_INVALIDARG;
1332 for (j = 0; j < 4; ++j)
1334 if ((1u << j) & output->mask)
1335 break;
1337 e->component_idx += j;
1338 mask = ((1u << e->component_count) - 1) << e->component_idx;
1339 if ((output->mask & 0xff & mask) != mask)
1341 WARN("Invalid component range %u-%u (mask %#x), output mask %#x.\n",
1342 e->component_idx, e->component_count, mask, output->mask & 0xff);
1343 return E_INVALIDARG;
1346 e->register_idx = output->register_idx;
1347 TRACE("Register idx: %u, register component idx %u, register mask %#x.\n",
1348 e->register_idx, e->component_idx, mask);
1350 else
1352 WARN("Failed to find output signature element for stream output entry.\n");
1353 return E_INVALIDARG;
1357 for (i = 0; i < entry_count; ++i)
1359 const struct wined3d_stream_output_element *e1 = &elements[i];
1360 if (e1->register_idx == WINED3D_STREAM_OUTPUT_GAP)
1361 continue;
1363 for (j = i + 1; j < entry_count; ++j)
1365 const struct wined3d_stream_output_element *e2 = &elements[j];
1367 if (e1->register_idx == e2->register_idx
1368 && e1->component_idx < e2->component_idx + e2->component_count
1369 && e1->component_idx + e1->component_count > e2->component_idx)
1371 WARN("Stream output elements %u and %u overlap.\n", i, j);
1372 return E_INVALIDARG;
1377 for (i = 0; i < D3D11_SO_STREAM_COUNT; ++i)
1379 unsigned int current_stride[D3D11_SO_BUFFER_SLOT_COUNT] = {0};
1380 unsigned int element_count[D3D11_SO_BUFFER_SLOT_COUNT] = {0};
1381 unsigned int gap_count[D3D11_SO_BUFFER_SLOT_COUNT] = {0};
1383 for (j = 0; j < entry_count; ++j)
1385 const struct wined3d_stream_output_element *e = &elements[j];
1387 if (e->stream_idx != i)
1388 continue;
1389 current_stride[e->output_slot] += 4 * e->component_count;
1390 ++element_count[e->output_slot];
1391 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
1392 ++gap_count[e->output_slot];
1395 for (j = 0; j < D3D11_SO_BUFFER_SLOT_COUNT; ++j)
1397 if (!element_count[j])
1398 continue;
1399 if (element_count[j] == gap_count[j])
1401 WARN("Stream %u, output slot %u contains only gaps.\n", i, j);
1402 return E_INVALIDARG;
1404 if (buffer_stride_count)
1406 if (buffer_stride_count <= j)
1408 WARN("Buffer strides are required for all buffer slots.\n");
1409 return E_INVALIDARG;
1411 if (buffer_strides[j] < current_stride[j] || buffer_strides[j] % 4)
1413 WARN("Invalid stride %u for buffer slot %u.\n", buffer_strides[j], j);
1414 return E_INVALIDARG;
1419 if (!i && feature_level < D3D_FEATURE_LEVEL_11_0 && element_count[0] != entry_count)
1421 for (j = 0; j < ARRAY_SIZE(element_count); ++j)
1423 if (element_count[j] > 1)
1425 WARN("Only one element per output slot is allowed.\n");
1426 return E_INVALIDARG;
1432 return S_OK;
1435 static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader,
1436 struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
1437 const D3D11_SO_DECLARATION_ENTRY *so_entries, unsigned int so_entry_count,
1438 const unsigned int *buffer_strides, unsigned int buffer_stride_count,
1439 unsigned int rasterizer_stream)
1441 struct wined3d_stream_output_desc so_desc;
1442 struct wined3d_shader_desc desc;
1443 unsigned int i;
1444 HRESULT hr;
1446 if (so_entry_count > D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT)
1448 WARN("Entry count %u is greater than %u.\n",
1449 so_entry_count, D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT);
1450 return E_INVALIDARG;
1452 if (so_entries && !so_entry_count)
1454 WARN("Invalid SO entry count %u.\n", so_entry_count);
1455 return E_INVALIDARG;
1457 if (rasterizer_stream != D3D11_SO_NO_RASTERIZED_STREAM && rasterizer_stream >= D3D11_SO_STREAM_COUNT)
1459 WARN("Invalid rasterizer stream %u.\n", rasterizer_stream);
1460 return E_INVALIDARG;
1462 if (device->feature_level < D3D_FEATURE_LEVEL_11_0)
1464 if (rasterizer_stream)
1466 WARN("Invalid rasterizer stream %u for feature level %#x.\n",
1467 rasterizer_stream, device->feature_level);
1468 return E_INVALIDARG;
1470 if (buffer_stride_count && buffer_stride_count != 1)
1472 WARN("Invalid buffer stride count %u for feature level %#x.\n",
1473 buffer_stride_count, device->feature_level);
1474 return E_INVALIDARG;
1478 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
1480 WARN("Failed to extract shader, hr %#x.\n", hr);
1481 return hr;
1483 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
1485 memset(&so_desc, 0, sizeof(so_desc));
1486 if (so_entries)
1488 so_desc.element_count = so_entry_count;
1489 for (i = 0; i < min(buffer_stride_count, ARRAY_SIZE(so_desc.buffer_strides)); ++i)
1490 so_desc.buffer_strides[i] = buffer_strides[i];
1491 so_desc.buffer_stride_count = buffer_stride_count;
1492 so_desc.rasterizer_stream_idx = rasterizer_stream;
1494 if (!(so_desc.elements = d3d11_calloc(so_entry_count, sizeof(*so_desc.elements))))
1496 ERR("Failed to allocate wined3d stream output element array memory.\n");
1497 free_shader_desc(&desc);
1498 return E_OUTOFMEMORY;
1500 if (FAILED(hr = wined3d_so_elements_from_d3d11_so_entries(so_desc.elements,
1501 so_entries, so_entry_count, buffer_strides, buffer_stride_count,
1502 &desc.output_signature, device->feature_level)))
1504 HeapFree(GetProcessHeap(), 0, so_desc.elements);
1505 free_shader_desc(&desc);
1506 return hr;
1510 shader->ID3D11GeometryShader_iface.lpVtbl = &d3d11_geometry_shader_vtbl;
1511 shader->ID3D10GeometryShader_iface.lpVtbl = &d3d10_geometry_shader_vtbl;
1512 shader->refcount = 1;
1513 wined3d_mutex_lock();
1514 wined3d_private_store_init(&shader->private_store);
1516 hr = wined3d_shader_create_gs(device->wined3d_device, &desc, so_entries ? &so_desc : NULL,
1517 shader, &d3d_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader);
1518 HeapFree(GetProcessHeap(), 0, so_desc.elements);
1519 free_shader_desc(&desc);
1520 if (FAILED(hr))
1522 WARN("Failed to create wined3d geometry shader, hr %#x.\n", hr);
1523 wined3d_private_store_cleanup(&shader->private_store);
1524 wined3d_mutex_unlock();
1525 return E_INVALIDARG;
1527 wined3d_mutex_unlock();
1529 shader->device = &device->ID3D11Device_iface;
1530 ID3D11Device_AddRef(shader->device);
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 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 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 HeapFree(GetProcessHeap(), 0, 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 ID3D11Device_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 ID3D11Device *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 ID3D11Device_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 = 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 ID3D11Device_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 HeapFree(GetProcessHeap(), 0, 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 shader->device = &device->ID3D11Device_iface;
1849 ID3D11Device_AddRef(shader->device);
1851 return S_OK;
1854 HRESULT d3d_pixel_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
1855 struct d3d_pixel_shader **shader)
1857 struct d3d_pixel_shader *object;
1858 HRESULT hr;
1860 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
1861 return E_OUTOFMEMORY;
1863 if (FAILED(hr = d3d_pixel_shader_init(object, device, byte_code, byte_code_length)))
1865 WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
1866 HeapFree(GetProcessHeap(), 0, object);
1867 return hr;
1870 TRACE("Created pixel shader %p.\n", object);
1871 *shader = object;
1873 return S_OK;
1876 struct d3d_pixel_shader *unsafe_impl_from_ID3D11PixelShader(ID3D11PixelShader *iface)
1878 if (!iface)
1879 return NULL;
1880 assert(iface->lpVtbl == &d3d11_pixel_shader_vtbl);
1882 return impl_from_ID3D11PixelShader(iface);
1885 struct d3d_pixel_shader *unsafe_impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
1887 if (!iface)
1888 return NULL;
1889 assert(iface->lpVtbl == &d3d10_pixel_shader_vtbl);
1891 return impl_from_ID3D10PixelShader(iface);
1894 /* ID3D11ComputeShader methods */
1896 static inline struct d3d11_compute_shader *impl_from_ID3D11ComputeShader(ID3D11ComputeShader *iface)
1898 return CONTAINING_RECORD(iface, struct d3d11_compute_shader, ID3D11ComputeShader_iface);
1901 static HRESULT STDMETHODCALLTYPE d3d11_compute_shader_QueryInterface(ID3D11ComputeShader *iface,
1902 REFIID riid, void **object)
1904 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1906 if (IsEqualGUID(riid, &IID_ID3D11ComputeShader)
1907 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1908 || IsEqualGUID(riid, &IID_IUnknown))
1910 ID3D11ComputeShader_AddRef(*object = iface);
1911 return S_OK;
1914 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1916 *object = NULL;
1917 return E_NOINTERFACE;
1920 static ULONG STDMETHODCALLTYPE d3d11_compute_shader_AddRef(ID3D11ComputeShader *iface)
1922 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1923 ULONG refcount = InterlockedIncrement(&shader->refcount);
1925 TRACE("%p increasing refcount to %u.\n", shader, refcount);
1927 if (refcount == 1)
1929 ID3D11Device_AddRef(shader->device);
1930 wined3d_mutex_lock();
1931 wined3d_shader_incref(shader->wined3d_shader);
1932 wined3d_mutex_unlock();
1935 return refcount;
1938 static ULONG STDMETHODCALLTYPE d3d11_compute_shader_Release(ID3D11ComputeShader *iface)
1940 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1941 ULONG refcount = InterlockedDecrement(&shader->refcount);
1943 TRACE("%p decreasing refcount to %u.\n", shader, refcount);
1945 if (!refcount)
1947 ID3D11Device *device = shader->device;
1949 wined3d_mutex_lock();
1950 wined3d_shader_decref(shader->wined3d_shader);
1951 wined3d_mutex_unlock();
1953 /* Release the device last, it may cause the wined3d device to be
1954 * destroyed. */
1955 ID3D11Device_Release(device);
1958 return refcount;
1961 static void STDMETHODCALLTYPE d3d11_compute_shader_GetDevice(ID3D11ComputeShader *iface,
1962 ID3D11Device **device)
1964 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1966 TRACE("iface %p, device %p.\n", iface, device);
1968 ID3D11Device_AddRef(*device = shader->device);
1971 static HRESULT STDMETHODCALLTYPE d3d11_compute_shader_GetPrivateData(ID3D11ComputeShader *iface,
1972 REFGUID guid, UINT *data_size, void *data)
1974 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1976 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1978 return d3d_get_private_data(&shader->private_store, guid, data_size, data);
1981 static HRESULT STDMETHODCALLTYPE d3d11_compute_shader_SetPrivateData(ID3D11ComputeShader *iface,
1982 REFGUID guid, UINT data_size, const void *data)
1984 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1986 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1988 return d3d_set_private_data(&shader->private_store, guid, data_size, data);
1991 static HRESULT STDMETHODCALLTYPE d3d11_compute_shader_SetPrivateDataInterface(ID3D11ComputeShader *iface,
1992 REFGUID guid, const IUnknown *data)
1994 struct d3d11_compute_shader *shader = impl_from_ID3D11ComputeShader(iface);
1996 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1998 return d3d_set_private_data_interface(&shader->private_store, guid, data);
2001 static const struct ID3D11ComputeShaderVtbl d3d11_compute_shader_vtbl =
2003 /* IUnknown methods */
2004 d3d11_compute_shader_QueryInterface,
2005 d3d11_compute_shader_AddRef,
2006 d3d11_compute_shader_Release,
2007 /* ID3D11DeviceChild methods */
2008 d3d11_compute_shader_GetDevice,
2009 d3d11_compute_shader_GetPrivateData,
2010 d3d11_compute_shader_SetPrivateData,
2011 d3d11_compute_shader_SetPrivateDataInterface,
2014 static void STDMETHODCALLTYPE d3d11_compute_shader_wined3d_object_destroyed(void *parent)
2016 struct d3d11_compute_shader *shader = parent;
2018 wined3d_private_store_cleanup(&shader->private_store);
2019 HeapFree(GetProcessHeap(), 0, parent);
2022 static const struct wined3d_parent_ops d3d11_compute_shader_wined3d_parent_ops =
2024 d3d11_compute_shader_wined3d_object_destroyed,
2027 static HRESULT d3d11_compute_shader_init(struct d3d11_compute_shader *shader, struct d3d_device *device,
2028 const void *byte_code, SIZE_T byte_code_length)
2030 struct wined3d_shader_desc desc;
2031 HRESULT hr;
2033 shader->ID3D11ComputeShader_iface.lpVtbl = &d3d11_compute_shader_vtbl;
2034 shader->refcount = 1;
2035 wined3d_mutex_lock();
2036 wined3d_private_store_init(&shader->private_store);
2038 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level)))
2040 WARN("Failed to extract shader, hr %#x.\n", hr);
2041 wined3d_private_store_cleanup(&shader->private_store);
2042 wined3d_mutex_unlock();
2043 return hr;
2045 desc.max_version = d3d_sm_from_feature_level(device->feature_level);
2047 hr = wined3d_shader_create_cs(device->wined3d_device, &desc, shader,
2048 &d3d11_compute_shader_wined3d_parent_ops, &shader->wined3d_shader);
2049 free_shader_desc(&desc);
2050 if (FAILED(hr))
2052 WARN("Failed to create wined3d compute shader, hr %#x.\n", hr);
2053 wined3d_private_store_cleanup(&shader->private_store);
2054 wined3d_mutex_unlock();
2055 return E_INVALIDARG;
2057 wined3d_mutex_unlock();
2059 ID3D11Device_AddRef(shader->device = &device->ID3D11Device_iface);
2061 return S_OK;
2064 HRESULT d3d11_compute_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length,
2065 struct d3d11_compute_shader **shader)
2067 struct d3d11_compute_shader *object;
2068 HRESULT hr;
2070 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
2071 return E_OUTOFMEMORY;
2073 if (FAILED(hr = d3d11_compute_shader_init(object, device, byte_code, byte_code_length)))
2075 HeapFree(GetProcessHeap(), 0, object);
2076 return hr;
2079 TRACE("Created compute shader %p.\n", object);
2080 *shader = object;
2082 return S_OK;
2085 struct d3d11_compute_shader *unsafe_impl_from_ID3D11ComputeShader(ID3D11ComputeShader *iface)
2087 if (!iface)
2088 return NULL;
2089 assert(iface->lpVtbl == &d3d11_compute_shader_vtbl);
2091 return impl_from_ID3D11ComputeShader(iface);
2094 /* ID3D11ClassLinkage methods */
2096 static inline struct d3d11_class_linkage *impl_from_ID3D11ClassLinkage(ID3D11ClassLinkage *iface)
2098 return CONTAINING_RECORD(iface, struct d3d11_class_linkage, ID3D11ClassLinkage_iface);
2101 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_QueryInterface(ID3D11ClassLinkage *iface,
2102 REFIID riid, void **object)
2104 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
2106 if (IsEqualGUID(riid, &IID_ID3D11ClassLinkage)
2107 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
2108 || IsEqualGUID(riid, &IID_IUnknown))
2110 ID3D11ClassLinkage_AddRef(*object = iface);
2111 return S_OK;
2114 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
2116 *object = NULL;
2117 return E_NOINTERFACE;
2120 static ULONG STDMETHODCALLTYPE d3d11_class_linkage_AddRef(ID3D11ClassLinkage *iface)
2122 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2123 ULONG refcount = InterlockedIncrement(&class_linkage->refcount);
2125 TRACE("%p increasing refcount to %u.\n", class_linkage, refcount);
2127 return refcount;
2130 static ULONG STDMETHODCALLTYPE d3d11_class_linkage_Release(ID3D11ClassLinkage *iface)
2132 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2133 ULONG refcount = InterlockedDecrement(&class_linkage->refcount);
2135 TRACE("%p decreasing refcount to %u.\n", class_linkage, refcount);
2137 if (!refcount)
2139 ID3D11Device *device = class_linkage->device;
2141 wined3d_private_store_cleanup(&class_linkage->private_store);
2142 HeapFree(GetProcessHeap(), 0, class_linkage);
2144 ID3D11Device_Release(device);
2147 return refcount;
2150 static void STDMETHODCALLTYPE d3d11_class_linkage_GetDevice(ID3D11ClassLinkage *iface,
2151 ID3D11Device **device)
2153 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2155 TRACE("iface %p, device %p.\n", iface, device);
2157 ID3D11Device_AddRef(*device = class_linkage->device);
2160 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_GetPrivateData(ID3D11ClassLinkage *iface,
2161 REFGUID guid, UINT *data_size, void *data)
2163 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2165 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
2167 return d3d_get_private_data(&class_linkage->private_store, guid, data_size, data);
2170 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_SetPrivateData(ID3D11ClassLinkage *iface,
2171 REFGUID guid, UINT data_size, const void *data)
2173 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2175 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
2177 return d3d_set_private_data(&class_linkage->private_store, guid, data_size, data);
2180 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_SetPrivateDataInterface(ID3D11ClassLinkage *iface,
2181 REFGUID guid, const IUnknown *data)
2183 struct d3d11_class_linkage *class_linkage = impl_from_ID3D11ClassLinkage(iface);
2185 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
2187 return d3d_set_private_data_interface(&class_linkage->private_store, guid, data);
2190 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_GetClassInstance(ID3D11ClassLinkage *iface,
2191 const char *instance_name, UINT instance_index, ID3D11ClassInstance **class_instance)
2193 FIXME("iface %p, instance_name %s, instance_index %u, class_instance %p stub!\n",
2194 iface, debugstr_a(instance_name), instance_index, class_instance);
2196 return E_NOTIMPL;
2199 static HRESULT STDMETHODCALLTYPE d3d11_class_linkage_CreateClassInstance(ID3D11ClassLinkage *iface,
2200 const char *type_name, UINT cb_offset, UINT cb_vector_offset, UINT texture_offset,
2201 UINT sampler_offset, ID3D11ClassInstance **class_instance)
2203 FIXME("iface %p, type_name %s, cb_offset %u, cb_vector_offset %u, texture_offset %u, "
2204 "sampler_offset %u, class_instance %p stub!\n",
2205 iface, debugstr_a(type_name), cb_offset, cb_vector_offset, texture_offset,
2206 sampler_offset, class_instance);
2208 return E_NOTIMPL;
2211 static const struct ID3D11ClassLinkageVtbl d3d11_class_linkage_vtbl =
2213 /* IUnknown methods */
2214 d3d11_class_linkage_QueryInterface,
2215 d3d11_class_linkage_AddRef,
2216 d3d11_class_linkage_Release,
2217 /* ID3D11DeviceChild methods */
2218 d3d11_class_linkage_GetDevice,
2219 d3d11_class_linkage_GetPrivateData,
2220 d3d11_class_linkage_SetPrivateData,
2221 d3d11_class_linkage_SetPrivateDataInterface,
2222 /* ID3D11ClassLinkage methods */
2223 d3d11_class_linkage_GetClassInstance,
2224 d3d11_class_linkage_CreateClassInstance,
2227 HRESULT d3d11_class_linkage_create(struct d3d_device *device, struct d3d11_class_linkage **class_linkage)
2229 struct d3d11_class_linkage *object;
2231 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
2232 return E_OUTOFMEMORY;
2234 object->ID3D11ClassLinkage_iface.lpVtbl = &d3d11_class_linkage_vtbl;
2235 object->refcount = 1;
2236 wined3d_private_store_init(&object->private_store);
2238 ID3D11Device_AddRef(object->device = &device->ID3D11Device_iface);
2240 TRACE("Created class linkage %p.\n", object);
2241 *class_linkage = object;
2243 return S_OK;