1 /**************************************************************************
3 * Copyright 2010 Luca Barbieri
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:
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.
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.
25 **************************************************************************/
27 /* used to unbind things, we need 128 due to resources */
28 static const void* zero_data
[128];
30 #define UPDATE_VIEWS_SHIFT (D3D11_STAGES * 0)
31 #define UPDATE_SAMPLERS_SHIFT (D3D11_STAGES * 1)
32 #define UPDATE_VERTEX_BUFFERS (1 << (D3D11_STAGES * 2))
35 template<typename PtrTraits
>
36 struct GalliumD3D11DeviceContext
:
37 public GalliumD3D11DeviceChild
<ID3D11DeviceContext
>
40 template<bool threadsafe
>
41 struct GalliumD3D10Device
: public GalliumD3D10ScreenImpl
<threadsafe
>
43 typedef simple_ptr_traits PtrTraits
;
44 typedef GalliumD3D10Device GalliumD3D10DeviceContext
;
47 refcnt_ptr
<GalliumD3D11Shader
<>, PtrTraits
> shaders
[D3D11_STAGES
];
48 refcnt_ptr
<GalliumD3D11InputLayout
, PtrTraits
> input_layout
;
49 refcnt_ptr
<GalliumD3D11Buffer
, PtrTraits
> index_buffer
;
50 refcnt_ptr
<GalliumD3D11RasterizerState
, PtrTraits
> rasterizer_state
;
51 refcnt_ptr
<GalliumD3D11DepthStencilState
, PtrTraits
> depth_stencil_state
;
52 refcnt_ptr
<GalliumD3D11BlendState
, PtrTraits
> blend_state
;
53 refcnt_ptr
<GalliumD3D11DepthStencilView
, PtrTraits
> depth_stencil_view
;
54 refcnt_ptr
<GalliumD3D11Predicate
, PtrTraits
> render_predicate
;
56 refcnt_ptr
<GalliumD3D11Buffer
, PtrTraits
> constant_buffers
[D3D11_STAGES
][D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
];
57 refcnt_ptr
<GalliumD3D11ShaderResourceView
, PtrTraits
> shader_resource_views
[D3D11_STAGES
][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT
];
58 refcnt_ptr
<GalliumD3D11SamplerState
, PtrTraits
> samplers
[D3D11_STAGES
][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
];
59 refcnt_ptr
<GalliumD3D11Buffer
, PtrTraits
> input_buffers
[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT
];
60 refcnt_ptr
<GalliumD3D11RenderTargetView
, PtrTraits
> render_target_views
[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT
];
61 refcnt_ptr
<GalliumD3D11Buffer
, PtrTraits
> so_targets
[D3D11_SO_BUFFER_SLOT_COUNT
];
64 refcnt_ptr
<ID3D11UnorderedAccessView
, PtrTraits
> cs_unordered_access_views
[D3D11_PS_CS_UAV_REGISTER_COUNT
];
65 refcnt_ptr
<ID3D11UnorderedAccessView
, PtrTraits
> om_unordered_access_views
[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT
];
68 D3D11_VIEWPORT viewports
[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE
];
69 D3D11_RECT scissor_rects
[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE
];
70 unsigned so_offsets
[D3D11_SO_BUFFER_SLOT_COUNT
];
71 D3D11_PRIMITIVE_TOPOLOGY primitive_topology
;
72 DXGI_FORMAT index_format
;
73 unsigned index_offset
;
74 uint32_t strip_cut_index
;
75 BOOL render_predicate_value
;
81 void* default_input_layout
;
82 void* default_rasterizer
;
83 void* default_depth_stencil
;
85 void* default_sampler
;
87 void * default_shaders
[D3D11_STAGES
];
91 struct pipe_vertex_buffer vertex_buffers
[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT
];
92 struct pipe_resource
* so_buffers
[D3D11_SO_BUFFER_SLOT_COUNT
];
93 struct pipe_sampler_view
* sampler_views
[D3D11_STAGES
][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT
];
96 void* ld
; // accessed with a -1 index from v
97 void* v
[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
];
98 } sampler_csos
[D3D11_STAGES
];
99 struct pipe_resource
* buffers
[D3D11_SO_BUFFER_SLOT_COUNT
];
100 unsigned num_shader_resource_views
[D3D11_STAGES
];
101 unsigned num_samplers
[D3D11_STAGES
];
102 unsigned num_vertex_buffers
;
103 unsigned num_render_target_views
;
104 unsigned num_viewports
;
105 unsigned num_scissor_rects
;
106 unsigned num_so_targets
;
108 struct pipe_context
* pipe
;
109 unsigned update_flags
;
112 unsigned context_flags
;
114 GalliumD3D11Caps caps
;
116 cso_context
* cso_ctx
;
117 gen_mipmap_state
* gen_mipmap
;
120 #define SYNCHRONIZED do {} while(0)
122 GalliumD3D11DeviceContext(GalliumD3D11Screen
* device
, pipe_context
* pipe
, bool owns_pipe
, unsigned context_flags
= 0)
123 : GalliumD3D11DeviceChild
<ID3D11DeviceContext
>(device
), pipe(pipe
), owns_pipe(owns_pipe
), context_flags(context_flags
)
125 caps
= device
->screen_caps
;
129 ~GalliumD3D11DeviceContext()
134 #define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(this->mutex)
136 GalliumD3D10Device(pipe_screen
* screen
, pipe_context
* pipe
, bool owns_pipe
, unsigned creation_flags
, IDXGIAdapter
* adapter
)
137 : GalliumD3D10ScreenImpl
<threadsafe
>(screen
, pipe
, owns_pipe
, creation_flags
, adapter
), pipe(pipe
), owns_pipe(owns_pipe
), context_flags(0)
139 caps
= this->screen_caps
;
143 ~GalliumD3D10Device()
151 if(!pipe
->begin_query
)
152 caps
.queries
= false;
153 if(!pipe
->render_condition
|| !screen
->get_param(screen
, PIPE_CAP_CONDITIONAL_RENDER
))
154 caps
.render_condition
= false;
155 if(!pipe
->bind_gs_state
)
160 if(!pipe
->set_stream_output_buffers
)
162 if(!pipe
->set_geometry_sampler_views
)
163 caps
.stages_with_sampling
&=~ (1 << PIPE_SHADER_GEOMETRY
);
164 if(!pipe
->set_fragment_sampler_views
)
165 caps
.stages_with_sampling
&=~ (1 << PIPE_SHADER_FRAGMENT
);
166 if(!pipe
->set_vertex_sampler_views
)
167 caps
.stages_with_sampling
&=~ (1 << PIPE_SHADER_VERTEX
);
172 memset(viewports
, 0, sizeof(viewports
));
173 memset(scissor_rects
, 0, sizeof(scissor_rects
));
174 memset(so_offsets
, 0, sizeof(so_offsets
));
175 primitive_topology
= D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED
;
176 index_format
= DXGI_FORMAT_UNKNOWN
;
178 strip_cut_index
= 0xffffffff;
179 render_predicate_value
= 0;
180 memset(blend_color
, 0, sizeof(blend_color
));
187 memset(vertex_buffers
, 0, sizeof(vertex_buffers
));
188 memset(so_buffers
, 0, sizeof(so_buffers
));
189 memset(sampler_views
, 0, sizeof(sampler_views
));
190 memset(sampler_csos
, 0, sizeof(sampler_csos
));
191 memset(num_shader_resource_views
, 0, sizeof(num_shader_resource_views
));
192 memset(num_samplers
, 0, sizeof(num_samplers
));
193 num_vertex_buffers
= 0;
194 num_render_target_views
= 0;
196 num_scissor_rects
= 0;
199 default_input_layout
= pipe
->create_vertex_elements_state(pipe
, 0, 0);
201 struct pipe_rasterizer_state rasterizerd
;
202 memset(&rasterizerd
, 0, sizeof(rasterizerd
));
203 rasterizerd
.gl_rasterization_rules
= 1;
204 rasterizerd
.cull_face
= PIPE_FACE_BACK
;
205 rasterizerd
.flatshade_first
= 1;
206 rasterizerd
.line_width
= 1.0f
;
207 rasterizerd
.point_size
= 1.0f
;
208 default_rasterizer
= pipe
->create_rasterizer_state(pipe
, &rasterizerd
);
210 struct pipe_depth_stencil_alpha_state depth_stencild
;
211 memset(&depth_stencild
, 0, sizeof(depth_stencild
));
212 depth_stencild
.depth
.enabled
= TRUE
;
213 depth_stencild
.depth
.writemask
= 1;
214 depth_stencild
.depth
.func
= PIPE_FUNC_LESS
;
215 default_depth_stencil
= pipe
->create_depth_stencil_alpha_state(pipe
, &depth_stencild
);
217 struct pipe_blend_state blendd
;
218 memset(&blendd
, 0, sizeof(blendd
));
219 blendd
.rt
[0].colormask
= 0xf;
220 default_blend
= pipe
->create_blend_state(pipe
, &blendd
);
222 struct pipe_sampler_state samplerd
;
223 memset(&samplerd
, 0, sizeof(samplerd
));
224 samplerd
.normalized_coords
= 1;
225 samplerd
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
226 samplerd
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
227 samplerd
.min_mip_filter
= PIPE_TEX_MIPFILTER_LINEAR
;
228 samplerd
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
229 samplerd
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
230 samplerd
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
231 samplerd
.border_color
.f
[0] = 1.0f
;
232 samplerd
.border_color
.f
[1] = 1.0f
;
233 samplerd
.border_color
.f
[2] = 1.0f
;
234 samplerd
.border_color
.f
[3] = 1.0f
;
235 samplerd
.min_lod
= -FLT_MAX
;
236 samplerd
.max_lod
= FLT_MAX
;
237 samplerd
.max_anisotropy
= 1;
238 default_sampler
= pipe
->create_sampler_state(pipe
, &samplerd
);
240 memset(&samplerd
, 0, sizeof(samplerd
));
241 samplerd
.normalized_coords
= 0;
242 samplerd
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
243 samplerd
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
244 samplerd
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
245 samplerd
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
246 samplerd
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
247 samplerd
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
248 samplerd
.min_lod
= -FLT_MAX
;
249 samplerd
.max_lod
= FLT_MAX
;
250 samplerd
.max_anisotropy
= 1;
251 ld_sampler
= pipe
->create_sampler_state(pipe
, &samplerd
);
253 for(unsigned s
= 0; s
< D3D11_STAGES
; ++s
)
255 sampler_csos
[s
].ld
= ld_sampler
;
256 for(unsigned i
= 0; i
< D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
; ++i
)
257 sampler_csos
[s
].v
[i
] = default_sampler
;
260 // TODO: should this really be empty shaders, or should they be all-passthrough?
261 memset(default_shaders
, 0, sizeof(default_shaders
));
262 struct ureg_program
*ureg
;
263 ureg
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
265 default_shaders
[PIPE_SHADER_FRAGMENT
] = ureg_create_shader_and_destroy(ureg
, pipe
);
267 ureg
= ureg_create(TGSI_PROCESSOR_VERTEX
);
269 default_shaders
[PIPE_SHADER_VERTEX
] = ureg_create_shader_and_destroy(ureg
, pipe
);
271 cso_ctx
= cso_create_context(pipe
);
272 gen_mipmap
= util_create_gen_mipmap(pipe
, cso_ctx
);
274 RestoreGalliumState();
277 void destroy_context()
279 util_destroy_gen_mipmap(gen_mipmap
);
280 cso_destroy_context(cso_ctx
);
282 pipe
->bind_vertex_elements_state(pipe
, 0);
283 pipe
->delete_vertex_elements_state(pipe
, default_input_layout
);
285 pipe
->bind_rasterizer_state(pipe
, 0);
286 pipe
->delete_rasterizer_state(pipe
, default_rasterizer
);
288 pipe
->bind_depth_stencil_alpha_state(pipe
, 0);
289 pipe
->delete_depth_stencil_alpha_state(pipe
, default_depth_stencil
);
291 pipe
->bind_blend_state(pipe
, 0);
292 pipe
->delete_blend_state(pipe
, default_blend
);
294 pipe
->bind_fragment_sampler_states(pipe
, 0, 0);
295 pipe
->bind_vertex_sampler_states(pipe
, 0, 0);
296 if(pipe
->bind_geometry_sampler_states
)
297 pipe
->bind_geometry_sampler_states(pipe
, 0, 0);
298 pipe
->delete_sampler_state(pipe
, default_sampler
);
299 pipe
->delete_sampler_state(pipe
, ld_sampler
);
301 pipe
->bind_fs_state(pipe
, 0);
302 pipe
->delete_fs_state(pipe
, default_shaders
[PIPE_SHADER_FRAGMENT
]);
304 pipe
->bind_vs_state(pipe
, 0);
305 pipe
->delete_vs_state(pipe
, default_shaders
[PIPE_SHADER_VERTEX
]);
311 virtual unsigned STDMETHODCALLTYPE
GetContextFlags(void)
313 return context_flags
;
316 #define SET_SHADER_EXTRA_ARGS , \
317 ID3D11ClassInstance *const *ppClassInstances, \
319 #define GET_SHADER_EXTRA_ARGS , \
320 ID3D11ClassInstance **ppClassInstances, \
323 #define SET_SHADER_EXTRA_ARGS
324 #define GET_SHADER_EXTRA_ARGS
327 /* On Windows D3D11, SetConstantBuffers and SetShaderResources crash if passed a null pointer.
328 * Instead, you have to pass a pointer to nulls to unbind things.
330 * TODO: is D3D10 the same?
333 void xs_set_shader(GalliumD3D11Shader
<>* shader
)
335 if(shader
!= shaders
[s
].p
)
338 void* shader_cso
= shader
? shader
->object
: default_shaders
[s
];
341 case PIPE_SHADER_VERTEX
:
342 pipe
->bind_vs_state(pipe
, shader_cso
);
344 case PIPE_SHADER_FRAGMENT
:
345 pipe
->bind_fs_state(pipe
, shader_cso
);
347 case PIPE_SHADER_GEOMETRY
:
348 pipe
->bind_gs_state(pipe
, shader_cso
);
351 update_flags
|= (1 << (UPDATE_SAMPLERS_SHIFT
+ s
)) | (1 << (UPDATE_VIEWS_SHIFT
+ s
));
356 void xs_set_constant_buffers(unsigned start
, unsigned count
, GalliumD3D11Buffer
*const *constbufs
)
358 for(unsigned i
= 0; i
< count
; ++i
)
360 if(constbufs
[i
] != constant_buffers
[s
][start
+ i
].p
)
362 constant_buffers
[s
][start
+ i
] = constbufs
[i
];
363 if(s
< caps
.stages
&& start
+ i
< caps
.constant_buffers
[s
])
364 pipe
->set_constant_buffer(pipe
, s
, start
+ i
, constbufs
[i
] ? constbufs
[i
]->resource
: NULL
);
370 void xs_set_shader_resources(unsigned start
, unsigned count
, GalliumD3D11ShaderResourceView
*const *srvs
)
372 int last_different
= -1;
373 for(unsigned i
= 0; i
< count
; ++i
)
375 if(shader_resource_views
[s
][start
+ i
].p
!= srvs
[i
])
377 shader_resource_views
[s
][start
+ i
] = srvs
[i
];
378 sampler_views
[s
][start
+ i
] = srvs
[i
] ? srvs
[i
]->object
: 0;
382 if(last_different
>= 0)
384 num_shader_resource_views
[s
] = std::max(num_shader_resource_views
[s
], start
+ last_different
+ 1);
385 update_flags
|= 1 << (UPDATE_VIEWS_SHIFT
+ s
);
390 void xs_set_samplers(unsigned start
, unsigned count
, GalliumD3D11SamplerState
*const *samps
)
392 int last_different
= -1;
393 for(unsigned i
= 0; i
< count
; ++i
)
395 if(samplers
[s
][start
+ i
].p
!= samps
[i
])
397 samplers
[s
][start
+ i
] = samps
[i
];
398 sampler_csos
[s
].v
[start
+ i
] = samps
[i
] ? samps
[i
]->object
: default_sampler
;
401 if(last_different
>= 0)
403 num_samplers
[s
] = std::max(num_samplers
[s
], start
+ last_different
+ 1);
404 update_flags
|= 1 << (UPDATE_SAMPLERS_SHIFT
+ s
);
409 #define IMPLEMENT_SHADER_STAGE(XS, Stage) \
410 virtual void STDMETHODCALLTYPE XS##SetShader( \
411 ID3D11##Stage##Shader *pShader \
412 SET_SHADER_EXTRA_ARGS) \
415 xs_set_shader<D3D11_STAGE_##XS>((GalliumD3D11Shader<>*)pShader); \
417 virtual void STDMETHODCALLTYPE XS##GetShader(\
418 ID3D11##Stage##Shader **ppShader \
419 GET_SHADER_EXTRA_ARGS) \
422 *ppShader = (ID3D11##Stage##Shader*)shaders[D3D11_STAGE_##XS].ref(); \
424 virtual void STDMETHODCALLTYPE XS##SetConstantBuffers(\
427 ID3D11Buffer *const* constant_buffers) \
430 xs_set_constant_buffers<D3D11_STAGE_##XS>(start, count, (GalliumD3D11Buffer *const *)constant_buffers); \
432 virtual void STDMETHODCALLTYPE XS##GetConstantBuffers(\
435 ID3D11Buffer **out_constant_buffers) \
438 for(unsigned i = 0; i < count; ++i) \
439 out_constant_buffers[i] = constant_buffers[D3D11_STAGE_##XS][start + i].ref(); \
441 virtual void STDMETHODCALLTYPE XS##SetShaderResources(\
444 ID3D11ShaderResourceView *const *new_shader_resource_views) \
447 xs_set_shader_resources<D3D11_STAGE_##XS>(start, count, (GalliumD3D11ShaderResourceView *const *)new_shader_resource_views); \
449 virtual void STDMETHODCALLTYPE XS##GetShaderResources(\
452 ID3D11ShaderResourceView **out_shader_resource_views) \
455 for(unsigned i = 0; i < count; ++i) \
456 out_shader_resource_views[i] = shader_resource_views[D3D11_STAGE_##XS][start + i].ref(); \
458 virtual void STDMETHODCALLTYPE XS##SetSamplers(\
461 ID3D11SamplerState *const *new_samplers) \
464 xs_set_samplers<D3D11_STAGE_##XS>(start, count, (GalliumD3D11SamplerState *const *)new_samplers); \
466 virtual void STDMETHODCALLTYPE XS##GetSamplers( \
469 ID3D11SamplerState **out_samplers) \
472 for(unsigned i = 0; i < count; ++i) \
473 out_samplers[i] = samplers[D3D11_STAGE_##XS][start + i].ref(); \
477 #define DO_GS(x) do {if(caps.gs) {x;}} while(0)
482 IMPLEMENT_SHADER_STAGE(VS
, Vertex
)
483 IMPLEMENT_SHADER_STAGE(GS
, Geometry
)
484 IMPLEMENT_SHADER_STAGE(PS
, Pixel
)
487 IMPLEMENT_SHADER_STAGE(HS
, Hull
)
488 IMPLEMENT_SHADER_STAGE(DS
, Domain
)
489 IMPLEMENT_SHADER_STAGE(CS
, Compute
)
491 virtual void STDMETHODCALLTYPE
CSSetUnorderedAccessViews(
494 ID3D11UnorderedAccessView
*const *new_unordered_access_views
,
495 const unsigned *new_uav_initial_counts
)
498 for(unsigned i
= 0; i
< count
; ++i
)
499 cs_unordered_access_views
[start
+ i
] = new_unordered_access_views
[i
];
502 virtual void STDMETHODCALLTYPE
CSGetUnorderedAccessViews(
505 ID3D11UnorderedAccessView
**out_unordered_access_views
)
508 for(unsigned i
= 0; i
< count
; ++i
)
509 out_unordered_access_views
[i
] = cs_unordered_access_views
[start
+ i
].ref();
516 if(update_flags
& (1 << (UPDATE_VIEWS_SHIFT
+ s
)))
518 while(num_shader_resource_views
[s
] && !sampler_views
[s
][num_shader_resource_views
[s
] - 1]) \
519 --num_shader_resource_views
[s
];
520 if((1 << s
) & caps
.stages_with_sampling
)
522 struct pipe_sampler_view
* views_to_bind
[PIPE_MAX_SAMPLERS
];
523 unsigned num_views_to_bind
= shaders
[s
] ? shaders
[s
]->slot_to_resource
.size() : 0;
524 for(unsigned i
= 0; i
< num_views_to_bind
; ++i
)
526 views_to_bind
[i
] = sampler_views
[s
][shaders
[s
]->slot_to_resource
[i
]];
530 case PIPE_SHADER_VERTEX
:
531 pipe
->set_vertex_sampler_views(pipe
, num_views_to_bind
, views_to_bind
);
533 case PIPE_SHADER_FRAGMENT
:
534 pipe
->set_fragment_sampler_views(pipe
, num_views_to_bind
, views_to_bind
);
536 case PIPE_SHADER_GEOMETRY
:
537 pipe
->set_geometry_sampler_views(pipe
, num_views_to_bind
, views_to_bind
);
543 if(update_flags
& (1 << (UPDATE_SAMPLERS_SHIFT
+ s
)))
545 while(num_samplers
[s
] && !sampler_csos
[s
].v
[num_samplers
[s
] - 1])
547 if((1 << s
) & caps
.stages_with_sampling
)
549 void* samplers_to_bind
[PIPE_MAX_SAMPLERS
];
550 unsigned num_samplers_to_bind
= shaders
[s
] ? shaders
[s
]->slot_to_sampler
.size() : 0;
551 for(unsigned i
= 0; i
< num_samplers_to_bind
; ++i
)
553 // index can be -1 to access sampler_csos[s].ld
554 samplers_to_bind
[i
] = *(sampler_csos
[s
].v
+ shaders
[s
]->slot_to_sampler
[i
]);
558 case PIPE_SHADER_VERTEX
:
559 pipe
->bind_vertex_sampler_states(pipe
, num_samplers_to_bind
, samplers_to_bind
);
561 case PIPE_SHADER_FRAGMENT
:
562 pipe
->bind_fragment_sampler_states(pipe
, num_samplers_to_bind
, samplers_to_bind
);
564 case PIPE_SHADER_GEOMETRY
:
565 pipe
->bind_geometry_sampler_states(pipe
, num_samplers_to_bind
, samplers_to_bind
);
574 update_stage
<D3D11_STAGE_PS
>();
575 update_stage
<D3D11_STAGE_VS
>();
576 update_stage
<D3D11_STAGE_GS
>();
578 update_stage
<D3D11_STAGE_HS
>();
579 update_stage
<D3D11_STAGE_DS
>();
580 update_stage
<D3D11_STAGE_CS
>();
583 if(update_flags
& UPDATE_VERTEX_BUFFERS
)
585 while(num_vertex_buffers
&& !vertex_buffers
[num_vertex_buffers
- 1].buffer
)
586 --num_vertex_buffers
;
587 pipe
->set_vertex_buffers(pipe
, num_vertex_buffers
, vertex_buffers
);
593 virtual void STDMETHODCALLTYPE
IASetInputLayout(
594 ID3D11InputLayout
*new_input_layout
)
597 if(new_input_layout
!= input_layout
.p
)
599 input_layout
= new_input_layout
;
600 pipe
->bind_vertex_elements_state(pipe
, new_input_layout
? ((GalliumD3D11InputLayout
*)new_input_layout
)->object
: default_input_layout
);
604 virtual void STDMETHODCALLTYPE
IAGetInputLayout(
605 ID3D11InputLayout
**out_input_layout
)
608 *out_input_layout
= input_layout
.ref();
611 virtual void STDMETHODCALLTYPE
IASetVertexBuffers(
614 ID3D11Buffer
*const *new_vertex_buffers
,
615 const unsigned *new_strides
,
616 const unsigned *new_offsets
)
619 int last_different
= -1;
620 for(unsigned i
= 0; i
< count
; ++i
)
622 ID3D11Buffer
* buffer
= new_vertex_buffers
[i
];
623 if(buffer
!= input_buffers
[start
+ i
].p
624 || vertex_buffers
[start
+ i
].buffer_offset
!= new_offsets
[i
]
625 || vertex_buffers
[start
+ i
].stride
!= new_offsets
[i
]
628 input_buffers
[start
+ i
] = buffer
;
629 vertex_buffers
[start
+ i
].buffer
= buffer
? ((GalliumD3D11Buffer
*)buffer
)->resource
: 0;
630 vertex_buffers
[start
+ i
].buffer_offset
= new_offsets
[i
];
631 vertex_buffers
[start
+ i
].stride
= new_strides
[i
];
635 if(last_different
>= 0)
637 num_vertex_buffers
= std::max(num_vertex_buffers
, start
+ count
);
638 update_flags
|= UPDATE_VERTEX_BUFFERS
;
642 virtual void STDMETHODCALLTYPE
IAGetVertexBuffers(
645 ID3D11Buffer
**out_vertex_buffers
,
646 unsigned *out_strides
,
647 unsigned *out_offsets
)
650 if(out_vertex_buffers
)
652 for(unsigned i
= 0; i
< count
; ++i
)
653 out_vertex_buffers
[i
] = input_buffers
[start
+ i
].ref();
658 for(unsigned i
= 0; i
< count
; ++i
)
659 out_offsets
[i
] = vertex_buffers
[start
+ i
].buffer_offset
;
664 for(unsigned i
= 0; i
< count
; ++i
)
665 out_strides
[i
] = vertex_buffers
[start
+ i
].stride
;
669 void set_index_buffer()
671 pipe_index_buffer ib
;
674 memset(&ib
, 0, sizeof(ib
));
678 switch(index_format
) {
679 case DXGI_FORMAT_R32_UINT
:
681 strip_cut_index
= 0xffffffff;
683 case DXGI_FORMAT_R16_UINT
:
685 strip_cut_index
= 0xffff;
689 strip_cut_index
= 0xff;
692 ib
.offset
= index_offset
;
693 ib
.buffer
= index_buffer
? ((GalliumD3D11Buffer
*)index_buffer
.p
)->resource
: 0;
695 pipe
->set_index_buffer(pipe
, &ib
);
698 virtual void STDMETHODCALLTYPE
IASetIndexBuffer(
699 ID3D11Buffer
*new_index_buffer
,
700 DXGI_FORMAT new_index_format
,
701 unsigned new_index_offset
)
704 if(index_buffer
.p
!= new_index_buffer
|| index_format
!= new_index_format
|| index_offset
!= new_index_offset
)
706 index_buffer
= new_index_buffer
;
707 index_format
= new_index_format
;
708 index_offset
= new_index_offset
;
714 virtual void STDMETHODCALLTYPE
IAGetIndexBuffer(
715 ID3D11Buffer
**out_index_buffer
,
716 DXGI_FORMAT
*out_index_format
,
717 unsigned *out_index_offset
)
721 *out_index_buffer
= index_buffer
.ref();
723 *out_index_format
= index_format
;
725 *out_index_offset
= index_offset
;
728 virtual void STDMETHODCALLTYPE
IASetPrimitiveTopology(
729 D3D11_PRIMITIVE_TOPOLOGY new_primitive_topology
)
732 if(primitive_topology
!= new_primitive_topology
)
734 if(new_primitive_topology
< D3D_PRIMITIVE_TOPOLOGY_COUNT
)
735 primitive_mode
= d3d_to_pipe_prim
[new_primitive_topology
];
738 primitive_topology
= new_primitive_topology
;
742 virtual void STDMETHODCALLTYPE
IAGetPrimitiveTopology(
743 D3D11_PRIMITIVE_TOPOLOGY
*out_primitive_topology
)
746 *out_primitive_topology
= primitive_topology
;
749 virtual void STDMETHODCALLTYPE
DrawIndexed(
750 unsigned index_count
,
751 unsigned start_index_location
,
752 int base_vertex_location
)
759 info
.mode
= primitive_mode
;
761 info
.count
= index_count
;
762 info
.start
= start_index_location
;
763 info
.index_bias
= base_vertex_location
;
766 info
.start_instance
= 0;
767 info
.instance_count
= 1;
768 info
.primitive_restart
= FALSE
;
770 pipe
->draw_vbo(pipe
, &info
);
773 virtual void STDMETHODCALLTYPE
Draw(
774 unsigned vertex_count
,
775 unsigned start_vertex_location
)
782 info
.mode
= primitive_mode
;
783 info
.indexed
= FALSE
;
784 info
.count
= vertex_count
;
785 info
.start
= start_vertex_location
;
789 info
.start_instance
= 0;
790 info
.instance_count
= 1;
791 info
.primitive_restart
= TRUE
;
792 info
.restart_index
= strip_cut_index
;
794 pipe
->draw_vbo(pipe
, &info
);
797 virtual void STDMETHODCALLTYPE
DrawIndexedInstanced(
798 unsigned index_countPerInstance
,
799 unsigned instance_count
,
800 unsigned start_index_location
,
801 int base_vertex_location
,
802 unsigned start_instance_location
)
809 info
.mode
= primitive_mode
;
811 info
.count
= index_countPerInstance
;
812 info
.start
= start_index_location
;
813 info
.index_bias
= base_vertex_location
;
816 info
.start_instance
= start_instance_location
;
817 info
.instance_count
= instance_count
;
818 info
.primitive_restart
= FALSE
;
820 pipe
->draw_vbo(pipe
, &info
);
823 virtual void STDMETHODCALLTYPE
DrawInstanced(
824 unsigned vertex_countPerInstance
,
825 unsigned instance_count
,
826 unsigned start_vertex_location
,
827 unsigned start_instance_location
)
834 info
.mode
= primitive_mode
;
835 info
.indexed
= FALSE
;
836 info
.count
= vertex_countPerInstance
;
837 info
.start
= start_vertex_location
;
841 info
.start_instance
= start_instance_location
;
842 info
.instance_count
= instance_count
;
843 info
.primitive_restart
= TRUE
;
844 info
.restart_index
= strip_cut_index
;
846 pipe
->draw_vbo(pipe
, &info
);
849 virtual void STDMETHODCALLTYPE
DrawAuto(void)
858 pipe
->draw_stream_output(pipe
, primitive_mode
);
861 virtual void STDMETHODCALLTYPE
DrawIndexedInstancedIndirect(
862 ID3D11Buffer
*buffer
,
863 unsigned aligned_byte_offset
)
871 unsigned instance_count
;
876 pipe_buffer_read(pipe
, ((GalliumD3D11Buffer
*)buffer
)->resource
, aligned_byte_offset
, sizeof(data
), &data
);
879 info
.mode
= primitive_mode
;
881 info
.start
= data
.start
;
882 info
.count
= data
.count
;
883 info
.index_bias
= data
.index_bias
;
886 info
.start_instance
= 0;
887 info
.instance_count
= data
.instance_count
;
888 info
.primitive_restart
= FALSE
;
890 pipe
->draw_vbo(pipe
, &info
);
893 virtual void STDMETHODCALLTYPE
DrawInstancedIndirect(
894 ID3D11Buffer
*buffer
,
895 unsigned aligned_byte_offset
)
903 unsigned instance_count
;
907 pipe_buffer_read(pipe
, ((GalliumD3D11Buffer
*)buffer
)->resource
, aligned_byte_offset
, sizeof(data
), &data
);
910 info
.mode
= primitive_mode
;
911 info
.indexed
= FALSE
;
912 info
.start
= data
.start
;
913 info
.count
= data
.count
;
917 info
.start_instance
= 0;
918 info
.instance_count
= data
.instance_count
;
919 info
.primitive_restart
= TRUE
;
920 info
.restart_index
= strip_cut_index
;
922 pipe
->draw_vbo(pipe
, &info
);
926 virtual void STDMETHODCALLTYPE
Dispatch(
927 unsigned thread_group_count_x
,
928 unsigned thread_group_count_y
,
929 unsigned thread_group_count_z
)
931 // uncomment this when this is implemented
937 virtual void STDMETHODCALLTYPE
DispatchIndirect(
938 ID3D11Buffer
*buffer
,
939 unsigned aligned_byte_offset
)
941 // uncomment this when this is implemented
950 pipe_clip_state clip
;
952 clip
.depth_clamp
= depth_clamp
;
953 pipe
->set_clip_state(pipe
, &clip
);
956 virtual void STDMETHODCALLTYPE
RSSetState(
957 ID3D11RasterizerState
*new_rasterizer_state
)
960 if(new_rasterizer_state
!= rasterizer_state
.p
)
962 rasterizer_state
= new_rasterizer_state
;
963 pipe
->bind_rasterizer_state(pipe
, new_rasterizer_state
? ((GalliumD3D11RasterizerState
*)new_rasterizer_state
)->object
: default_rasterizer
);
964 bool new_depth_clamp
= new_rasterizer_state
? ((GalliumD3D11RasterizerState
*)new_rasterizer_state
)->depth_clamp
: false;
965 if(depth_clamp
!= new_depth_clamp
)
967 depth_clamp
= new_depth_clamp
;
973 virtual void STDMETHODCALLTYPE
RSGetState(
974 ID3D11RasterizerState
**out_rasterizer_state
)
977 *out_rasterizer_state
= rasterizer_state
.ref();
982 // TODO: is depth correct? it seems D3D10/11 uses a [-1,1]x[-1,1]x[0,1] cube
983 pipe_viewport_state viewport
;
984 float half_width
= viewports
[0].Width
* 0.5f
;
985 float half_height
= viewports
[0].Height
* 0.5f
;
987 viewport
.scale
[0] = half_width
;
988 viewport
.scale
[1] = -half_height
;
989 viewport
.scale
[2] = (viewports
[0].MaxDepth
- viewports
[0].MinDepth
);
990 viewport
.scale
[3] = 1.0f
;
991 viewport
.translate
[0] = half_width
+ viewports
[0].TopLeftX
;
992 viewport
.translate
[1] = half_height
+ viewports
[0].TopLeftY
;
993 viewport
.translate
[2] = viewports
[0].MinDepth
;
994 viewport
.translate
[3] = 1.0f
;
995 pipe
->set_viewport_state(pipe
, &viewport
);
998 virtual void STDMETHODCALLTYPE
RSSetViewports(
1000 const D3D11_VIEWPORT
*new_viewports
)
1005 if(memcmp(&viewports
[0], &new_viewports
[0], sizeof(viewports
[0])))
1007 viewports
[0] = new_viewports
[0];
1010 for(unsigned i
= 1; i
< count
; ++i
)
1011 viewports
[i
] = new_viewports
[i
];
1013 else if(num_viewports
)
1015 // TODO: what should we do here?
1016 memset(&viewports
[0], 0, sizeof(viewports
[0]));
1019 num_viewports
= count
;
1022 virtual void STDMETHODCALLTYPE
RSGetViewports(
1023 unsigned *out_count
,
1024 D3D11_VIEWPORT
*out_viewports
)
1030 for(i
= 0; i
< std::min(*out_count
, num_viewports
); ++i
)
1031 out_viewports
[i
] = viewports
[i
];
1033 memset(out_viewports
+ i
, 0, (*out_count
- i
) * sizeof(D3D11_VIEWPORT
));
1036 *out_count
= num_viewports
;
1041 pipe_scissor_state scissor
;
1042 scissor
.minx
= scissor_rects
[0].left
;
1043 scissor
.miny
= scissor_rects
[0].top
;
1044 scissor
.maxx
= scissor_rects
[0].right
;
1045 scissor
.maxy
= scissor_rects
[0].bottom
;
1046 pipe
->set_scissor_state(pipe
, &scissor
);
1049 virtual void STDMETHODCALLTYPE
RSSetScissorRects(
1051 const D3D11_RECT
*new_rects
)
1056 if(memcmp(&scissor_rects
[0], &new_rects
[0], sizeof(scissor_rects
[0])))
1058 scissor_rects
[0] = new_rects
[0];
1061 for(unsigned i
= 1; i
< count
; ++i
)
1062 scissor_rects
[i
] = new_rects
[i
];
1064 else if(num_scissor_rects
)
1066 // TODO: what should we do here?
1067 memset(&scissor_rects
[0], 0, sizeof(scissor_rects
[0]));
1071 num_scissor_rects
= count
;
1074 virtual void STDMETHODCALLTYPE
RSGetScissorRects(
1075 unsigned *out_count
,
1076 D3D11_RECT
*out_rects
)
1082 for(i
= 0; i
< std::min(*out_count
, num_scissor_rects
); ++i
)
1083 out_rects
[i
] = scissor_rects
[i
];
1085 memset(out_rects
+ i
, 0, (*out_count
- i
) * sizeof(D3D11_RECT
));
1088 *out_count
= num_scissor_rects
;
1091 virtual void STDMETHODCALLTYPE
OMSetBlendState(
1092 ID3D11BlendState
*new_blend_state
,
1093 const float new_blend_factor
[4],
1094 unsigned new_sample_mask
)
1097 float white
[4] = {1.0f
, 1.0f
, 1.0f
, 1.0f
};
1099 if(blend_state
.p
!= new_blend_state
)
1101 pipe
->bind_blend_state(pipe
, new_blend_state
? ((GalliumD3D11BlendState
*)new_blend_state
)->object
: default_blend
);
1102 blend_state
= new_blend_state
;
1105 // Windows D3D11 does this, even though it's apparently undocumented
1106 if(!new_blend_factor
)
1107 new_blend_factor
= white
;
1109 if(memcmp(blend_color
, new_blend_factor
, sizeof(blend_color
)))
1111 pipe
->set_blend_color(pipe
, (struct pipe_blend_color
*)new_blend_factor
);
1112 memcpy(blend_color
, new_blend_factor
, sizeof(blend_color
));
1115 if(sample_mask
!= new_sample_mask
)
1117 pipe
->set_sample_mask(pipe
, new_sample_mask
);
1118 sample_mask
= new_sample_mask
;
1122 virtual void STDMETHODCALLTYPE
OMGetBlendState(
1123 ID3D11BlendState
**out_blend_state
,
1124 float out_blend_factor
[4],
1125 unsigned *out_sample_mask
)
1129 *out_blend_state
= blend_state
.ref();
1130 if(out_blend_factor
)
1131 memcpy(out_blend_factor
, blend_color
, sizeof(blend_color
));
1133 *out_sample_mask
= sample_mask
;
1136 void set_stencil_ref()
1138 struct pipe_stencil_ref sref
;
1139 sref
.ref_value
[0] = stencil_ref
;
1140 sref
.ref_value
[1] = stencil_ref
;
1141 pipe
->set_stencil_ref(pipe
, &sref
);
1144 virtual void STDMETHODCALLTYPE
OMSetDepthStencilState(
1145 ID3D11DepthStencilState
*new_depth_stencil_state
,
1146 unsigned new_stencil_ref
)
1149 if(new_depth_stencil_state
!= depth_stencil_state
.p
)
1151 pipe
->bind_depth_stencil_alpha_state(pipe
, new_depth_stencil_state
? ((GalliumD3D11DepthStencilState
*)new_depth_stencil_state
)->object
: default_depth_stencil
);
1152 depth_stencil_state
= new_depth_stencil_state
;
1155 if(new_stencil_ref
!= stencil_ref
)
1157 stencil_ref
= new_stencil_ref
;
1162 virtual void STDMETHODCALLTYPE
OMGetDepthStencilState(
1163 ID3D11DepthStencilState
**out_depth_stencil_state
,
1164 unsigned *out_stencil_ref
)
1167 if(*out_depth_stencil_state
)
1168 *out_depth_stencil_state
= depth_stencil_state
.ref();
1170 *out_stencil_ref
= stencil_ref
;
1173 void set_framebuffer()
1175 struct pipe_framebuffer_state fb
;
1176 memset(&fb
, 0, sizeof(fb
));
1177 if(depth_stencil_view
)
1179 struct pipe_surface
* surf
= ((GalliumD3D11DepthStencilView
*)depth_stencil_view
.p
)->object
;
1181 if(surf
->width
> fb
.width
)
1182 fb
.width
= surf
->width
;
1183 if(surf
->height
> fb
.height
)
1184 fb
.height
= surf
->height
;
1186 fb
.nr_cbufs
= num_render_target_views
;
1188 for(i
= 0; i
< num_render_target_views
; ++i
)
1190 if(render_target_views
[i
])
1192 struct pipe_surface
* surf
= ((GalliumD3D11RenderTargetView
*)render_target_views
[i
].p
)->object
;
1194 if(surf
->width
> fb
.width
)
1195 fb
.width
= surf
->width
;
1196 if(surf
->height
> fb
.height
)
1197 fb
.height
= surf
->height
;
1201 pipe
->set_framebuffer_state(pipe
, &fb
);
1204 /* TODO: the docs say that we should unbind conflicting resources (e.g. those bound for read while we are binding them for write too), but we aren't.
1205 * Hopefully nobody relies on this happening
1208 virtual void STDMETHODCALLTYPE
OMSetRenderTargets(
1210 ID3D11RenderTargetView
*const *new_render_target_views
,
1211 ID3D11DepthStencilView
*new_depth_stencil_view
)
1214 if(!new_render_target_views
)
1216 if(count
== num_render_target_views
)
1218 for(unsigned i
= 0; i
< count
; ++i
)
1220 if(new_render_target_views
[i
] != render_target_views
[i
].p
)
1226 depth_stencil_view
= new_depth_stencil_view
;
1228 for(i
= 0; i
< count
; ++i
)
1230 render_target_views
[i
] = new_render_target_views
[i
];
1232 om_unordered_access_views
[i
] = (ID3D11UnorderedAccessView
*)NULL
;
1235 for(; i
< num_render_target_views
; ++i
)
1236 render_target_views
[i
] = (ID3D11RenderTargetView
*)NULL
;
1237 num_render_target_views
= count
;
1241 virtual void STDMETHODCALLTYPE
OMGetRenderTargets(
1243 ID3D11RenderTargetView
**out_render_target_views
,
1244 ID3D11DepthStencilView
**out_depth_stencil_view
)
1247 if(out_render_target_views
)
1250 for(i
= 0; i
< std::min(num_render_target_views
, count
); ++i
)
1251 out_render_target_views
[i
] = render_target_views
[i
].ref();
1253 for(; i
< count
; ++i
)
1254 out_render_target_views
[i
] = 0;
1257 if(out_depth_stencil_view
)
1258 *out_depth_stencil_view
= depth_stencil_view
.ref();
1262 /* TODO: what is this supposed to do _exactly_? are we doing the right thing? */
1263 virtual void STDMETHODCALLTYPE
OMSetRenderTargetsAndUnorderedAccessViews(
1265 ID3D11RenderTargetView
*const *new_render_target_views
,
1266 ID3D11DepthStencilView
*new_depth_stencil_view
,
1269 ID3D11UnorderedAccessView
*const *new_unordered_access_views
,
1270 const unsigned *new_uav_initial_counts
)
1273 if(rtv_count
!= D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL
)
1274 OMSetRenderTargets(rtv_count
, new_render_target_views
, new_depth_stencil_view
);
1276 if(uav_count
!= D3D11_KEEP_UNORDERED_ACCESS_VIEWS
)
1278 for(unsigned i
= 0; i
< uav_count
; ++i
)
1280 om_unordered_access_views
[uav_start
+ i
] = new_unordered_access_views
[i
];
1281 render_target_views
[uav_start
+ i
] = (ID3D11RenderTargetView
*)0;
1286 virtual void STDMETHODCALLTYPE
OMGetRenderTargetsAndUnorderedAccessViews(
1288 ID3D11RenderTargetView
**out_render_target_views
,
1289 ID3D11DepthStencilView
**out_depth_stencil_view
,
1292 ID3D11UnorderedAccessView
**out_unordered_access_views
)
1295 if(out_render_target_views
)
1296 OMGetRenderTargets(rtv_count
, out_render_target_views
, out_depth_stencil_view
);
1298 if(out_unordered_access_views
)
1300 for(unsigned i
= 0; i
< uav_count
; ++i
)
1301 out_unordered_access_views
[i
] = om_unordered_access_views
[uav_start
+ i
].ref();
1306 virtual void STDMETHODCALLTYPE
SOSetTargets(
1308 ID3D11Buffer
*const *new_so_targets
,
1309 const unsigned *new_offsets
)
1315 bool changed
= false;
1316 for(i
= 0; i
< count
; ++i
)
1318 ID3D11Buffer
* buffer
= new_so_targets
[i
];
1319 if(buffer
!= so_targets
[i
].p
|| new_offsets
[i
] != so_offsets
[i
])
1321 so_buffers
[i
] = buffer
? ((GalliumD3D11Buffer
*)buffer
)->resource
: 0;
1322 so_targets
[i
] = buffer
;
1323 so_offsets
[i
] = new_offsets
[i
];
1327 for(; i
< D3D11_SO_BUFFER_SLOT_COUNT
; ++i
)
1329 if(so_targets
[i
].p
|| so_offsets
[i
])
1332 so_targets
[i
] = (ID3D11Buffer
*)0;
1336 num_so_targets
= count
;
1338 if(changed
&& caps
.so
)
1339 pipe
->set_stream_output_buffers(pipe
, so_buffers
, (int*)so_offsets
, num_so_targets
);
1342 virtual void STDMETHODCALLTYPE
SOGetTargets(
1344 ID3D11Buffer
**out_so_targets
1351 for(unsigned i
= 0; i
< count
; ++i
)
1353 out_so_targets
[i
] = so_targets
[i
].ref();
1355 out_offsets
[i
] = so_offsets
[i
];
1360 virtual void STDMETHODCALLTYPE
Begin(
1361 ID3D11Asynchronous
*async
)
1365 pipe
->begin_query(pipe
, ((GalliumD3D11Asynchronous
<>*)async
)->query
);
1368 virtual void STDMETHODCALLTYPE
End(
1369 ID3D11Asynchronous
*async
)
1373 pipe
->end_query(pipe
, ((GalliumD3D11Asynchronous
<>*)async
)->query
);
1376 virtual HRESULT STDMETHODCALLTYPE
GetData(
1377 ID3D11Asynchronous
*iasync
,
1380 unsigned get_data_flags
)
1386 GalliumD3D11Asynchronous
<>* async
= (GalliumD3D11Asynchronous
<>*)iasync
;
1387 void* tmp_data
= alloca(async
->data_size
);
1388 boolean ret
= pipe
->get_query_result(pipe
, async
->query
, !(get_data_flags
& D3D11_ASYNC_GETDATA_DONOTFLUSH
), tmp_data
);
1390 memcpy(out_data
, tmp_data
, std::min(async
->data_size
, data_size
));
1391 return ret
? S_OK
: S_FALSE
;
1394 void set_render_condition()
1396 if(caps
.render_condition
)
1398 if(!render_predicate
)
1399 pipe
->render_condition(pipe
, 0, 0);
1402 GalliumD3D11Predicate
* predicate
= (GalliumD3D11Predicate
*)render_predicate
.p
;
1403 if(!render_predicate_value
&& predicate
->desc
.Query
== D3D11_QUERY_OCCLUSION_PREDICATE
)
1405 unsigned mode
= (predicate
->desc
.MiscFlags
& D3D11_QUERY_MISC_PREDICATEHINT
) ? PIPE_RENDER_COND_NO_WAIT
: PIPE_RENDER_COND_WAIT
;
1406 pipe
->render_condition(pipe
, predicate
->query
, mode
);
1410 /* TODO: add inverted predication to Gallium*/
1411 pipe
->render_condition(pipe
, 0, 0);
1417 virtual void STDMETHODCALLTYPE
SetPredication(
1418 ID3D11Predicate
*new_predicate
,
1419 BOOL new_predicate_value
)
1422 if(render_predicate
.p
!= new_predicate
|| render_predicate_value
!= new_predicate_value
)
1424 render_predicate
= new_predicate
;
1425 render_predicate_value
= new_predicate_value
;
1426 set_render_condition();
1430 virtual void STDMETHODCALLTYPE
GetPredication(
1431 ID3D11Predicate
**out_predicate
,
1432 BOOL
*out_predicate_value
)
1436 *out_predicate
= render_predicate
.ref();
1437 if(out_predicate_value
)
1438 *out_predicate_value
= render_predicate_value
;
1441 static unsigned d3d11_subresource_to_level(struct pipe_resource
* resource
, unsigned subresource
)
1443 if(subresource
<= resource
->last_level
)
1449 unsigned levels
= resource
->last_level
+ 1;
1450 return subresource
% levels
;
1454 static unsigned d3d11_subresource_to_face(struct pipe_resource
* resource
, unsigned subresource
)
1456 if(subresource
<= resource
->last_level
)
1462 unsigned levels
= resource
->last_level
+ 1;
1463 return subresource
/ levels
;
1468 /* TODO: deferred contexts will need a different implementation of this,
1469 * because we can't put the transfer info into the resource itself.
1470 * Also, there are very different restrictions, for obvious reasons.
1472 virtual HRESULT STDMETHODCALLTYPE
Map(
1473 ID3D11Resource
*iresource
,
1474 unsigned subresource
,
1477 D3D11_MAPPED_SUBRESOURCE
*mapped_resource
)
1480 GalliumD3D11Resource
<>* resource
= (GalliumD3D11Resource
<>*)iresource
;
1481 if(resource
->transfers
.count(subresource
))
1483 unsigned level
= d3d11_subresource_to_level(resource
->resource
, subresource
);
1484 unsigned face
= d3d11_subresource_to_face(resource
->resource
, subresource
);
1485 pipe_box box
= d3d11_to_pipe_box(resource
->resource
, level
, 0);
1486 /* XXX the translation from subresource to level/face(zslice/array layer) isn't quite right */
1488 if(map_type
== D3D11_MAP_READ
)
1489 usage
= PIPE_TRANSFER_READ
;
1490 else if(map_type
== D3D11_MAP_WRITE
)
1491 usage
= PIPE_TRANSFER_WRITE
;
1492 else if(map_type
== D3D11_MAP_READ_WRITE
)
1493 usage
= PIPE_TRANSFER_READ_WRITE
;
1494 else if(map_type
== D3D11_MAP_WRITE_DISCARD
)
1495 usage
= PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
;
1496 else if(map_type
== D3D11_MAP_WRITE_NO_OVERWRITE
)
1497 usage
= PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_NOOVERWRITE
;
1499 return E_INVALIDARG
;
1500 if(map_type
& D3D10_MAP_FLAG_DO_NOT_WAIT
)
1501 usage
|= PIPE_TRANSFER_DONTBLOCK
;
1502 struct pipe_transfer
* transfer
= pipe
->get_transfer(pipe
, resource
->resource
, level
, usage
, &box
);
1504 if(map_type
& D3D10_MAP_FLAG_DO_NOT_WAIT
)
1505 return DXGI_ERROR_WAS_STILL_DRAWING
;
1509 resource
->transfers
[subresource
] = transfer
;
1510 mapped_resource
->pData
= pipe
->transfer_map(pipe
, transfer
);
1511 mapped_resource
->RowPitch
= transfer
->stride
;
1512 mapped_resource
->DepthPitch
= transfer
->layer_stride
;
1516 virtual void STDMETHODCALLTYPE
Unmap(
1517 ID3D11Resource
*iresource
,
1518 unsigned subresource
)
1521 GalliumD3D11Resource
<>* resource
= (GalliumD3D11Resource
<>*)iresource
;
1522 std::unordered_map
<unsigned, pipe_transfer
*>::iterator i
= resource
->transfers
.find(subresource
);
1523 if(i
!= resource
->transfers
.end())
1525 pipe
->transfer_unmap(pipe
, i
->second
);
1526 pipe
->transfer_destroy(pipe
, i
->second
);
1527 resource
->transfers
.erase(i
);
1531 virtual void STDMETHODCALLTYPE
CopySubresourceRegion(
1532 ID3D11Resource
*dst_resource
,
1533 unsigned dst_subresource
,
1537 ID3D11Resource
*src_resource
,
1538 unsigned src_subresource
,
1539 const D3D11_BOX
*src_box
)
1542 GalliumD3D11Resource
<>* dst
= (GalliumD3D11Resource
<>*)dst_resource
;
1543 GalliumD3D11Resource
<>* src
= (GalliumD3D11Resource
<>*)src_resource
;
1544 unsigned dst_level
= d3d11_subresource_to_level(dst
->resource
, dst_subresource
);
1545 unsigned dst_face
= d3d11_subresource_to_face(dst
->resource
, dst_subresource
);
1546 unsigned src_level
= d3d11_subresource_to_level(src
->resource
, src_subresource
);
1547 unsigned src_face
= d3d11_subresource_to_face(src
->resource
, src_subresource
);
1548 /* XXX the translation from subresource to level/face(zslice/array layer) isn't quite right */
1549 pipe_box box
= d3d11_to_pipe_box(src
->resource
, src_level
, src_box
);
1551 pipe
->resource_copy_region(pipe
,
1552 dst
->resource
, dst_level
, dst_x
, dst_y
, dst_z
,
1553 src
->resource
, src_level
, &box
);
1557 virtual void STDMETHODCALLTYPE
CopyResource(
1558 ID3D11Resource
*dst_resource
,
1559 ID3D11Resource
*src_resource
)
1562 GalliumD3D11Resource
<>* dst
= (GalliumD3D11Resource
<>*)dst_resource
;
1563 GalliumD3D11Resource
<>* src
= (GalliumD3D11Resource
<>*)src_resource
;
1565 for(level
= 0; level
<= dst
->resource
->last_level
; ++level
)
1567 unsigned layers
= 1;
1569 if (dst
->resource
->target
== PIPE_TEXTURE_CUBE
)
1571 else if (dst
->resource
->target
== PIPE_TEXTURE_3D
)
1572 layers
= u_minify(dst
->resource
->depth0
, level
);
1573 /* else layers = dst->resource->array_size; */
1574 box
.x
= box
.y
= box
.z
= 0;
1575 box
.width
= u_minify(dst
->resource
->width0
, level
);
1576 box
.height
= u_minify(dst
->resource
->height0
, level
);
1578 pipe
->resource_copy_region(pipe
,
1579 dst
->resource
, level
, 0, 0, 0,
1580 src
->resource
, level
, &box
);
1584 virtual void STDMETHODCALLTYPE
UpdateSubresource(
1585 ID3D11Resource
*dst_resource
,
1586 unsigned dst_subresource
,
1587 const D3D11_BOX
*pDstBox
,
1588 const void *pSrcData
,
1589 unsigned src_row_pitch
,
1590 unsigned src_depth_pitch
)
1593 GalliumD3D11Resource
<>* dst
= (GalliumD3D11Resource
<>*)dst_resource
;
1594 unsigned dst_level
= d3d11_subresource_to_level(dst
->resource
, dst_subresource
);
1595 /* XXX the translation from subresource to level/face(zslice/array layer) isn't quite right */
1596 pipe_box box
= d3d11_to_pipe_box(dst
->resource
, dst_level
, pDstBox
);
1597 pipe
->transfer_inline_write(pipe
, dst
->resource
, dst_level
, PIPE_TRANSFER_WRITE
, &box
, pSrcData
, src_row_pitch
, src_depth_pitch
);
1601 virtual void STDMETHODCALLTYPE
CopyStructureCount(
1602 ID3D11Buffer
*dst_buffer
,
1603 unsigned dst_aligned_byte_offset
,
1604 ID3D11UnorderedAccessView
*src_view
)
1610 virtual void STDMETHODCALLTYPE
ClearRenderTargetView(
1611 ID3D11RenderTargetView
*render_target_view
,
1612 const float color
[4])
1615 GalliumD3D11RenderTargetView
* view
= ((GalliumD3D11RenderTargetView
*)render_target_view
);
1616 union pipe_color_union cc
;
1621 pipe
->clear_render_target(pipe
, view
->object
, &cc
, 0, 0, view
->object
->width
, view
->object
->height
);
1624 virtual void STDMETHODCALLTYPE
ClearDepthStencilView(
1625 ID3D11DepthStencilView
*depth_stencil_view
,
1626 unsigned clear_flags
,
1631 GalliumD3D11DepthStencilView
* view
= ((GalliumD3D11DepthStencilView
*)depth_stencil_view
);
1633 if(clear_flags
& D3D11_CLEAR_DEPTH
)
1634 flags
|= PIPE_CLEAR_DEPTH
;
1635 if(clear_flags
& D3D11_CLEAR_STENCIL
)
1636 flags
|= PIPE_CLEAR_STENCIL
;
1637 pipe
->clear_depth_stencil(pipe
, view
->object
, flags
, depth
, stencil
, 0, 0, view
->object
->width
, view
->object
->height
);
1641 virtual void STDMETHODCALLTYPE
ClearUnorderedAccessViewUint(
1642 ID3D11UnorderedAccessView
*unordered_access_view
,
1643 const unsigned values
[4])
1648 virtual void STDMETHODCALLTYPE
ClearUnorderedAccessViewFloat(
1649 ID3D11UnorderedAccessView
*unordered_access_view
,
1650 const float values
[4])
1656 void restore_gallium_state_blit_only()
1658 pipe
->bind_blend_state(pipe
, blend_state
.p
? blend_state
.p
->object
: default_blend
);
1659 pipe
->bind_depth_stencil_alpha_state(pipe
, depth_stencil_state
.p
? depth_stencil_state
.p
->object
: default_depth_stencil
);
1660 pipe
->bind_rasterizer_state(pipe
, rasterizer_state
.p
? rasterizer_state
.p
->object
: default_rasterizer
);
1661 pipe
->bind_vertex_elements_state(pipe
, input_layout
.p
? input_layout
.p
->object
: default_input_layout
);
1662 pipe
->bind_fs_state(pipe
, shaders
[D3D11_STAGE_PS
].p
? shaders
[D3D11_STAGE_PS
].p
->object
: default_shaders
[PIPE_SHADER_FRAGMENT
]);
1663 pipe
->bind_vs_state(pipe
, shaders
[D3D11_STAGE_VS
].p
? shaders
[D3D11_STAGE_VS
].p
->object
: default_shaders
[PIPE_SHADER_VERTEX
]);
1665 pipe
->bind_gs_state(pipe
, shaders
[D3D11_STAGE_GS
].p
? shaders
[D3D11_STAGE_GS
].p
->object
: default_shaders
[PIPE_SHADER_GEOMETRY
]);
1669 set_render_condition();
1670 // TODO: restore stream output
1672 update_flags
|= UPDATE_VERTEX_BUFFERS
| (1 << (UPDATE_SAMPLERS_SHIFT
+ D3D11_STAGE_PS
)) | (1 << (UPDATE_VIEWS_SHIFT
+ D3D11_STAGE_PS
));
1675 virtual void STDMETHODCALLTYPE
RestoreGalliumStateBlitOnly()
1678 restore_gallium_state_blit_only();
1681 virtual void STDMETHODCALLTYPE
GenerateMips(
1682 ID3D11ShaderResourceView
*shader_resource_view
)
1686 GalliumD3D11ShaderResourceView
* view
= (GalliumD3D11ShaderResourceView
*)shader_resource_view
;
1688 pipe
->bind_gs_state(pipe
, 0);
1690 pipe
->bind_stream_output_state(pipe
, 0);
1691 if(pipe
->render_condition
)
1692 pipe
->render_condition(pipe
, 0, 0);
1693 util_gen_mipmap(gen_mipmap
, view
->object
, 0, 0, view
->object
->texture
->last_level
, PIPE_TEX_FILTER_LINEAR
);
1694 restore_gallium_state_blit_only();
1697 virtual void STDMETHODCALLTYPE
RestoreGalliumState()
1700 restore_gallium_state_blit_only();
1704 pipe
->set_blend_color(pipe
, (struct pipe_blend_color
*)blend_color
);
1705 pipe
->set_sample_mask(pipe
, sample_mask
);
1707 for(unsigned s
= 0; s
< 3; ++s
)
1709 unsigned num
= std::min(caps
.constant_buffers
[s
], (unsigned)D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
);
1710 for(unsigned i
= 0; i
< num
; ++i
)
1711 pipe
->set_constant_buffer(pipe
, s
, i
, constant_buffers
[s
][i
].p
? constant_buffers
[s
][i
].p
->resource
: 0);
1715 pipe
->set_stream_output_buffers(pipe
, so_buffers
, (int*)so_offsets
, num_so_targets
);
1717 update_flags
|= (1 << (UPDATE_SAMPLERS_SHIFT
+ D3D11_STAGE_VS
)) | (1 << (UPDATE_VIEWS_SHIFT
+ D3D11_STAGE_VS
));
1718 update_flags
|= (1 << (UPDATE_SAMPLERS_SHIFT
+ D3D11_STAGE_GS
)) | (1 << (UPDATE_VIEWS_SHIFT
+ D3D11_STAGE_GS
));
1724 /* TODO: hack SRVs or sampler states to handle this, or add to Gallium */
1725 virtual void STDMETHODCALLTYPE
SetResourceMinLOD(
1726 ID3D11Resource
*iresource
,
1730 GalliumD3D11Resource
<>* resource
= (GalliumD3D11Resource
<>*)iresource
;
1731 if(resource
->min_lod
!= min_lod
)
1733 // TODO: actually do anything?
1734 resource
->min_lod
= min_lod
;
1738 virtual float STDMETHODCALLTYPE
GetResourceMinLOD(
1739 ID3D11Resource
*iresource
)
1742 GalliumD3D11Resource
<>* resource
= (GalliumD3D11Resource
<>*)iresource
;
1743 return resource
->min_lod
;
1747 virtual void STDMETHODCALLTYPE
ResolveSubresource(
1748 ID3D11Resource
*dst_resource
,
1749 unsigned dst_subresource
,
1750 ID3D11Resource
*src_resource
,
1751 unsigned src_subresource
,
1755 GalliumD3D11Resource
<>* dst
= (GalliumD3D11Resource
<>*)dst_resource
;
1756 GalliumD3D11Resource
<>* src
= (GalliumD3D11Resource
<>*)src_resource
;
1757 struct pipe_resolve_info info
;
1759 info
.dst
.res
= dst
->resource
;
1760 info
.src
.res
= src
->resource
;
1762 info
.dst
.layer
= d3d11_subresource_to_face(dst
->resource
, dst_subresource
);
1763 info
.src
.layer
= d3d11_subresource_to_face(src
->resource
, src_subresource
);
1766 info
.src
.x1
= info
.src
.res
->width0
;
1768 info
.src
.y1
= info
.src
.res
->height0
;
1770 info
.dst
.x1
= info
.dst
.res
->width0
;
1772 info
.dst
.y1
= info
.dst
.res
->height0
;
1774 info
.mask
= PIPE_MASK_RGBA
| PIPE_MASK_ZS
;
1776 pipe
->resource_resolve(pipe
, &info
);
1780 virtual void STDMETHODCALLTYPE
ExecuteCommandList(
1781 ID3D11CommandList
*command_list
,
1782 BOOL restore_context_state
)
1787 virtual HRESULT STDMETHODCALLTYPE
FinishCommandList(
1788 BOOL restore_deferred_context_state
,
1789 ID3D11CommandList
**out_command_list
)
1796 virtual void STDMETHODCALLTYPE
ClearState(void)
1798 /* we don't take a lock here because we would deadlock otherwise
1799 * TODO: this is probably incorrect, because ClearState should likely be atomic.
1800 * However, I can't think of any correct usage that would be affected by this
1801 * being non-atomic, and making this atomic is quite expensive and complicates
1805 // we qualify all calls so that we avoid virtual dispatch and might get them inlined
1806 // TODO: make sure all this gets inlined, which might require more compiler flags
1807 // TODO: optimize this
1809 GalliumD3D11DeviceContext::PSSetShader(0, 0, 0);
1810 GalliumD3D11DeviceContext::GSSetShader(0, 0, 0);
1811 GalliumD3D11DeviceContext::VSSetShader(0, 0, 0);
1812 GalliumD3D11DeviceContext::HSSetShader(0, 0, 0);
1813 GalliumD3D11DeviceContext::DSSetShader(0, 0, 0);
1814 GalliumD3D11DeviceContext::CSSetShader(0, 0, 0);
1816 GalliumD3D11DeviceContext::PSSetShader(0);
1817 GalliumD3D11DeviceContext::GSSetShader(0);
1818 GalliumD3D11DeviceContext::VSSetShader(0);
1821 GalliumD3D11DeviceContext::IASetInputLayout(0);
1822 GalliumD3D11DeviceContext::IASetIndexBuffer(0, DXGI_FORMAT_UNKNOWN
, 0);
1823 GalliumD3D11DeviceContext::RSSetState(0);
1824 GalliumD3D11DeviceContext::OMSetDepthStencilState(0, 0);
1825 GalliumD3D11DeviceContext::OMSetBlendState(0, (float*)zero_data
, ~0);
1826 GalliumD3D11DeviceContext::SetPredication(0, 0);
1827 GalliumD3D11DeviceContext::IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED
);
1829 GalliumD3D11DeviceContext::PSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
, (ID3D11Buffer
**)zero_data
);
1830 GalliumD3D11DeviceContext::GSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
, (ID3D11Buffer
**)zero_data
);
1831 GalliumD3D11DeviceContext::VSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
, (ID3D11Buffer
**)zero_data
);
1833 GalliumD3D11DeviceContext::HSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
, (ID3D11Buffer
**)zero_data
);
1834 GalliumD3D11DeviceContext::DSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
, (ID3D11Buffer
**)zero_data
);
1835 GalliumD3D11DeviceContext::CSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
, (ID3D11Buffer
**)zero_data
);
1838 GalliumD3D11DeviceContext::IASetVertexBuffers(0, num_vertex_buffers
, (ID3D11Buffer
**)zero_data
, (unsigned*)zero_data
, (unsigned*)zero_data
);
1840 GalliumD3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews(0, 0, 0 , 0, 0, 0, 0);
1842 GalliumD3D11DeviceContext::OMSetRenderTargets(0, 0, 0 );
1844 GalliumD3D11DeviceContext::SOSetTargets(0, 0, 0);
1846 GalliumD3D11DeviceContext::PSSetShaderResources(0, num_shader_resource_views
[D3D11_STAGE_PS
], (ID3D11ShaderResourceView
**)zero_data
);
1847 GalliumD3D11DeviceContext::GSSetShaderResources(0, num_shader_resource_views
[D3D11_STAGE_GS
], (ID3D11ShaderResourceView
**)zero_data
);
1848 GalliumD3D11DeviceContext::VSSetShaderResources(0, num_shader_resource_views
[D3D11_STAGE_VS
], (ID3D11ShaderResourceView
**)zero_data
);
1850 GalliumD3D11DeviceContext::HSSetShaderResources(0, num_shader_resource_views
[D3D11_STAGE_HS
], (ID3D11ShaderResourceView
**)zero_data
);
1851 GalliumD3D11DeviceContext::DSSetShaderResources(0, num_shader_resource_views
[D3D11_STAGE_DS
], (ID3D11ShaderResourceView
**)zero_data
);
1852 GalliumD3D11DeviceContext::CSSetShaderResources(0, num_shader_resource_views
[D3D11_STAGE_CS
], (ID3D11ShaderResourceView
**)zero_data
);
1855 GalliumD3D11DeviceContext::PSSetSamplers(0, num_shader_resource_views
[D3D11_STAGE_PS
], (ID3D11SamplerState
**)zero_data
);
1856 GalliumD3D11DeviceContext::GSSetSamplers(0, num_shader_resource_views
[D3D11_STAGE_GS
], (ID3D11SamplerState
**)zero_data
);
1857 GalliumD3D11DeviceContext::VSSetSamplers(0, num_shader_resource_views
[D3D11_STAGE_VS
], (ID3D11SamplerState
**)zero_data
);
1859 GalliumD3D11DeviceContext::HSSetSamplers(0, num_shader_resource_views
[D3D11_STAGE_HS
], (ID3D11SamplerState
**)zero_data
);
1860 GalliumD3D11DeviceContext::DSSetSamplers(0, num_shader_resource_views
[D3D11_STAGE_DS
], (ID3D11SamplerState
**)zero_data
);
1861 GalliumD3D11DeviceContext::CSSetSamplers(0, num_shader_resource_views
[D3D11_STAGE_CS
], (ID3D11SamplerState
**)zero_data
);
1864 GalliumD3D11DeviceContext::RSSetViewports(0, 0);
1865 GalliumD3D11DeviceContext::RSSetScissorRects(0, 0);
1868 virtual void STDMETHODCALLTYPE
Flush(void)
1871 pipe
->flush(pipe
, 0);
1874 /* In Direct3D 10, if the reference count of an object drops to 0, it is automatically
1875 * cleanly unbound from the pipeline.
1876 * In Direct3D 11, the pipeline holds a reference.
1878 * Note that instead of always scanning the pipeline on destruction, we could
1879 * maintain the internal reference count on DirectX 10 and use it to check if an
1880 * object is still bound.
1881 * Presumably, on average, scanning is faster if the application is well written.
1884 #define IMPLEMENT_SIMPLE_UNBIND(name, member, gallium, def) \
1885 void Unbind##name(ID3D11##name* state) \
1888 if((void*)state == (void*)member.p) \
1891 pipe->bind_##gallium##_state(pipe, default_##def); \
1894 IMPLEMENT_SIMPLE_UNBIND(BlendState
, blend_state
, blend
, blend
)
1895 IMPLEMENT_SIMPLE_UNBIND(RasterizerState
, rasterizer_state
, rasterizer
, rasterizer
)
1896 IMPLEMENT_SIMPLE_UNBIND(DepthStencilState
, depth_stencil_state
, depth_stencil_alpha
, depth_stencil
)
1897 IMPLEMENT_SIMPLE_UNBIND(InputLayout
, input_layout
, vertex_elements
, input_layout
)
1898 IMPLEMENT_SIMPLE_UNBIND(PixelShader
, shaders
[D3D11_STAGE_PS
], fs
, shaders
[D3D11_STAGE_PS
])
1899 IMPLEMENT_SIMPLE_UNBIND(VertexShader
, shaders
[D3D11_STAGE_VS
], vs
, shaders
[D3D11_STAGE_VS
])
1900 IMPLEMENT_SIMPLE_UNBIND(GeometryShader
, shaders
[D3D11_STAGE_GS
], gs
, shaders
[D3D11_STAGE_GS
])
1902 void UnbindPredicate(ID3D11Predicate
* predicate
)
1905 if(predicate
== render_predicate
)
1907 render_predicate
.p
= NULL
;
1908 render_predicate_value
= 0;
1909 pipe
->render_condition(pipe
, 0, 0);
1913 void UnbindSamplerState(ID3D11SamplerState
* state
)
1916 for(unsigned s
= 0; s
< D3D11_STAGES
; ++s
)
1918 for(unsigned i
= 0; i
< num_samplers
[s
]; ++i
)
1920 if(samplers
[s
][i
] == state
)
1922 samplers
[s
][i
].p
= NULL
;
1923 sampler_csos
[s
].v
[i
] = NULL
;
1924 update_flags
|= (1 << (UPDATE_SAMPLERS_SHIFT
+ s
));
1930 void UnbindBuffer(ID3D11Buffer
* buffer
)
1933 if(buffer
== index_buffer
)
1936 index_format
= DXGI_FORMAT_UNKNOWN
;
1938 struct pipe_index_buffer ib
;
1939 memset(&ib
, 0, sizeof(ib
));
1940 pipe
->set_index_buffer(pipe
, &ib
);
1943 for(unsigned i
= 0; i
< num_vertex_buffers
; ++i
)
1945 if(buffer
== input_buffers
[i
])
1947 input_buffers
[i
].p
= 0;
1948 memset(&vertex_buffers
[num_vertex_buffers
], 0, sizeof(vertex_buffers
[num_vertex_buffers
]));
1949 update_flags
|= UPDATE_VERTEX_BUFFERS
;
1953 for(unsigned s
= 0; s
< D3D11_STAGES
; ++s
)
1955 for(unsigned i
= 0; i
< sizeof(constant_buffers
) / sizeof(constant_buffers
[0]); ++i
)
1957 if(constant_buffers
[s
][i
] == buffer
)
1959 constant_buffers
[s
][i
] = (ID3D10Buffer
*)NULL
;
1960 pipe
->set_constant_buffer(pipe
, s
, i
, NULL
);
1966 void UnbindDepthStencilView(ID3D11DepthStencilView
* view
)
1969 if(view
== depth_stencil_view
)
1971 depth_stencil_view
.p
= NULL
;
1976 void UnbindRenderTargetView(ID3D11RenderTargetView
* view
)
1979 bool any_bound
= false;
1980 for(unsigned i
= 0; i
< num_render_target_views
; ++i
)
1982 if(render_target_views
[i
] == view
)
1984 render_target_views
[i
].p
= NULL
;
1992 void UnbindShaderResourceView(ID3D11ShaderResourceView
* view
)
1995 for(unsigned s
= 0; s
< D3D11_STAGES
; ++s
)
1997 for(unsigned i
= 0; i
< num_shader_resource_views
[s
]; ++i
)
1999 if(shader_resource_views
[s
][i
] == view
)
2001 shader_resource_views
[s
][i
].p
= NULL
;
2002 sampler_views
[s
][i
] = NULL
;
2003 update_flags
|= (1 << (UPDATE_VIEWS_SHIFT
+ s
));
2014 /* This approach serves two purposes.
2015 * First, we don't want to do an atomic operation to manipulate the reference
2016 * count every time something is bound/unbound to the pipeline, since they are
2018 * Fortunately, the immediate context can only be used by a single thread, so
2019 * we don't have to use them, as long as a separate reference count is used
2020 * (see dual_refcnt_t).
2022 * Second, we want to avoid the Device -> DeviceContext -> bound DeviceChild -> Device
2024 * To avoid it, DeviceChild doesn't hold a reference to Device as usual, but adds
2025 * one for each external reference count, while internal nonatomic_add_ref doesn't
2028 * Note that ideally we would to eliminate the non-atomic op too, but this is more
2029 * complicated, since we would either need to use garbage collection and give up
2030 * deterministic destruction (especially bad for large textures), or scan the whole
2031 * pipeline state every time the reference count of object drops to 0, which risks
2032 * pathological slowdowns.
2034 * Since this microoptimization should matter relatively little, let's avoid it for now.
2036 * Note that deferred contexts don't use this, since as a whole, they must thread-safe.
2037 * Eliminating the atomic ops for deferred contexts seems substantially harder.
2038 * This might be a problem if they are used in a one-shot multithreaded rendering
2039 * fashion, where SMP cacheline bouncing on the reference count may be visible.
2041 * The idea would be to attach a structure of reference counts indexed by deferred
2042 * context id to each object. Ideally, this should be organized like ext2 block pointers.
2044 * Every deferred context would get a reference count in its own cacheline.
2045 * The external count is protected by a lock bit, and there is also a "lock bit" in each
2048 * When the external count has to be dropped to 0, the lock bit is taken and all internal
2049 * reference counts are scanned, taking a count of them. A flag would also be set on them.
2050 * Deferred context manipulation would notice the flag, and update the count.
2051 * Once the count goes to zero, the object is freed.
2053 * The problem of this is that if the external reference count ping-pongs between
2054 * zero and non-zero, the scans will take a lot of time.
2056 * The idea to solve this is to compute the scans in a binary-tree like fashion, where
2057 * each binary tree node would have a "determined bit", which would be invalidated
2060 * However, all this complexity might actually be a loss in most cases, so let's just
2061 * stick to a single atomic refcnt for now.
2063 * Also, we don't even support deferred contexts yet, so this can wait.
2065 struct nonatomic_device_child_ptr_traits
2067 static void add_ref(void* p
)
2070 ((GalliumD3D11DeviceChild
<>*)p
)->nonatomic_add_ref();
2073 static void release(void* p
)
2076 ((GalliumD3D11DeviceChild
<>*)p
)->nonatomic_release();
2080 struct GalliumD3D11ImmediateDeviceContext
2081 : public GalliumD3D11DeviceContext
<nonatomic_device_child_ptr_traits
>
2083 GalliumD3D11ImmediateDeviceContext(GalliumD3D11Screen
* device
, pipe_context
* pipe
, unsigned context_flags
= 0)
2084 : GalliumD3D11DeviceContext
<nonatomic_device_child_ptr_traits
>(device
, pipe
, context_flags
)
2086 // not necessary, but tests that the API at least basically works
2090 /* we do this since otherwise we would have a garbage cycle between this and the device */
2091 virtual ULONG STDMETHODCALLTYPE
AddRef()
2093 return this->device
->AddRef();
2096 virtual ULONG STDMETHODCALLTYPE
Release()
2098 return this->device
->Release();
2101 virtual D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE
GetType()
2103 return D3D11_DEVICE_CONTEXT_IMMEDIATE
;
2107 static ID3D11DeviceContext
* GalliumD3D11ImmediateDeviceContext_Create(GalliumD3D11Screen
* device
, struct pipe_context
* pipe
, bool owns_pipe
)
2109 return new GalliumD3D11ImmediateDeviceContext(device
, pipe
, owns_pipe
);
2112 static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(ID3D11DeviceContext
* context
)
2114 ((GalliumD3D11ImmediateDeviceContext
*)context
)->RestoreGalliumState();
2117 static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(ID3D11DeviceContext
* context
)
2119 ((GalliumD3D11ImmediateDeviceContext
*)context
)->RestoreGalliumStateBlitOnly();
2122 static void GalliumD3D11ImmediateDeviceContext_Destroy(ID3D11DeviceContext
* context
)
2124 delete (GalliumD3D11ImmediateDeviceContext
*)context
;