gallium: remove pipe_surface::usage
[mesa.git] / src / gallium / state_trackers / d3d1x / gd3d11 / d3d11_screen.h
1 /**************************************************************************
2 *
3 * Copyright 2010 Luca Barbieri
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27 DEBUG_GET_ONCE_BOOL_OPTION(dump_shaders, "D3D1X_DUMP_SHADERS", FALSE);
28
29 /* These cap sets are much more correct than the ones in u_caps.c */
30 /* TODO: it seems cube levels should be the same as 2D levels */
31
32 /* DX 9_1 */
33 static unsigned caps_dx_9_1[] = {
34 UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
35 UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */
36 UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 8), /* 256 */
37 UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
38 UTIL_CHECK_TERMINATE
39 };
40
41 /* DX 9_2 */
42 static unsigned caps_dx_9_2[] = {
43 UTIL_CHECK_CAP(OCCLUSION_QUERY),
44 UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
45 UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
46 UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
47 UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
48 UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */
49 UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
50 UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
51 UTIL_CHECK_TERMINATE
52 };
53
54 /* DX 9_3 */
55 static unsigned caps_dx_9_3[] = {
56 UTIL_CHECK_CAP(OCCLUSION_QUERY),
57 UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
58 UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
59 UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
60 UTIL_CHECK_CAP(SM3),
61 UTIL_CHECK_CAP(VERTEX_ELEMENT_INSTANCE_DIVISOR),
62 UTIL_CHECK_CAP(OCCLUSION_QUERY),
63 UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4),
64 UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13), /* 4096 */
65 UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
66 UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
67 UTIL_CHECK_TERMINATE
68 };
69
70 static unsigned caps_dx_10_0[] = {
71 UTIL_CHECK_CAP(INDEP_BLEND_ENABLE),
72 UTIL_CHECK_CAP(ANISOTROPIC_FILTER),
73 UTIL_CHECK_CAP(MIXED_COLORBUFFER_FORMATS),
74 UTIL_CHECK_CAP(FRAGMENT_COLOR_CLAMP_CONTROL),
75 UTIL_CHECK_CAP(CONDITIONAL_RENDER),
76 UTIL_CHECK_CAP(PRIMITIVE_RESTART),
77 UTIL_CHECK_CAP(TGSI_INSTANCEID),
78 UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
79 UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13),
80 UTIL_CHECK_INT(MAX_TEXTURE_ARRAY_LAYERS, 512),
81 UTIL_CHECK_INT(MAX_STREAM_OUTPUT_BUFFERS, 4),
82 UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16),
83 UTIL_CHECK_SHADER(GEOMETRY, MAX_CONST_BUFFERS, 14),
84 UTIL_CHECK_SHADER(GEOMETRY, MAX_TEXTURE_SAMPLERS, 16),
85 UTIL_CHECK_SHADER(GEOMETRY, SUBROUTINES, 1),
86 UTIL_CHECK_SHADER(FRAGMENT, INTEGERS, 1),
87 UTIL_CHECK_TERMINATE
88 };
89
90
91 // this is called "screen" because in the D3D10 case it's only part of the device
92 template<bool threadsafe>
93 struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
94 {
95 D3D_FEATURE_LEVEL feature_level;
96 int format_support[PIPE_FORMAT_COUNT];
97 unsigned creation_flags;
98 unsigned exception_mode;
99 maybe_mutex_t<threadsafe> mutex;
100
101 /* TODO: Direct3D 11 specifies that fine-grained locking should be used if the driver supports it.
102 * Right now, I don't trust Gallium drivers to get this right.
103 */
104 #define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(mutex)
105
106 GalliumD3D11ScreenImpl(struct pipe_screen* screen, struct pipe_context* immediate_pipe, BOOL owns_immediate_pipe,unsigned creation_flags, IDXGIAdapter* adapter)
107 : GalliumD3D11Screen(screen, immediate_pipe, adapter), creation_flags(creation_flags)
108 {
109 memset(&screen_caps, 0, sizeof(screen_caps));
110 screen_caps.gs = screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
111 screen_caps.so = screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) > 0;
112 screen_caps.queries = screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY);
113 screen_caps.render_condition = screen->get_param(screen, PIPE_CAP_CONDITIONAL_RENDER);
114 for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
115 screen_caps.constant_buffers[i] = screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
116 screen_caps.stages = 0;
117 for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
118 {
119 if(!screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
120 break;
121 screen_caps.stages = i + 1;
122 }
123
124 screen_caps.stages_with_sampling = (1 << screen_caps.stages) - 1;
125 if(!screen->get_shader_param(screen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS))
126 screen_caps.stages_with_sampling &=~ (1 << PIPE_SHADER_VERTEX);
127
128 memset(format_support, 0xff, sizeof(format_support));
129
130 float default_level = 9.1f;
131 if(!util_check_caps(screen, caps_dx_9_1))
132 _debug_printf("Warning: driver does not even meet D3D_FEATURE_LEVEL_9_1 features, advertising it anyway!\n");
133 else if(!util_check_caps(screen, caps_dx_9_2))
134 default_level = 9.1f;
135 else if(!util_check_caps(screen, caps_dx_9_3))
136 default_level = 9.2f;
137 else if(!util_check_caps(screen, caps_dx_10_0))
138 default_level = 9.3f;
139 else
140 default_level = 10.0f;
141
142 char default_level_name[64];
143 sprintf(default_level_name, "%.1f", default_level);
144 float feature_level_number = atof(debug_get_option("D3D11_FEATURE_LEVEL", default_level_name));
145 if(!feature_level_number)
146 feature_level_number = default_level;
147
148 #if API >= 11
149 if(feature_level_number >= 11.0f)
150 feature_level = D3D_FEATURE_LEVEL_11_0;
151 else
152 #endif
153 if(feature_level_number >= 10.1f)
154 feature_level = D3D_FEATURE_LEVEL_10_1;
155 else if(feature_level_number >= 10.0f)
156 feature_level = D3D_FEATURE_LEVEL_10_0;
157 else if(feature_level_number >= 9.3f)
158 feature_level = D3D_FEATURE_LEVEL_9_3;
159 else if(feature_level_number >= 9.2f)
160 feature_level = D3D_FEATURE_LEVEL_9_2;
161 else
162 feature_level = D3D_FEATURE_LEVEL_9_1;
163
164 #if API >= 11
165 immediate_context = GalliumD3D11ImmediateDeviceContext_Create(this, immediate_pipe, owns_immediate_pipe);
166 // release to the reference to ourselves that the immediate context took, to avoid a garbage cycle
167 immediate_context->Release();
168 #endif
169 }
170
171 ~GalliumD3D11ScreenImpl()
172 {
173 #if API >= 11
174 GalliumD3D11ImmediateDeviceContext_Destroy(immediate_context);
175 #endif
176 }
177
178 virtual D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel(void)
179 {
180 return feature_level;
181 }
182
183 virtual unsigned STDMETHODCALLTYPE GetCreationFlags(void)
184 {
185 return creation_flags;
186 }
187
188 virtual HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(void)
189 {
190 return S_OK;
191 }
192
193 #if API >= 11
194 virtual void STDMETHODCALLTYPE GetImmediateContext(
195 ID3D11DeviceContext **out_immediate_context)
196 {
197 immediate_context->AddRef();
198 *out_immediate_context = immediate_context;
199 }
200 #endif
201
202 virtual HRESULT STDMETHODCALLTYPE SetExceptionMode(unsigned RaiseFlags)
203 {
204 exception_mode = RaiseFlags;
205 return S_OK;
206 }
207
208 virtual unsigned STDMETHODCALLTYPE GetExceptionMode(void)
209 {
210 return exception_mode;
211 }
212
213 virtual HRESULT STDMETHODCALLTYPE CheckCounter(
214 const D3D11_COUNTER_DESC *desc,
215 D3D11_COUNTER_TYPE *type,
216 unsigned *active_counters,
217 LPSTR sz_name,
218 unsigned *name_length,
219 LPSTR sz_units,
220 unsigned *units_length,
221 LPSTR sz_description,
222 unsigned *description_length)
223 {
224 return E_NOTIMPL;
225 }
226
227 virtual void STDMETHODCALLTYPE CheckCounterInfo(
228 D3D11_COUNTER_INFO *counter_info)
229 {
230 /* none supported at the moment */
231 counter_info->LastDeviceDependentCounter = (D3D11_COUNTER)0;
232 counter_info->NumDetectableParallelUnits = 1;
233 counter_info->NumSimultaneousCounters = 0;
234 }
235
236 #if API >= 11
237 virtual HRESULT STDMETHODCALLTYPE CheckFeatureSupport(
238 D3D11_FEATURE feature,
239 void *out_feature_support_data,
240 unsigned feature_support_data_size)
241 {
242 SYNCHRONIZED;
243
244 switch(feature)
245 {
246 case D3D11_FEATURE_THREADING:
247 {
248 D3D11_FEATURE_DATA_THREADING* data = (D3D11_FEATURE_DATA_THREADING*)out_feature_support_data;
249 if(feature_support_data_size != sizeof(*data))
250 return E_INVALIDARG;
251
252 data->DriverCommandLists = FALSE;
253 data->DriverConcurrentCreates = FALSE;
254 return S_OK;
255 }
256 case D3D11_FEATURE_DOUBLES:
257 {
258 D3D11_FEATURE_DATA_DOUBLES* data = (D3D11_FEATURE_DATA_DOUBLES*)out_feature_support_data;
259 if(feature_support_data_size != sizeof(*data))
260 return E_INVALIDARG;
261
262 data->DoublePrecisionFloatShaderOps = FALSE;
263 return S_OK;
264 }
265 case D3D11_FEATURE_FORMAT_SUPPORT:
266 {
267 D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)out_feature_support_data;
268 if(feature_support_data_size != sizeof(*data))
269 return E_INVALIDARG;
270
271 return this->CheckFormatSupport(data->InFormat, &data->OutFormatSupport);
272 }
273 case D3D11_FEATURE_FORMAT_SUPPORT2:
274 {
275 D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)out_feature_support_data;
276 if(feature_support_data_size != sizeof(*data))
277 return E_INVALIDARG;
278
279 data->OutFormatSupport = 0;
280 /* TODO: should this be S_OK? */
281 return E_INVALIDARG;
282 }
283 case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS:
284 {
285 D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS* data = (D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS*)out_feature_support_data;
286 if(feature_support_data_size != sizeof(*data))
287 return E_INVALIDARG;
288
289 data->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = FALSE;
290 return S_OK;
291 }
292 default:
293 return E_INVALIDARG;
294 }
295 }
296 #endif
297
298 virtual HRESULT STDMETHODCALLTYPE CheckFormatSupport(
299 DXGI_FORMAT dxgi_format,
300 unsigned *out_format_support
301 )
302 {
303 SYNCHRONIZED;
304
305 /* TODO: MSAA, advanced features */
306
307 pipe_format format = dxgi_to_pipe_format[dxgi_format];
308 if(!format)
309 return E_INVALIDARG;
310
311 int support = format_support[format];
312 if(support < 0)
313 {
314 support = 0;
315
316 if(dxgi_format == DXGI_FORMAT_R8_UINT ||
317 dxgi_format == DXGI_FORMAT_R16_UINT ||
318 dxgi_format == DXGI_FORMAT_R32_UINT)
319 support |= D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER;
320
321 if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER))
322 support |= D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER;
323
324 if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_STREAM_OUTPUT))
325 support |= D3D11_FORMAT_SUPPORT_SO_BUFFER;
326
327 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_1D, 0, PIPE_BIND_SAMPLER_VIEW))
328 support |= D3D11_FORMAT_SUPPORT_TEXTURE1D;
329 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW))
330 support |= D3D11_FORMAT_SUPPORT_TEXTURE2D;
331 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_CUBE, 0, PIPE_BIND_SAMPLER_VIEW))
332 support |= D3D11_FORMAT_SUPPORT_TEXTURECUBE;
333 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_3D, 0, PIPE_BIND_SAMPLER_VIEW))
334 support |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
335
336 if(support & (D3D11_FORMAT_SUPPORT_TEXTURE1D | D3D11_FORMAT_SUPPORT_TEXTURE2D |
337 D3D11_FORMAT_SUPPORT_TEXTURE3D | D3D11_FORMAT_SUPPORT_TEXTURECUBE))
338 {
339 support |=
340 D3D11_FORMAT_SUPPORT_SHADER_LOAD |
341 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE |
342 D3D11_FORMAT_SUPPORT_MIP |
343 D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
344 if(util_format_is_depth_or_stencil(format))
345 support |= D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON;
346 }
347
348 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET | PIPE_BIND_BLENDABLE))
349 support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_BLENDABLE;
350 else
351 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET))
352 support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET;
353 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL))
354 support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DEPTH_STENCIL;
355 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DISPLAY_TARGET))
356 support |= D3D11_FORMAT_SUPPORT_DISPLAY;
357
358 unsigned ms;
359 for(ms = 2; ms <= 8; ++ms)
360 {
361 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, ms, PIPE_BIND_RENDER_TARGET))
362 {
363 support |= D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE;
364 break;
365 }
366 }
367 if(ms <= 8 && screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, ms, PIPE_BIND_SAMPLER_VIEW))
368 support |= D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD;
369
370 format_support[format] = support;
371 }
372 *out_format_support = support;
373 return S_OK;
374 }
375
376 virtual HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels(
377 DXGI_FORMAT format,
378 unsigned sample_count,
379 unsigned *pcount
380 )
381 {
382 SYNCHRONIZED;
383
384 if(sample_count == 1)
385 *pcount = 1;
386 else
387 *pcount = 0;
388 return S_OK;
389 }
390
391 template<typename T, typename U>
392 bool convert_blend_state(T& to, const U& from, unsigned BlendEnable, unsigned RenderTargetWriteMask)
393 {
394 if(unlikely(BlendEnable &&
395 (from.SrcBlend >= D3D11_BLEND_COUNT ||
396 from.SrcBlendAlpha >= D3D11_BLEND_COUNT ||
397 from.DestBlend >= D3D11_BLEND_COUNT ||
398 from.DestBlendAlpha >= D3D11_BLEND_COUNT ||
399 from.BlendOp >= 6 ||
400 from.BlendOp == 0 ||
401 from.BlendOpAlpha >= 6 ||
402 from.BlendOpAlpha == 0)))
403 return false;
404
405 to.blend_enable = BlendEnable;
406
407 if(BlendEnable)
408 {
409 to.rgb_func = from.BlendOp - 1;
410 to.alpha_func = from.BlendOpAlpha - 1;
411
412 to.rgb_src_factor = d3d11_to_pipe_blend[from.SrcBlend];
413 to.alpha_src_factor = d3d11_to_pipe_blend[from.SrcBlendAlpha];
414 to.rgb_dst_factor = d3d11_to_pipe_blend[from.DestBlend];
415 to.alpha_dst_factor = d3d11_to_pipe_blend[from.DestBlendAlpha];
416 }
417
418 to.colormask = RenderTargetWriteMask & 0xf;
419 return true;
420 }
421
422 #if API >= 11
423 virtual HRESULT STDMETHODCALLTYPE CreateBlendState(
424 const D3D11_BLEND_DESC *blend_state_desc,
425 ID3D11BlendState **out_blend_state
426 )
427 #else
428 virtual HRESULT STDMETHODCALLTYPE CreateBlendState1(
429 const D3D10_BLEND_DESC1 *blend_state_desc,
430 ID3D10BlendState1 **out_blend_state
431 )
432 #endif
433 {
434 SYNCHRONIZED;
435
436 pipe_blend_state state;
437 memset(&state, 0, sizeof(state));
438 state.alpha_to_coverage = !!blend_state_desc->AlphaToCoverageEnable;
439 state.independent_blend_enable = !!blend_state_desc->IndependentBlendEnable;
440
441 assert(PIPE_MAX_COLOR_BUFS >= 8);
442 const unsigned n = blend_state_desc->IndependentBlendEnable ? 8 : 1;
443 for(unsigned i = 0; i < n; ++i)
444 {
445 if(!convert_blend_state(
446 state.rt[i],
447 blend_state_desc->RenderTarget[i],
448 blend_state_desc->RenderTarget[i].BlendEnable,
449 blend_state_desc->RenderTarget[i].RenderTargetWriteMask))
450 return E_INVALIDARG;
451 }
452
453 if(!out_blend_state)
454 return S_FALSE;
455
456 void* object = immediate_pipe->create_blend_state(immediate_pipe, &state);
457 if(!object)
458 return E_FAIL;
459
460 *out_blend_state = new GalliumD3D11BlendState(this, object, *blend_state_desc);
461 return S_OK;
462 }
463
464 #if API < 11
465 virtual HRESULT STDMETHODCALLTYPE CreateBlendState(
466 const D3D10_BLEND_DESC *blend_state_desc,
467 ID3D10BlendState **out_blend_state
468 )
469 {
470 SYNCHRONIZED;
471
472 pipe_blend_state state;
473 memset(&state, 0, sizeof(state));
474 state.alpha_to_coverage = !!blend_state_desc->AlphaToCoverageEnable;
475 assert(PIPE_MAX_COLOR_BUFS >= 8);
476 for(unsigned i = 0; i < 8; ++i)
477 {
478 if(!convert_blend_state(
479 state.rt[i],
480 *blend_state_desc,
481 blend_state_desc->BlendEnable[i],
482 blend_state_desc->RenderTargetWriteMask[i]))
483 return E_INVALIDARG;
484 }
485
486 for(unsigned i = 1; i < 8; ++i)
487 {
488 if(memcmp(&state.rt[0], &state.rt[i], sizeof(state.rt[0])))
489 {
490 state.independent_blend_enable = TRUE;
491 break;
492 }
493 }
494
495 void* object = immediate_pipe->create_blend_state(immediate_pipe, &state);
496 if(!object)
497 return E_FAIL;
498
499 *out_blend_state = new GalliumD3D11BlendState(this, object, *blend_state_desc);
500 return S_OK;
501 }
502 #endif
503
504 virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilState(
505 const D3D11_DEPTH_STENCIL_DESC *depth_stencil_state_desc,
506 ID3D11DepthStencilState **depth_stencil_state
507 )
508 {
509 SYNCHRONIZED;
510
511 pipe_depth_stencil_alpha_state state;
512 memset(&state, 0, sizeof(state));
513
514 state.depth.enabled = !!depth_stencil_state_desc->DepthEnable;
515 if(depth_stencil_state_desc->DepthEnable)
516 {
517 if(depth_stencil_state_desc->DepthFunc == 0 ||
518 depth_stencil_state_desc->DepthFunc >= 9)
519 return E_INVALIDARG;
520 state.depth.writemask = depth_stencil_state_desc->DepthWriteMask;
521 state.depth.func = depth_stencil_state_desc->DepthFunc - 1;
522 }
523
524 state.stencil[0].enabled = !!depth_stencil_state_desc->StencilEnable;
525 if(depth_stencil_state_desc->StencilEnable)
526 {
527 if(depth_stencil_state_desc->FrontFace.StencilPassOp >= D3D11_STENCIL_OP_COUNT ||
528 depth_stencil_state_desc->FrontFace.StencilFailOp >= D3D11_STENCIL_OP_COUNT ||
529 depth_stencil_state_desc->FrontFace.StencilDepthFailOp >= D3D11_STENCIL_OP_COUNT ||
530 depth_stencil_state_desc->BackFace.StencilPassOp >= D3D11_STENCIL_OP_COUNT ||
531 depth_stencil_state_desc->BackFace.StencilFailOp >= D3D11_STENCIL_OP_COUNT ||
532 depth_stencil_state_desc->BackFace.StencilDepthFailOp >= D3D11_STENCIL_OP_COUNT)
533 return E_INVALIDARG;
534 state.stencil[0].writemask = depth_stencil_state_desc->StencilWriteMask;
535 state.stencil[0].valuemask = depth_stencil_state_desc->StencilReadMask;
536 state.stencil[0].zpass_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->FrontFace.StencilPassOp];
537 state.stencil[0].fail_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->FrontFace.StencilFailOp];
538 state.stencil[0].zfail_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->FrontFace.StencilDepthFailOp];
539 state.stencil[0].func = depth_stencil_state_desc->FrontFace.StencilFunc - 1;
540 state.stencil[1].enabled = !!depth_stencil_state_desc->StencilEnable;
541 state.stencil[1].writemask = depth_stencil_state_desc->StencilWriteMask;
542 state.stencil[1].valuemask = depth_stencil_state_desc->StencilReadMask;
543 state.stencil[1].zpass_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->BackFace.StencilPassOp];
544 state.stencil[1].fail_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->BackFace.StencilFailOp];
545 state.stencil[1].zfail_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->BackFace.StencilDepthFailOp];
546 state.stencil[1].func = depth_stencil_state_desc->BackFace.StencilFunc - 1;
547 }
548
549 if(!depth_stencil_state)
550 return S_FALSE;
551
552 void* object = immediate_pipe->create_depth_stencil_alpha_state(immediate_pipe, &state);
553 if(!object)
554 return E_FAIL;
555
556 *depth_stencil_state = new GalliumD3D11DepthStencilState(this, object, *depth_stencil_state_desc);
557 return S_OK;
558 }
559
560 virtual HRESULT STDMETHODCALLTYPE CreateRasterizerState(
561 const D3D11_RASTERIZER_DESC *rasterizer_desc,
562 ID3D11RasterizerState **out_rasterizer_state)
563 {
564 SYNCHRONIZED;
565
566 pipe_rasterizer_state state;
567 memset(&state, 0, sizeof(state));
568 state.gl_rasterization_rules = 1; /* D3D10/11 use GL rules */
569 state.fill_front = state.fill_back = (rasterizer_desc->FillMode == D3D11_FILL_WIREFRAME) ? PIPE_POLYGON_MODE_LINE : PIPE_POLYGON_MODE_FILL;
570 if(rasterizer_desc->CullMode == D3D11_CULL_FRONT)
571 state.cull_face = PIPE_FACE_FRONT;
572 else if(rasterizer_desc->CullMode == D3D11_CULL_BACK)
573 state.cull_face = PIPE_FACE_BACK;
574 else
575 state.cull_face = PIPE_FACE_NONE;
576 state.front_ccw = !!rasterizer_desc->FrontCounterClockwise;
577 state.offset_tri = state.offset_line = state.offset_point = rasterizer_desc->SlopeScaledDepthBias || rasterizer_desc->DepthBias;
578 state.offset_scale = rasterizer_desc->SlopeScaledDepthBias;
579 state.offset_units = rasterizer_desc->DepthBias;
580 state.offset_clamp = rasterizer_desc->DepthBiasClamp;
581 state.depth_clip = rasterizer_desc->DepthClipEnable;
582 state.scissor = !!rasterizer_desc->ScissorEnable;
583 state.multisample = !!rasterizer_desc->MultisampleEnable;
584 state.line_smooth = !!rasterizer_desc->AntialiasedLineEnable;
585 state.flatshade_first = 1;
586 state.line_width = 1.0f;
587 state.point_size = 1.0f;
588
589 /* TODO: is this correct? */
590 state.point_quad_rasterization = 1;
591
592 if(!out_rasterizer_state)
593 return S_FALSE;
594
595 void* object = immediate_pipe->create_rasterizer_state(immediate_pipe, &state);
596 if(!object)
597 return E_FAIL;
598
599 *out_rasterizer_state = new GalliumD3D11RasterizerState(this, object, *rasterizer_desc);
600 return S_OK;
601 }
602
603 virtual HRESULT STDMETHODCALLTYPE CreateSamplerState(
604 const D3D11_SAMPLER_DESC *sampler_desc,
605 ID3D11SamplerState **out_sampler_state)
606 {
607 SYNCHRONIZED;
608
609 pipe_sampler_state state;
610 memset(&state, 0, sizeof(state));
611 state.normalized_coords = 1;
612 state.min_mip_filter = (sampler_desc->Filter & 1);
613 state.mag_img_filter = ((sampler_desc->Filter >> 2) & 1);
614 state.min_img_filter = ((sampler_desc->Filter >> 4) & 1);
615 if(sampler_desc->Filter & 0x40)
616 state.max_anisotropy = sampler_desc->MaxAnisotropy;
617 if(sampler_desc->Filter & 0x80)
618 {
619 state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
620 state.compare_func = sampler_desc->ComparisonFunc - 1;
621 }
622 state.wrap_s = d3d11_to_pipe_wrap[sampler_desc->AddressU];
623 state.wrap_t = d3d11_to_pipe_wrap[sampler_desc->AddressV];
624 state.wrap_r = d3d11_to_pipe_wrap[sampler_desc->AddressW];
625 state.lod_bias = sampler_desc->MipLODBias;
626 memcpy(state.border_color.f, sampler_desc->BorderColor, sizeof(state.border_color));
627 state.min_lod = sampler_desc->MinLOD;
628 state.max_lod = sampler_desc->MaxLOD;
629
630 if(!out_sampler_state)
631 return S_FALSE;
632
633 void* object = immediate_pipe->create_sampler_state(immediate_pipe, &state);
634 if(!object)
635 return E_FAIL;
636
637 *out_sampler_state = new GalliumD3D11SamplerState(this, object, *sampler_desc);
638 return S_OK;
639 }
640
641 virtual HRESULT STDMETHODCALLTYPE CreateInputLayout(
642 const D3D11_INPUT_ELEMENT_DESC *input_element_descs,
643 unsigned count,
644 const void *shader_bytecode_with_input_signature,
645 SIZE_T bytecode_length,
646 ID3D11InputLayout **out_input_layout)
647 {
648 SYNCHRONIZED;
649
650 if(count > D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT)
651 return E_INVALIDARG;
652 assert(D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT <= PIPE_MAX_ATTRIBS);
653
654 // putting semantics matching in the core API seems to be a (minor) design mistake
655
656 struct dxbc_chunk_signature* sig = dxbc_find_signature(shader_bytecode_with_input_signature, bytecode_length, DXBC_FIND_INPUT_SIGNATURE);
657 D3D11_SIGNATURE_PARAMETER_DESC* params;
658 unsigned num_params = dxbc_parse_signature(sig, &params);
659
660 typedef std::unordered_map<std::pair<c_string, unsigned>, unsigned> semantic_to_idx_map_t;
661 semantic_to_idx_map_t semantic_to_idx_map;
662 for(unsigned i = 0; i < count; ++i)
663 semantic_to_idx_map[std::make_pair(c_string(input_element_descs[i].SemanticName), input_element_descs[i].SemanticIndex)] = i;
664
665 struct pipe_vertex_element elements[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
666
667 enum pipe_format formats[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
668 unsigned offsets[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
669
670 offsets[0] = 0;
671 for(unsigned i = 0; i < count; ++i)
672 {
673 formats[i] = dxgi_to_pipe_format[input_element_descs[i].Format];
674
675 if(likely(input_element_descs[i].AlignedByteOffset != D3D11_APPEND_ALIGNED_ELEMENT))
676 {
677 offsets[i] = input_element_descs[i].AlignedByteOffset;
678 }
679 else if(i > 0)
680 {
681 unsigned align_mask = util_format_description(formats[i])->channel[0].size;
682 if(align_mask & 7) // e.g. R10G10B10A2
683 align_mask = 32;
684 align_mask = (align_mask / 8) - 1;
685
686 offsets[i] = (offsets[i - 1] + util_format_get_blocksize(formats[i - 1]) + align_mask) & ~align_mask;
687 }
688 }
689
690 // TODO: check for & report errors (e.g. ambiguous layouts, unmatched semantics)
691
692 unsigned num_params_to_use = 0;
693 for(unsigned i = 0; i < num_params && num_params_to_use < D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT; ++i)
694 {
695 if(!strcasecmp(params[i].SemanticName, "SV_INSTANCEID") ||
696 !strcasecmp(params[i].SemanticName, "SV_VERTEXID"))
697 continue;
698 const unsigned n = num_params_to_use++;
699
700 semantic_to_idx_map_t::iterator iter = semantic_to_idx_map.find(std::make_pair(c_string(params[i].SemanticName), params[i].SemanticIndex));
701
702 if(iter != semantic_to_idx_map.end())
703 {
704 unsigned idx = iter->second;
705
706 elements[n].src_format = formats[idx];
707 elements[n].src_offset = offsets[idx];
708 elements[n].vertex_buffer_index = input_element_descs[idx].InputSlot;
709 elements[n].instance_divisor = input_element_descs[idx].InstanceDataStepRate;
710 if (input_element_descs[idx].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA)
711 if (elements[n].instance_divisor == 0)
712 elements[n].instance_divisor = ~0; // XXX: can't specify 'never' to gallium
713 }
714 else
715 {
716 // XXX: undefined input, is this valid or should we return an error ?
717 elements[n].src_format = PIPE_FORMAT_NONE;
718 elements[n].src_offset = 0;
719 elements[n].vertex_buffer_index = 0;
720 elements[n].instance_divisor = 0;
721 }
722 }
723
724 free(params);
725
726 if(!out_input_layout)
727 return S_FALSE;
728
729 void* object = immediate_pipe->create_vertex_elements_state(immediate_pipe, num_params_to_use, elements);
730 if(!object)
731 return E_FAIL;
732
733 *out_input_layout = new GalliumD3D11InputLayout(this, object);
734 return S_OK;
735 }
736
737 static unsigned d3d11_to_pipe_bind_flags(unsigned bind_flags)
738 {
739 unsigned bind = 0;
740 if(bind_flags & D3D11_BIND_VERTEX_BUFFER)
741 bind |= PIPE_BIND_VERTEX_BUFFER;
742 if(bind_flags & D3D11_BIND_INDEX_BUFFER)
743 bind |= PIPE_BIND_INDEX_BUFFER;
744 if(bind_flags & D3D11_BIND_CONSTANT_BUFFER)
745 bind |= PIPE_BIND_CONSTANT_BUFFER;
746 if(bind_flags & D3D11_BIND_SHADER_RESOURCE)
747 bind |= PIPE_BIND_SAMPLER_VIEW;
748 if(bind_flags & D3D11_BIND_STREAM_OUTPUT)
749 bind |= PIPE_BIND_STREAM_OUTPUT;
750 if(bind_flags & D3D11_BIND_RENDER_TARGET)
751 bind |= PIPE_BIND_RENDER_TARGET;
752 if(bind_flags & D3D11_BIND_DEPTH_STENCIL)
753 bind |= PIPE_BIND_DEPTH_STENCIL;
754 return bind;
755 }
756
757 inline HRESULT create_resource(
758 pipe_texture_target target,
759 unsigned width,
760 unsigned height,
761 unsigned depth,
762 unsigned mip_levels,
763 unsigned array_size,
764 DXGI_FORMAT format,
765 const DXGI_SAMPLE_DESC* SampleDesc,
766 D3D11_USAGE usage,
767 unsigned bind_flags,
768 unsigned c_p_u_access_flags,
769 unsigned misc_flags,
770 const D3D11_SUBRESOURCE_DATA *initial_data,
771 DXGI_USAGE dxgi_usage,
772 struct pipe_resource** ppresource
773 )
774 {
775 if(invalid(format >= DXGI_FORMAT_COUNT))
776 return E_INVALIDARG;
777 if(misc_flags & D3D11_RESOURCE_MISC_TEXTURECUBE)
778 {
779 if(target != PIPE_TEXTURE_2D)
780 return E_INVALIDARG;
781 target = PIPE_TEXTURE_CUBE;
782 if(array_size % 6)
783 return E_INVALIDARG;
784 }
785 else if(array_size > 1)
786 {
787 switch (target) {
788 case PIPE_TEXTURE_1D: target = PIPE_TEXTURE_1D_ARRAY; break;
789 case PIPE_TEXTURE_2D: target = PIPE_TEXTURE_2D_ARRAY; break;
790 default:
791 return E_INVALIDARG;
792 }
793 }
794 /* TODO: msaa */
795 struct pipe_resource templat;
796 memset(&templat, 0, sizeof(templat));
797 templat.target = target;
798 templat.width0 = width;
799 templat.height0 = height;
800 templat.depth0 = depth;
801 templat.array_size = array_size;
802 if(mip_levels)
803 templat.last_level = mip_levels - 1;
804 else
805 templat.last_level = MAX2(MAX2(util_logbase2(templat.width0), util_logbase2(templat.height0)), util_logbase2(templat.depth0));
806 templat.format = dxgi_to_pipe_format[format];
807 if(bind_flags & D3D11_BIND_DEPTH_STENCIL) {
808 // colour formats are not depth-renderable, but depth/stencil-formats may be colour-renderable
809 switch(format)
810 {
811 case DXGI_FORMAT_R32_TYPELESS: templat.format = PIPE_FORMAT_Z32_FLOAT; break;
812 case DXGI_FORMAT_R16_TYPELESS: templat.format = PIPE_FORMAT_Z16_UNORM; break;
813 default:
814 break;
815 }
816 }
817 templat.bind = d3d11_to_pipe_bind_flags(bind_flags);
818 if(c_p_u_access_flags & D3D11_CPU_ACCESS_READ)
819 templat.bind |= PIPE_BIND_TRANSFER_READ;
820 if(c_p_u_access_flags & D3D11_CPU_ACCESS_WRITE)
821 templat.bind |= PIPE_BIND_TRANSFER_WRITE;
822 if(misc_flags & D3D11_RESOURCE_MISC_SHARED)
823 templat.bind |= PIPE_BIND_SHARED;
824 if(misc_flags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE)
825 templat.bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE;
826 if(dxgi_usage & DXGI_USAGE_BACK_BUFFER)
827 templat.bind |= PIPE_BIND_DISPLAY_TARGET;
828 templat.usage = d3d11_to_pipe_usage[usage];
829 if(invalid(!templat.format))
830 return E_NOTIMPL;
831
832 if(!ppresource)
833 return S_FALSE;
834
835 struct pipe_resource* resource = screen->resource_create(screen, &templat);
836 if(!resource)
837 return E_FAIL;
838 if(initial_data)
839 {
840 for(unsigned slice = 0; slice < array_size; ++slice)
841 {
842 for(unsigned level = 0; level <= templat.last_level; ++level)
843 {
844 struct pipe_box box;
845 box.x = box.y = 0;
846 box.z = slice;
847 box.width = u_minify(width, level);
848 box.height = u_minify(height, level);
849 box.depth = u_minify(depth, level);
850 immediate_pipe->transfer_inline_write(immediate_pipe, resource, level, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_UNSYNCHRONIZED, &box, initial_data->pSysMem, initial_data->SysMemPitch, initial_data->SysMemSlicePitch);
851 ++initial_data;
852 }
853 }
854 }
855 *ppresource = resource;
856 return S_OK;
857 }
858
859 static unsigned d3d_to_dxgi_usage(unsigned bind, unsigned misc)
860 {
861 unsigned dxgi_usage = 0;
862 if(bind |= D3D11_BIND_RENDER_TARGET)
863 dxgi_usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
864 if(bind & D3D11_BIND_SHADER_RESOURCE)
865 dxgi_usage |= DXGI_USAGE_SHADER_INPUT;
866 #if API >= 11
867 if(bind & D3D11_BIND_UNORDERED_ACCESS)
868 dxgi_usage |= DXGI_USAGE_UNORDERED_ACCESS;
869 #endif
870 if(misc & D3D11_RESOURCE_MISC_SHARED)
871 dxgi_usage |= DXGI_USAGE_SHARED;
872 return dxgi_usage;
873 }
874
875 virtual HRESULT STDMETHODCALLTYPE CreateTexture1D(
876 const D3D11_TEXTURE1D_DESC *desc,
877 const D3D11_SUBRESOURCE_DATA *initial_data,
878 ID3D11Texture1D **out_texture1d)
879 {
880 SYNCHRONIZED;
881
882 struct pipe_resource* resource;
883 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
884 HRESULT hr = create_resource(PIPE_TEXTURE_1D, desc->Width, 1, 1, desc->MipLevels, desc->ArraySize, desc->Format, 0, desc->Usage, desc->BindFlags, desc->CPUAccessFlags, desc->MiscFlags, initial_data, dxgi_usage, out_texture1d ? &resource : 0);
885 if(hr != S_OK)
886 return hr;
887 D3D11_TEXTURE1D_DESC cdesc = *desc;
888 cdesc.MipLevels = resource->last_level + 1;
889 *out_texture1d = new GalliumD3D11Texture1D(this, resource, cdesc, dxgi_usage);
890 return S_OK;
891 }
892
893 virtual HRESULT STDMETHODCALLTYPE CreateTexture2D(
894 const D3D11_TEXTURE2D_DESC *desc,
895 const D3D11_SUBRESOURCE_DATA *initial_data,
896 ID3D11Texture2D **out_texture2d)
897 {
898 SYNCHRONIZED;
899
900 struct pipe_resource* resource;
901 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
902 HRESULT hr = create_resource(PIPE_TEXTURE_2D, desc->Width, desc->Height, 1, desc->MipLevels, desc->ArraySize, desc->Format, &desc->SampleDesc, desc->Usage, desc->BindFlags, desc->CPUAccessFlags, desc->MiscFlags, initial_data, dxgi_usage, out_texture2d ? &resource : 0);
903 if(hr != S_OK)
904 return hr;
905 D3D11_TEXTURE2D_DESC cdesc = *desc;
906 cdesc.MipLevels = resource->last_level + 1;
907 if(cdesc.MipLevels == 1 && cdesc.ArraySize == 1)
908 *out_texture2d = new GalliumD3D11Surface(this, resource, cdesc, dxgi_usage);
909 else
910 *out_texture2d = new GalliumD3D11Texture2D(this, resource, cdesc, dxgi_usage);
911 return S_OK;
912 }
913
914 virtual HRESULT STDMETHODCALLTYPE CreateTexture3D(
915 const D3D11_TEXTURE3D_DESC *desc,
916 const D3D11_SUBRESOURCE_DATA *initial_data,
917 ID3D11Texture3D **out_texture3d)
918 {
919 SYNCHRONIZED;
920
921 struct pipe_resource* resource;
922 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
923 HRESULT hr = create_resource(PIPE_TEXTURE_3D, desc->Width, desc->Height, desc->Depth, desc->MipLevels, 1, desc->Format, 0, desc->Usage, desc->BindFlags, desc->CPUAccessFlags, desc->MiscFlags, initial_data, dxgi_usage, out_texture3d ? &resource : 0);
924 if(hr != S_OK)
925 return hr;
926 D3D11_TEXTURE3D_DESC cdesc = *desc;
927 cdesc.MipLevels = resource->last_level + 1;
928 *out_texture3d = new GalliumD3D11Texture3D(this, resource, cdesc, dxgi_usage);
929 return S_OK;
930 }
931
932 virtual HRESULT STDMETHODCALLTYPE CreateBuffer(
933 const D3D11_BUFFER_DESC *desc,
934 const D3D11_SUBRESOURCE_DATA *initial_data,
935 ID3D11Buffer **out_buffer)
936 {
937 SYNCHRONIZED;
938
939 struct pipe_resource* resource;
940 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
941 HRESULT hr = create_resource(PIPE_BUFFER, desc->ByteWidth, 1, 1, 1, 1, DXGI_FORMAT_R8_UNORM, 0, desc->Usage, desc->BindFlags, desc->CPUAccessFlags, desc->MiscFlags, initial_data, dxgi_usage, out_buffer ? &resource : 0);
942 if(hr != S_OK)
943 return hr;
944 *out_buffer = new GalliumD3D11Buffer(this, resource, *desc, dxgi_usage);
945 return S_OK;
946 }
947
948 virtual HRESULT STDMETHODCALLTYPE OpenGalliumResource(
949 struct pipe_resource* resource,
950 IUnknown** dxgi_resource)
951 {
952 SYNCHRONIZED;
953
954 /* TODO: maybe support others */
955 assert(resource->target == PIPE_TEXTURE_2D);
956 *dxgi_resource = 0;
957 D3D11_TEXTURE2D_DESC desc;
958 memset(&desc, 0, sizeof(desc));
959 desc.Width = resource->width0;
960 desc.Height = resource->height0;
961 init_pipe_to_dxgi_format();
962 desc.Format = pipe_to_dxgi_format[resource->format];
963 desc.SampleDesc.Count = resource->nr_samples;
964 desc.SampleDesc.Quality = 0;
965 desc.ArraySize = 1;
966 desc.MipLevels = resource->last_level + 1;
967 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
968 if(resource->bind & PIPE_BIND_RENDER_TARGET)
969 desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
970 if(resource->bind & PIPE_BIND_DEPTH_STENCIL)
971 desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
972 if(resource->bind & PIPE_BIND_SAMPLER_VIEW)
973 desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
974 if(resource->bind & PIPE_BIND_SHARED)
975 desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
976 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc.BindFlags, desc.MiscFlags);
977 if(desc.MipLevels == 1 && desc.ArraySize == 1)
978 *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Surface(this, resource, desc, dxgi_usage);
979 else
980 *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Texture2D(this, resource, desc, dxgi_usage);
981 return S_OK;
982 }
983
984 virtual HRESULT STDMETHODCALLTYPE CreateSurface(
985 const DXGI_SURFACE_DESC *dxgi_desc,
986 unsigned count,
987 DXGI_USAGE usage,
988 const DXGI_SHARED_RESOURCE *shared_resource,
989 IDXGISurface **out_surface)
990 {
991 SYNCHRONIZED;
992
993 D3D11_TEXTURE2D_DESC desc;
994 memset(&desc, 0, sizeof(desc));
995
996 struct pipe_resource* resource;
997 desc.Width = dxgi_desc->Width;
998 desc.Height = dxgi_desc->Height;
999 desc.Format = dxgi_desc->Format;
1000 desc.SampleDesc = dxgi_desc->SampleDesc;
1001 desc.ArraySize = count;
1002 desc.MipLevels = 1;
1003 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
1004 if(usage & DXGI_USAGE_RENDER_TARGET_OUTPUT)
1005 desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
1006 if(usage & DXGI_USAGE_SHADER_INPUT)
1007 desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
1008 #if API >= 11
1009 if(usage & DXGI_USAGE_UNORDERED_ACCESS)
1010 desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
1011 #endif
1012 if(usage & DXGI_USAGE_SHARED)
1013 desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
1014 HRESULT hr = create_resource(PIPE_TEXTURE_2D, dxgi_desc->Width, dxgi_desc->Height, 1, 1, count, dxgi_desc->Format, &dxgi_desc->SampleDesc, D3D11_USAGE_DEFAULT, desc.BindFlags, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE, desc.MiscFlags, 0, usage, &resource);
1015 if(hr != S_OK)
1016 return hr;
1017 *out_surface = new GalliumD3D11Surface(this, resource, desc, usage);
1018 return S_OK;
1019 }
1020
1021 virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView(
1022 ID3D11Resource *iresource,
1023 const D3D11_SHADER_RESOURCE_VIEW_DESC *desc,
1024 ID3D11ShaderResourceView **out_srv)
1025 {
1026 #if API >= 11
1027 D3D11_SHADER_RESOURCE_VIEW_DESC def_desc;
1028 #else
1029 if(desc->ViewDimension == D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY)
1030 return E_INVALIDARG;
1031 D3D10_SHADER_RESOURCE_VIEW_DESC1 desc1;
1032 memset(&desc1, 0, sizeof(desc1));
1033 memcpy(&desc1, desc, sizeof(*desc));
1034 return CreateShaderResourceView1(iresource, &desc1, (ID3D10ShaderResourceView1**)out_srv);
1035 }
1036
1037 virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView1(
1038 ID3D11Resource *iresource,
1039 const D3D10_SHADER_RESOURCE_VIEW_DESC1 *desc,
1040 ID3D10ShaderResourceView1 **out_srv)
1041 {
1042 D3D10_SHADER_RESOURCE_VIEW_DESC1 def_desc;
1043 #endif
1044 SYNCHRONIZED;
1045
1046 const struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource;
1047
1048 if(!desc)
1049 {
1050 init_pipe_to_dxgi_format();
1051 memset(&def_desc, 0, sizeof(def_desc));
1052 def_desc.Format = pipe_to_dxgi_format[resource->format];
1053 switch(resource->target)
1054 {
1055 case PIPE_BUFFER:
1056 def_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
1057 def_desc.Buffer.ElementWidth = resource->width0;
1058 break;
1059 case PIPE_TEXTURE_1D:
1060 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
1061 def_desc.Texture1D.MipLevels = resource->last_level + 1;
1062 break;
1063 case PIPE_TEXTURE_1D_ARRAY:
1064 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
1065 def_desc.Texture1DArray.MipLevels = resource->last_level + 1;
1066 def_desc.Texture1DArray.ArraySize = resource->array_size;
1067 break;
1068 case PIPE_TEXTURE_2D:
1069 case PIPE_TEXTURE_RECT:
1070 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
1071 def_desc.Texture2D.MipLevels = resource->last_level + 1;
1072 break;
1073 case PIPE_TEXTURE_2D_ARRAY:
1074 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1075 def_desc.Texture2DArray.MipLevels = resource->last_level + 1;
1076 def_desc.Texture2DArray.ArraySize = resource->array_size;
1077 break;
1078 case PIPE_TEXTURE_3D:
1079 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
1080 def_desc.Texture3D.MipLevels = resource->last_level + 1;
1081 break;
1082 case PIPE_TEXTURE_CUBE:
1083 if(resource->array_size > 6)
1084 {
1085 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
1086 def_desc.TextureCubeArray.NumCubes = resource->array_size / 6;
1087 }
1088 else
1089 {
1090 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
1091 }
1092 def_desc.TextureCube.MipLevels = resource->last_level + 1;
1093 break;
1094 default:
1095 return E_INVALIDARG;
1096 }
1097 desc = &def_desc;
1098 }
1099
1100 struct pipe_sampler_view templat;
1101 memset(&templat, 0, sizeof(templat));
1102 if(invalid(format >= DXGI_FORMAT_COUNT))
1103 return E_INVALIDARG;
1104 templat.format = (desc->Format == DXGI_FORMAT_UNKNOWN) ? resource->format : dxgi_to_pipe_format[desc->Format];
1105 if(!templat.format)
1106 return E_NOTIMPL;
1107 templat.swizzle_r = PIPE_SWIZZLE_RED;
1108 templat.swizzle_g = PIPE_SWIZZLE_GREEN;
1109 templat.swizzle_b = PIPE_SWIZZLE_BLUE;
1110 templat.swizzle_a = PIPE_SWIZZLE_ALPHA;
1111
1112 templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
1113 switch(desc->ViewDimension)
1114 {
1115 case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
1116 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
1117 case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
1118 templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
1119 templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice + desc->Texture1DArray.ArraySize - 1;
1120 if (desc->ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) {
1121 templat.u.tex.first_layer *= 6;
1122 templat.u.tex.last_layer *= 6;
1123 }
1124 // fall through
1125 case D3D11_SRV_DIMENSION_TEXTURE1D:
1126 case D3D11_SRV_DIMENSION_TEXTURE2D:
1127 case D3D11_SRV_DIMENSION_TEXTURE3D:
1128 case D3D11_SRV_DIMENSION_TEXTURECUBE:
1129 // yes, this works for all of these types
1130 templat.u.tex.first_level = desc->Texture1D.MostDetailedMip;
1131 if(desc->Texture1D.MipLevels == (unsigned)-1)
1132 templat.u.tex.last_level = templat.texture->last_level;
1133 else
1134 templat.u.tex.last_level = templat.u.tex.first_level + desc->Texture1D.MipLevels - 1;
1135 assert(templat.u.tex.last_level >= templat.u.tex.first_level);
1136 break;
1137 case D3D11_SRV_DIMENSION_BUFFER:
1138 templat.u.buf.first_element = desc->Buffer.ElementOffset;
1139 templat.u.buf.last_element = desc->Buffer.ElementOffset + desc->Buffer.ElementWidth - 1;
1140 break;
1141 case D3D11_SRV_DIMENSION_TEXTURE2DMS:
1142 case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
1143 return E_NOTIMPL;
1144 default:
1145 return E_INVALIDARG;
1146 }
1147
1148 if(!out_srv)
1149 return S_FALSE;
1150
1151 struct pipe_sampler_view* view = immediate_pipe->create_sampler_view(immediate_pipe, templat.texture, &templat);
1152 if(!view)
1153 return E_FAIL;
1154 *out_srv = new GalliumD3D11ShaderResourceView(this, (GalliumD3D11Resource<>*)iresource, view, *desc);
1155 return S_OK;
1156 }
1157
1158 #if API >= 11
1159 virtual HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView(
1160 ID3D11Resource *resource,
1161 const D3D11_UNORDERED_ACCESS_VIEW_DESC *desc,
1162 ID3D11UnorderedAccessView **out_uav)
1163 {
1164 SYNCHRONIZED;
1165
1166 return E_NOTIMPL;
1167
1168 // remember to return S_FALSE and not crash if out_u_a_view == 0 and parameters are valid
1169 }
1170 #endif
1171
1172 virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView(
1173 ID3D11Resource *iresource,
1174 const D3D11_RENDER_TARGET_VIEW_DESC *desc,
1175 ID3D11RenderTargetView **out_rtv)
1176 {
1177 SYNCHRONIZED;
1178
1179 const struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource;
1180
1181 D3D11_RENDER_TARGET_VIEW_DESC def_desc;
1182 if(!desc)
1183 {
1184 init_pipe_to_dxgi_format();
1185 memset(&def_desc, 0, sizeof(def_desc));
1186 def_desc.Format = pipe_to_dxgi_format[resource->format];
1187 switch(resource->target)
1188 {
1189 case PIPE_BUFFER:
1190 def_desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER;
1191 def_desc.Buffer.ElementWidth = resource->width0;
1192 break;
1193 case PIPE_TEXTURE_1D:
1194 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
1195 break;
1196 case PIPE_TEXTURE_1D_ARRAY:
1197 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
1198 def_desc.Texture1DArray.ArraySize = resource->array_size;
1199 break;
1200 case PIPE_TEXTURE_2D:
1201 case PIPE_TEXTURE_RECT:
1202 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1203 break;
1204 case PIPE_TEXTURE_2D_ARRAY:
1205 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1206 def_desc.Texture2DArray.ArraySize = resource->array_size;
1207 break;
1208 case PIPE_TEXTURE_3D:
1209 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
1210 def_desc.Texture3D.WSize = resource->depth0;
1211 break;
1212 case PIPE_TEXTURE_CUBE:
1213 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1214 def_desc.Texture2DArray.ArraySize = 6;
1215 break;
1216 default:
1217 return E_INVALIDARG;
1218 }
1219 desc = &def_desc;
1220 }
1221
1222 struct pipe_surface templat;
1223 memset(&templat, 0, sizeof(templat));
1224 if(invalid(desc->format >= DXGI_FORMAT_COUNT))
1225 return E_INVALIDARG;
1226 templat.format = (desc->Format == DXGI_FORMAT_UNKNOWN) ? resource->format : dxgi_to_pipe_format[desc->Format];
1227 if(!templat.format)
1228 return E_NOTIMPL;
1229 templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
1230
1231 switch(desc->ViewDimension)
1232 {
1233 case D3D11_RTV_DIMENSION_TEXTURE1D:
1234 case D3D11_RTV_DIMENSION_TEXTURE2D:
1235 templat.u.tex.level = desc->Texture1D.MipSlice;
1236 break;
1237 case D3D11_RTV_DIMENSION_TEXTURE3D:
1238 templat.u.tex.level = desc->Texture3D.MipSlice;
1239 templat.u.tex.first_layer = desc->Texture3D.FirstWSlice;
1240 templat.u.tex.last_layer = desc->Texture3D.FirstWSlice + desc->Texture3D.WSize - 1;
1241 break;
1242 case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
1243 case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
1244 templat.u.tex.level = desc->Texture1DArray.MipSlice;
1245 templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
1246 templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice + desc->Texture1DArray.ArraySize - 1;
1247 break;
1248 case D3D11_RTV_DIMENSION_BUFFER:
1249 templat.u.buf.first_element = desc->Buffer.ElementOffset;
1250 templat.u.buf.last_element = desc->Buffer.ElementOffset + desc->Buffer.ElementWidth - 1;
1251 break;
1252 case D3D11_RTV_DIMENSION_TEXTURE2DMS:
1253 case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
1254 return E_NOTIMPL;
1255 default:
1256 return E_INVALIDARG;
1257 }
1258
1259 if(!out_rtv)
1260 return S_FALSE;
1261
1262 struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat);
1263 if(!surface)
1264 return E_FAIL;
1265 *out_rtv = new GalliumD3D11RenderTargetView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc);
1266 return S_OK;
1267 }
1268
1269 virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilView(
1270 ID3D11Resource *iresource,
1271 const D3D11_DEPTH_STENCIL_VIEW_DESC *desc,
1272 ID3D11DepthStencilView **out_depth_stencil_view)
1273 {
1274 SYNCHRONIZED;
1275
1276 const struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource;
1277
1278 D3D11_DEPTH_STENCIL_VIEW_DESC def_desc;
1279 if(!desc)
1280 {
1281 init_pipe_to_dxgi_format();
1282 memset(&def_desc, 0, sizeof(def_desc));
1283 def_desc.Format = pipe_to_dxgi_format[resource->format];
1284 switch(resource->target)
1285 {
1286 case PIPE_TEXTURE_1D:
1287 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
1288 break;
1289 case PIPE_TEXTURE_1D_ARRAY:
1290 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY;
1291 def_desc.Texture1DArray.ArraySize = resource->array_size;
1292 break;
1293 case PIPE_TEXTURE_2D:
1294 case PIPE_TEXTURE_RECT:
1295 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
1296 break;
1297 case PIPE_TEXTURE_2D_ARRAY:
1298 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
1299 def_desc.Texture2DArray.ArraySize = resource->array_size;
1300 break;
1301 case PIPE_TEXTURE_CUBE:
1302 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
1303 def_desc.Texture2DArray.ArraySize = 6;
1304 break;
1305 default:
1306 return E_INVALIDARG;
1307 }
1308 desc = &def_desc;
1309 }
1310
1311 struct pipe_surface templat;
1312 memset(&templat, 0, sizeof(templat));
1313 if(invalid(desc->format >= DXGI_FORMAT_COUNT))
1314 return E_INVALIDARG;
1315 templat.format = (desc->Format == DXGI_FORMAT_UNKNOWN) ? resource->format : dxgi_to_pipe_format[desc->Format];
1316 if(!templat.format)
1317 return E_NOTIMPL;
1318 templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
1319
1320 switch(desc->ViewDimension)
1321 {
1322 case D3D11_DSV_DIMENSION_TEXTURE1D:
1323 case D3D11_DSV_DIMENSION_TEXTURE2D:
1324 templat.u.tex.level = desc->Texture1D.MipSlice;
1325 break;
1326 case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
1327 case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
1328 templat.u.tex.level = desc->Texture1DArray.MipSlice;
1329 templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
1330 templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice + desc->Texture1DArray.ArraySize - 1;
1331 break;
1332 case D3D11_DSV_DIMENSION_TEXTURE2DMS:
1333 case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
1334 return E_NOTIMPL;
1335 default:
1336 return E_INVALIDARG;
1337 }
1338
1339 if(!out_depth_stencil_view)
1340 return S_FALSE;
1341
1342 struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat);
1343 if(!surface)
1344 return E_FAIL;
1345 *out_depth_stencil_view = new GalliumD3D11DepthStencilView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc);
1346 return S_OK;
1347 }
1348
1349 #define D3D1X_SHVER_GEOMETRY_SHADER 2 /* D3D11_SHVER_GEOMETRY_SHADER */
1350
1351 GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void* shader_bytecode, SIZE_T bytecode_length
1352 #if API >= 11
1353 , ID3D11ClassLinkage *class_linkage
1354 #endif
1355 , struct pipe_stream_output_info* so_info)
1356 {
1357 bool dump = debug_get_option_dump_shaders();
1358
1359 std::auto_ptr<sm4_program> sm4(0);
1360
1361 dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(shader_bytecode, bytecode_length);
1362 if(!sm4_chunk)
1363 {
1364 if(so_info)
1365 sm4.reset(new sm4_program());
1366 }
1367 else
1368 {
1369 sm4.reset(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size)));
1370 // check if this is a dummy GS, in which case we only need a place to store the signature
1371 if(sm4.get() && so_info && sm4->version.type != D3D1X_SHVER_GEOMETRY_SHADER)
1372 sm4.reset(new sm4_program());
1373 }
1374 if(!sm4.get())
1375 return 0;
1376
1377 if(dump)
1378 sm4->dump();
1379
1380 struct dxbc_chunk_signature* sig;
1381
1382 sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_INPUT_SIGNATURE);
1383 if(sig)
1384 sm4->num_params_in = dxbc_parse_signature(sig, &sm4->params_in);
1385
1386 sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_OUTPUT_SIGNATURE);
1387 if(sig)
1388 sm4->num_params_out = dxbc_parse_signature(sig, &sm4->params_out);
1389
1390 sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_PATCH_SIGNATURE);
1391 if(sig)
1392 sm4->num_params_patch = dxbc_parse_signature(sig, &sm4->params_patch);
1393
1394 struct pipe_shader_state tgsi_shader;
1395 memset(&tgsi_shader, 0, sizeof(tgsi_shader));
1396 if(so_info)
1397 memcpy(&tgsi_shader.stream_output, so_info, sizeof(tgsi_shader.stream_output));
1398
1399 if(so_info && sm4->version.type != D3D1X_SHVER_GEOMETRY_SHADER)
1400 tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi_linkage_only(*sm4);
1401 else
1402 tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4);
1403 if(!tgsi_shader.tokens)
1404 return 0;
1405
1406 if(dump)
1407 tgsi_dump(tgsi_shader.tokens, 0);
1408
1409 void* shader_cso;
1410 GalliumD3D11Shader<>* shader;
1411
1412 switch(type)
1413 {
1414 case PIPE_SHADER_VERTEX:
1415 shader_cso = immediate_pipe->create_vs_state(immediate_pipe, &tgsi_shader);
1416 shader = (GalliumD3D11Shader<>*)new GalliumD3D11VertexShader(this, shader_cso);
1417 break;
1418 case PIPE_SHADER_FRAGMENT:
1419 shader_cso = immediate_pipe->create_fs_state(immediate_pipe, &tgsi_shader);
1420 shader = (GalliumD3D11Shader<>*)new GalliumD3D11PixelShader(this, shader_cso);
1421 break;
1422 case PIPE_SHADER_GEOMETRY:
1423 shader_cso = immediate_pipe->create_gs_state(immediate_pipe, &tgsi_shader);
1424 shader = (GalliumD3D11Shader<>*)new GalliumD3D11GeometryShader(this, shader_cso);
1425 break;
1426 default:
1427 shader_cso = 0;
1428 shader = 0;
1429 break;
1430 }
1431
1432 free((void*)tgsi_shader.tokens);
1433 return shader;
1434 }
1435
1436 #if API >= 11
1437 #define CREATE_SHADER_ARGS \
1438 const void *shader_bytecode, \
1439 SIZE_T bytecode_length, \
1440 ID3D11ClassLinkage *class_linkage
1441 #define PASS_SHADER_ARGS shader_bytecode, bytecode_length, class_linkage
1442 #else
1443 #define CREATE_SHADER_ARGS \
1444 const void *shader_bytecode, \
1445 SIZE_T bytecode_length
1446 #define PASS_SHADER_ARGS shader_bytecode, bytecode_length
1447 #endif
1448
1449 #define IMPLEMENT_CREATE_SHADER(Stage, GALLIUM) \
1450 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
1451 CREATE_SHADER_ARGS, \
1452 ID3D11##Stage##Shader **out_shader) \
1453 { \
1454 SYNCHRONIZED; \
1455 GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS, NULL); \
1456 if(!shader) \
1457 return E_FAIL; \
1458 if(out_shader) \
1459 { \
1460 *out_shader = shader; \
1461 return S_OK; \
1462 } \
1463 else \
1464 { \
1465 shader->Release(); \
1466 return S_FALSE; \
1467 } \
1468 }
1469
1470 #define IMPLEMENT_NOTIMPL_CREATE_SHADER(Stage) \
1471 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
1472 CREATE_SHADER_ARGS, \
1473 ID3D11##Stage##Shader **out_shader) \
1474 { \
1475 return E_NOTIMPL; \
1476 }
1477
1478 IMPLEMENT_CREATE_SHADER(Vertex, VERTEX)
1479 IMPLEMENT_CREATE_SHADER(Pixel, FRAGMENT)
1480 IMPLEMENT_CREATE_SHADER(Geometry, GEOMETRY)
1481 #if API >= 11
1482 IMPLEMENT_NOTIMPL_CREATE_SHADER(Hull)
1483 IMPLEMENT_NOTIMPL_CREATE_SHADER(Domain)
1484 IMPLEMENT_NOTIMPL_CREATE_SHADER(Compute)
1485 #endif
1486
1487 virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput(
1488 const void *shader_bytecode,
1489 SIZE_T bytecode_length,
1490 const D3D11_SO_DECLARATION_ENTRY *so_declaration,
1491 unsigned num_entries,
1492 #if API >= 11
1493 const unsigned *buffer_strides,
1494 unsigned num_strides,
1495 unsigned rasterized_stream,
1496 ID3D11ClassLinkage *class_linkage,
1497 #else
1498 UINT output_stream_stride,
1499 #endif
1500 ID3D11GeometryShader **out_geometry_shader)
1501 {
1502 SYNCHRONIZED;
1503 GalliumD3D11GeometryShader* gs;
1504
1505 #if API >= 11
1506 if(rasterized_stream != 0)
1507 return E_NOTIMPL; // not yet supported by gallium
1508 #endif
1509 struct dxbc_chunk_signature* sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_OUTPUT_SIGNATURE);
1510 if(!sig)
1511 return E_INVALIDARG;
1512 D3D11_SIGNATURE_PARAMETER_DESC* out;
1513 unsigned num_outputs = dxbc_parse_signature(sig, &out);
1514
1515 struct pipe_stream_output_info so;
1516 memset(&so, 0, sizeof(so));
1517
1518 #if API >= 11
1519 if(num_strides)
1520 so.stride = buffer_strides[0];
1521 if(num_strides > 1)
1522 debug_printf("Warning: multiple user-specified strides not implemented !\n");
1523 #else
1524 so.stride = output_stream_stride;
1525 #endif
1526
1527 for(unsigned i = 0; i < num_entries; ++i)
1528 {
1529 unsigned j;
1530 for(j = 0; j < num_outputs; ++j)
1531 if(out[j].SemanticIndex == so_declaration[i].SemanticIndex && !strcasecmp(out[j].SemanticName, so_declaration[i].SemanticName))
1532 break;
1533 if(j >= num_outputs)
1534 continue;
1535 const int first_comp = ffs(out[j].Mask) - 1 + so_declaration[i].StartComponent;
1536 so.output[i].output_buffer = so_declaration[i].OutputSlot;
1537 so.output[i].register_index = out[j].Register;
1538 so.output[i].register_mask = ((1 << so_declaration[i].ComponentCount) - 1) << first_comp;
1539 ++so.num_outputs;
1540 }
1541 if(out)
1542 free(out);
1543
1544 gs = reinterpret_cast<GalliumD3D11GeometryShader*>(create_stage_shader(PIPE_SHADER_GEOMETRY, PASS_SHADER_ARGS, &so));
1545 if(!gs)
1546 return E_FAIL;
1547
1548 if(!out_geometry_shader) {
1549 gs->Release();
1550 return S_FALSE;
1551 }
1552 *out_geometry_shader = gs;
1553
1554 return S_OK;
1555 }
1556
1557 #if API >= 11
1558 virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage(
1559 ID3D11ClassLinkage **out_linkage)
1560 {
1561 SYNCHRONIZED;
1562
1563 return E_NOTIMPL;
1564 }
1565 #endif
1566
1567 virtual HRESULT STDMETHODCALLTYPE CreateQuery(
1568 const D3D11_QUERY_DESC *query_desc,
1569 ID3D11Query **out_query)
1570 {
1571 SYNCHRONIZED;
1572
1573 if(invalid(query_desc->Query >= D3D11_QUERY_COUNT))
1574 return E_INVALIDARG;
1575 unsigned query_type = d3d11_to_pipe_query[query_desc->Query];
1576 if(query_type >= PIPE_QUERY_TYPES)
1577 return E_NOTIMPL;
1578
1579 if(!out_query)
1580 return S_FALSE;
1581
1582 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
1583 if(!query)
1584 return E_FAIL;
1585
1586 *out_query = new GalliumD3D11Query(this, query, d3d11_query_size[query_desc->Query], *query_desc);
1587 return S_OK;
1588 }
1589
1590 virtual HRESULT STDMETHODCALLTYPE CreatePredicate(
1591 const D3D11_QUERY_DESC *predicate_desc,
1592 ID3D11Predicate **out_predicate)
1593 {
1594 SYNCHRONIZED;
1595
1596 unsigned query_type;
1597 switch(predicate_desc->Query)
1598 {
1599 case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
1600 query_type = PIPE_QUERY_SO_OVERFLOW_PREDICATE;
1601 break;
1602 case D3D11_QUERY_OCCLUSION_PREDICATE:
1603 query_type = PIPE_QUERY_OCCLUSION_PREDICATE;
1604 break;
1605 default:
1606 return E_INVALIDARG;
1607 }
1608
1609 if(out_predicate)
1610 return S_FALSE;
1611
1612 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
1613 if(!query)
1614 return E_FAIL;
1615
1616 *out_predicate = new GalliumD3D11Predicate(this, query, sizeof(BOOL), *predicate_desc);
1617 return S_OK;
1618 }
1619
1620
1621 virtual HRESULT STDMETHODCALLTYPE CreateCounter(
1622 const D3D11_COUNTER_DESC *counter_desc,
1623 ID3D11Counter **out_counter)
1624 {
1625 SYNCHRONIZED;
1626
1627 return E_NOTIMPL;
1628
1629 // remember to return S_FALSE if out_counter == NULL and everything is OK
1630 }
1631
1632 #if API >= 11
1633 virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext(
1634 unsigned context_flags,
1635 ID3D11DeviceContext **out_deferred_context)
1636 {
1637 SYNCHRONIZED;
1638
1639 // TODO: this will have to be implemented using a new Gallium util module
1640 return E_NOTIMPL;
1641
1642 // remember to return S_FALSE if out_counter == NULL and everything is OK
1643 }
1644 #endif
1645
1646 virtual HRESULT STDMETHODCALLTYPE OpenSharedResource(
1647 HANDLE resource,
1648 REFIID iid,
1649 void **out_resource)
1650 {
1651 SYNCHRONIZED;
1652
1653 // TODO: the problem here is that we need to communicate dimensions somehow
1654 return E_NOTIMPL;
1655
1656 // remember to return S_FALSE if out_counter == NULL and everything is OK
1657 #if 0
1658 struct pipe_resou rce templat;
1659 struct winsys_handle handle;
1660 handle.stride = 0;
1661 handle.handle = resource;
1662 handle.type = DRM_API_HANDLE_TYPE_SHARED;
1663 screen->resource_from_handle(screen, &templat, &handle);
1664 #endif
1665 }
1666
1667 #if API < 11
1668 /* these are documented as "Not implemented".
1669 * According to the UMDDI documentation, they apparently turn on a
1670 * (width + 1) x (height + 1) convolution filter for 1-bit textures.
1671 * Probably nothing uses these, assuming it has ever been implemented anywhere.
1672 */
1673 void STDMETHODCALLTYPE SetTextFilterSize(
1674 UINT width,
1675 UINT height
1676 )
1677 {}
1678
1679 virtual void STDMETHODCALLTYPE GetTextFilterSize(
1680 UINT *width,
1681 UINT *height
1682 )
1683 {}
1684 #endif
1685
1686 #if API >= 11
1687 virtual void STDMETHODCALLTYPE RestoreGalliumState()
1688 {
1689 GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(immediate_context);
1690 }
1691
1692 virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly()
1693 {
1694 GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(immediate_context);
1695 }
1696 #endif
1697
1698 virtual struct pipe_context* STDMETHODCALLTYPE GetGalliumContext(void)
1699 {
1700 return immediate_pipe;
1701 }
1702
1703 #undef SYNCHRONIZED
1704 };