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 /* used to unbind things, we need 128 due to resources */ 28 static const void* zero_data[128]; 29 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)) 33 34 #if API >= 11 35 template<typename PtrTraits> 36 struct GalliumD3D11DeviceContext : 37 public GalliumD3D11DeviceChild<ID3D11DeviceContext> 38 { 39 #else 40 template<bool threadsafe> 41 struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe> 42 { 43 typedef simple_ptr_traits PtrTraits; 44 typedef GalliumD3D10Device GalliumD3D10DeviceContext; 45 #endif 46 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; 55 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_buffers[D3D11_SO_BUFFER_SLOT_COUNT]; 62 63 #if API >= 11 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]; 66 #endif 67 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 D3D11_PRIMITIVE_TOPOLOGY primitive_topology; 71 DXGI_FORMAT index_format; 72 unsigned index_offset; 73 uint32_t strip_cut_index; 74 BOOL render_predicate_value; 75 float blend_color[4]; 76 unsigned sample_mask; 77 unsigned stencil_ref; 78 79 void* default_input_layout; 80 void* default_rasterizer; 81 void* default_depth_stencil; 82 void* default_blend; 83 void* default_sampler; 84 void* default_shaders[D3D11_STAGES]; 85 86 // derived state 87 int primitive_mode; 88 struct pipe_vertex_buffer vertex_buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; 89 struct pipe_stream_output_target* so_targets[D3D11_SO_BUFFER_SLOT_COUNT]; 90 struct pipe_sampler_view* sampler_views[D3D11_STAGES][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; 91 void* sampler_csos[D3D11_STAGES][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; 92 unsigned num_shader_resource_views[D3D11_STAGES]; 93 unsigned num_samplers[D3D11_STAGES]; 94 unsigned num_vertex_buffers; 95 unsigned num_render_target_views; 96 unsigned num_viewports; 97 unsigned num_scissor_rects; 98 unsigned num_so_targets; 99 100 struct pipe_context* pipe; 101 unsigned update_flags; 102 103 bool owns_pipe; 104 unsigned context_flags; 105 106 GalliumD3D11Caps caps; 107 108 cso_context* cso_ctx; 109 gen_mipmap_state* gen_mipmap; 110 111 #if API >= 11 112 #define SYNCHRONIZED do {} while(0) 113 114 GalliumD3D11DeviceContext(GalliumD3D11Screen* device, pipe_context* pipe, bool owns_pipe, unsigned context_flags = 0) 115 : GalliumD3D11DeviceChild<ID3D11DeviceContext>(device), pipe(pipe), owns_pipe(owns_pipe), context_flags(context_flags) 116 { 117 caps = device->screen_caps; 118 init_context(); 119 } 120 121 ~GalliumD3D11DeviceContext() 122 { 123 destroy_context(); 124 } 125 #else 126 #define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(this->mutex) 127 128 GalliumD3D10Device(pipe_screen* screen, pipe_context* pipe, bool owns_pipe, unsigned creation_flags, IDXGIAdapter* adapter) 129 : GalliumD3D10ScreenImpl<threadsafe>(screen, pipe, owns_pipe, creation_flags, adapter), pipe(pipe), owns_pipe(owns_pipe), context_flags(0) 130 { 131 caps = this->screen_caps; 132 init_context(); 133 } 134 135 ~GalliumD3D10Device() 136 { 137 destroy_context(); 138 } 139 #endif 140 141 void init_context() 142 { 143 if(!pipe->begin_query) 144 caps.queries = false; 145 if(!pipe->bind_gs_state) 146 { 147 caps.gs = false; 148 caps.stages = 2; 149 } 150 assert(!caps.so || pipe->set_stream_output_targets); 151 if(!pipe->set_geometry_sampler_views) 152 caps.stages_with_sampling &=~ (1 << PIPE_SHADER_GEOMETRY); 153 if(!pipe->set_fragment_sampler_views) 154 caps.stages_with_sampling &=~ (1 << PIPE_SHADER_FRAGMENT); 155 if(!pipe->set_vertex_sampler_views) 156 caps.stages_with_sampling &=~ (1 << PIPE_SHADER_VERTEX); 157 158 update_flags = 0; 159 160 // pipeline state 161 memset(viewports, 0, sizeof(viewports)); 162 memset(scissor_rects, 0, sizeof(scissor_rects)); 163 primitive_topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; 164 index_format = DXGI_FORMAT_UNKNOWN; 165 index_offset = 0; 166 strip_cut_index = 0xffffffff; 167 render_predicate_value = 0; 168 memset(blend_color, 0, sizeof(blend_color)); 169 sample_mask = ~0; 170 stencil_ref = 0; 171 172 // derived state 173 primitive_mode = 0; 174 memset(vertex_buffers, 0, sizeof(vertex_buffers)); 175 memset(so_targets, 0, sizeof(so_buffers)); 176 memset(sampler_views, 0, sizeof(sampler_views)); 177 memset(sampler_csos, 0, sizeof(sampler_csos)); 178 memset(num_shader_resource_views, 0, sizeof(num_shader_resource_views)); 179 memset(num_samplers, 0, sizeof(num_samplers)); 180 num_vertex_buffers = 0; 181 num_render_target_views = 0; 182 num_viewports = 0; 183 num_scissor_rects = 0; 184 num_so_targets = 0; 185 186 default_input_layout = pipe->create_vertex_elements_state(pipe, 0, 0); 187 188 struct pipe_rasterizer_state rasterizerd; 189 memset(&rasterizerd, 0, sizeof(rasterizerd)); 190 rasterizerd.gl_rasterization_rules = 1; 191 rasterizerd.cull_face = PIPE_FACE_BACK; 192 rasterizerd.flatshade_first = 1; 193 rasterizerd.line_width = 1.0f; 194 rasterizerd.point_size = 1.0f; 195 rasterizerd.depth_clip = TRUE; 196 default_rasterizer = pipe->create_rasterizer_state(pipe, &rasterizerd); 197 198 struct pipe_depth_stencil_alpha_state depth_stencild; 199 memset(&depth_stencild, 0, sizeof(depth_stencild)); 200 depth_stencild.depth.enabled = TRUE; 201 depth_stencild.depth.writemask = 1; 202 depth_stencild.depth.func = PIPE_FUNC_LESS; 203 default_depth_stencil = pipe->create_depth_stencil_alpha_state(pipe, &depth_stencild); 204 205 struct pipe_blend_state blendd; 206 memset(&blendd, 0, sizeof(blendd)); 207 blendd.rt[0].colormask = 0xf; 208 default_blend = pipe->create_blend_state(pipe, &blendd); 209 210 struct pipe_sampler_state samplerd; 211 memset(&samplerd, 0, sizeof(samplerd)); 212 samplerd.normalized_coords = 1; 213 samplerd.min_img_filter = PIPE_TEX_FILTER_LINEAR; 214 samplerd.mag_img_filter = PIPE_TEX_FILTER_LINEAR; 215 samplerd.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR; 216 samplerd.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 217 samplerd.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 218 samplerd.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 219 samplerd.border_color.f[0] = 1.0f; 220 samplerd.border_color.f[1] = 1.0f; 221 samplerd.border_color.f[2] = 1.0f; 222 samplerd.border_color.f[3] = 1.0f; 223 samplerd.min_lod = -FLT_MAX; 224 samplerd.max_lod = FLT_MAX; 225 samplerd.max_anisotropy = 1; 226 default_sampler = pipe->create_sampler_state(pipe, &samplerd); 227 228 memset(&samplerd, 0, sizeof(samplerd)); 229 samplerd.normalized_coords = 0; 230 samplerd.min_img_filter = PIPE_TEX_FILTER_NEAREST; 231 samplerd.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 232 samplerd.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 233 samplerd.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER; 234 samplerd.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER; 235 samplerd.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER; 236 samplerd.min_lod = -FLT_MAX; 237 samplerd.max_lod = FLT_MAX; 238 samplerd.max_anisotropy = 1; 239 240 for(unsigned s = 0; s < D3D11_STAGES; ++s) 241 for(unsigned i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i) 242 sampler_csos[s][i] = default_sampler; 243 244 // TODO: should this really be empty shaders, or should they be all-passthrough? 245 memset(default_shaders, 0, sizeof(default_shaders)); 246 struct ureg_program *ureg; 247 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); 248 ureg_END(ureg); 249 default_shaders[PIPE_SHADER_FRAGMENT] = ureg_create_shader_and_destroy(ureg, pipe); 250 251 ureg = ureg_create(TGSI_PROCESSOR_VERTEX); 252 ureg_END(ureg); 253 default_shaders[PIPE_SHADER_VERTEX] = ureg_create_shader_and_destroy(ureg, pipe); 254 255 cso_ctx = cso_create_context(pipe); 256 gen_mipmap = util_create_gen_mipmap(pipe, cso_ctx); 257 258 RestoreGalliumState(); 259 } 260 261 void destroy_context() 262 { 263 util_destroy_gen_mipmap(gen_mipmap); 264 cso_destroy_context(cso_ctx); 265 266 pipe->bind_vertex_elements_state(pipe, 0); 267 pipe->delete_vertex_elements_state(pipe, default_input_layout); 268 269 pipe->bind_rasterizer_state(pipe, 0); 270 pipe->delete_rasterizer_state(pipe, default_rasterizer); 271 272 pipe->bind_depth_stencil_alpha_state(pipe, 0); 273 pipe->delete_depth_stencil_alpha_state(pipe, default_depth_stencil); 274 275 pipe->bind_blend_state(pipe, 0); 276 pipe->delete_blend_state(pipe, default_blend); 277 278 pipe->bind_fragment_sampler_states(pipe, 0, 0); 279 pipe->bind_vertex_sampler_states(pipe, 0, 0); 280 if(pipe->bind_geometry_sampler_states) 281 pipe->bind_geometry_sampler_states(pipe, 0, 0); 282 pipe->delete_sampler_state(pipe, default_sampler); 283 284 pipe->bind_fs_state(pipe, 0); 285 pipe->delete_fs_state(pipe, default_shaders[PIPE_SHADER_FRAGMENT]); 286 287 pipe->bind_vs_state(pipe, 0); 288 pipe->delete_vs_state(pipe, default_shaders[PIPE_SHADER_VERTEX]); 289 290 if(owns_pipe) 291 pipe->destroy(pipe); 292 } 293 294 virtual unsigned STDMETHODCALLTYPE GetContextFlags(void) 295 { 296 return context_flags; 297 } 298 #if API >= 11 299 #define SET_SHADER_EXTRA_ARGS , \ 300 ID3D11ClassInstance *const *ppClassInstances, \ 301 unsigned count 302 #define GET_SHADER_EXTRA_ARGS , \ 303 ID3D11ClassInstance **ppClassInstances, \ 304 unsigned *out_count 305 #else 306 #define SET_SHADER_EXTRA_ARGS 307 #define GET_SHADER_EXTRA_ARGS 308 #endif 309 310 /* On Windows D3D11, SetConstantBuffers and SetShaderResources crash if passed a null pointer. 311 * Instead, you have to pass a pointer to nulls to unbind things. 312 * We do the same. 313 * TODO: is D3D10 the same? 314 */ 315 template<unsigned s> 316 void xs_set_shader(GalliumD3D11Shader<>* shader) 317 { 318 if(shader != shaders[s].p) 319 { 320 shaders[s] = shader; 321 void* shader_cso = shader ? shader->object : default_shaders[s]; 322 switch(s) 323 { 324 case PIPE_SHADER_VERTEX: 325 pipe->bind_vs_state(pipe, shader_cso); 326 break; 327 case PIPE_SHADER_FRAGMENT: 328 pipe->bind_fs_state(pipe, shader_cso); 329 break; 330 case PIPE_SHADER_GEOMETRY: 331 pipe->bind_gs_state(pipe, shader_cso); 332 break; 333 } 334 update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + s)) | (1 << (UPDATE_VIEWS_SHIFT + s)); 335 } 336 } 337 338 template<unsigned s> 339 void xs_set_constant_buffers(unsigned start, unsigned count, GalliumD3D11Buffer *const *constbufs) 340 { 341 for(unsigned i = 0; i < count; ++i) 342 { 343 if(constbufs[i] != constant_buffers[s][start + i].p) 344 { 345 constant_buffers[s][start + i] = constbufs[i]; 346 if(s < caps.stages && start + i < caps.constant_buffers[s]) 347 pipe_set_constant_buffer(pipe, s, start + i, constbufs[i] ? constbufs[i]->resource : NULL); 348 } 349 } 350 } 351 352 template<unsigned s> 353 void xs_set_shader_resources(unsigned start, unsigned count, GalliumD3D11ShaderResourceView *const *srvs) 354 { 355 int last_different = -1; 356 for(unsigned i = 0; i < count; ++i) 357 { 358 if(shader_resource_views[s][start + i].p != srvs[i]) 359 { 360 shader_resource_views[s][start + i] = srvs[i]; 361 sampler_views[s][start + i] = srvs[i] ? srvs[i]->object : 0; 362 last_different = i; 363 } 364 } 365 if(last_different >= 0) 366 { 367 num_shader_resource_views[s] = std::max(num_shader_resource_views[s], start + last_different + 1); 368 update_flags |= 1 << (UPDATE_VIEWS_SHIFT + s); 369 } 370 } 371 372 template<unsigned s> 373 void xs_set_samplers(unsigned start, unsigned count, GalliumD3D11SamplerState *const *samps) 374 { 375 int last_different = -1; 376 for(unsigned i = 0; i < count; ++i) 377 { 378 if(samplers[s][start + i].p != samps[i]) 379 { 380 samplers[s][start + i] = samps[i]; 381 sampler_csos[s][start + i] = samps[i] ? samps[i]->object : default_sampler; 382 last_different = i; 383 } 384 } 385 if(last_different >= 0) 386 { 387 num_samplers[s] = std::max(num_samplers[s], start + last_different + 1); 388 update_flags |= 1 << (UPDATE_SAMPLERS_SHIFT + s); 389 } 390 } 391 392 #define IMPLEMENT_SHADER_STAGE(XS, Stage) \ 393 virtual void STDMETHODCALLTYPE XS##SetShader( \ 394 ID3D11##Stage##Shader *pShader \ 395 SET_SHADER_EXTRA_ARGS) \ 396 { \ 397 SYNCHRONIZED; \ 398 xs_set_shader<D3D11_STAGE_##XS>((GalliumD3D11Shader<>*)pShader); \ 399 } \ 400 virtual void STDMETHODCALLTYPE XS##GetShader(\ 401 ID3D11##Stage##Shader **ppShader \ 402 GET_SHADER_EXTRA_ARGS) \ 403 { \ 404 SYNCHRONIZED; \ 405 *ppShader = (ID3D11##Stage##Shader*)shaders[D3D11_STAGE_##XS].ref(); \ 406 } \ 407 virtual void STDMETHODCALLTYPE XS##SetConstantBuffers(\ 408 unsigned start, \ 409 unsigned count, \ 410 ID3D11Buffer *const* constant_buffers) \ 411 { \ 412 SYNCHRONIZED; \ 413 xs_set_constant_buffers<D3D11_STAGE_##XS>(start, count, (GalliumD3D11Buffer *const *)constant_buffers); \ 414 } \ 415 virtual void STDMETHODCALLTYPE XS##GetConstantBuffers(\ 416 unsigned start, \ 417 unsigned count, \ 418 ID3D11Buffer **out_constant_buffers) \ 419 { \ 420 SYNCHRONIZED; \ 421 for(unsigned i = 0; i < count; ++i) \ 422 out_constant_buffers[i] = constant_buffers[D3D11_STAGE_##XS][start + i].ref(); \ 423 } \ 424 virtual void STDMETHODCALLTYPE XS##SetShaderResources(\ 425 unsigned start, \ 426 unsigned count, \ 427 ID3D11ShaderResourceView *const *new_shader_resource_views) \ 428 { \ 429 SYNCHRONIZED; \ 430 xs_set_shader_resources<D3D11_STAGE_##XS>(start, count, (GalliumD3D11ShaderResourceView *const *)new_shader_resource_views); \ 431 } \ 432 virtual void STDMETHODCALLTYPE XS##GetShaderResources(\ 433 unsigned start, \ 434 unsigned count, \ 435 ID3D11ShaderResourceView **out_shader_resource_views) \ 436 { \ 437 SYNCHRONIZED; \ 438 for(unsigned i = 0; i < count; ++i) \ 439 out_shader_resource_views[i] = shader_resource_views[D3D11_STAGE_##XS][start + i].ref(); \ 440 } \ 441 virtual void STDMETHODCALLTYPE XS##SetSamplers(\ 442 unsigned start, \ 443 unsigned count, \ 444 ID3D11SamplerState *const *new_samplers) \ 445 { \ 446 SYNCHRONIZED; \ 447 xs_set_samplers<D3D11_STAGE_##XS>(start, count, (GalliumD3D11SamplerState *const *)new_samplers); \ 448 } \ 449 virtual void STDMETHODCALLTYPE XS##GetSamplers( \ 450 unsigned start, \ 451 unsigned count, \ 452 ID3D11SamplerState **out_samplers) \ 453 { \ 454 SYNCHRONIZED; \ 455 for(unsigned i = 0; i < count; ++i) \ 456 out_samplers[i] = samplers[D3D11_STAGE_##XS][start + i].ref(); \ 457 } 458 459 #define DO_VS(x) x 460 #define DO_GS(x) do {if(caps.gs) {x;}} while(0) 461 #define DO_PS(x) x 462 #define DO_HS(x) 463 #define DO_DS(x) 464 #define DO_CS(x) 465 IMPLEMENT_SHADER_STAGE(VS, Vertex) 466 IMPLEMENT_SHADER_STAGE(GS, Geometry) 467 IMPLEMENT_SHADER_STAGE(PS, Pixel) 468 469 #if API >= 11 470 IMPLEMENT_SHADER_STAGE(HS, Hull) 471 IMPLEMENT_SHADER_STAGE(DS, Domain) 472 IMPLEMENT_SHADER_STAGE(CS, Compute) 473 474 virtual void STDMETHODCALLTYPE CSSetUnorderedAccessViews( 475 unsigned start, 476 unsigned count, 477 ID3D11UnorderedAccessView *const *new_unordered_access_views, 478 const unsigned *new_uav_initial_counts) 479 { 480 SYNCHRONIZED; 481 for(unsigned i = 0; i < count; ++i) 482 cs_unordered_access_views[start + i] = new_unordered_access_views[i]; 483 } 484 485 virtual void STDMETHODCALLTYPE CSGetUnorderedAccessViews( 486 unsigned start, 487 unsigned count, 488 ID3D11UnorderedAccessView **out_unordered_access_views) 489 { 490 SYNCHRONIZED; 491 for(unsigned i = 0; i < count; ++i) 492 out_unordered_access_views[i] = cs_unordered_access_views[start + i].ref(); 493 } 494 #endif 495 496 template<unsigned s> 497 void update_stage() 498 { 499 if(update_flags & (1 << (UPDATE_VIEWS_SHIFT + s))) 500 { 501 while(num_shader_resource_views[s] && !sampler_views[s][num_shader_resource_views[s] - 1]) \ 502 --num_shader_resource_views[s]; 503 if((1 << s) & caps.stages_with_sampling) 504 { 505 const unsigned num_views_to_bind = num_shader_resource_views[s]; 506 switch(s) 507 { 508 case PIPE_SHADER_VERTEX: 509 pipe->set_vertex_sampler_views(pipe, num_views_to_bind, sampler_views[s]); 510 break; 511 case PIPE_SHADER_FRAGMENT: 512 pipe->set_fragment_sampler_views(pipe, num_views_to_bind, sampler_views[s]); 513 break; 514 case PIPE_SHADER_GEOMETRY: 515 pipe->set_geometry_sampler_views(pipe, num_views_to_bind, sampler_views[s]); 516 break; 517 } 518 } 519 } 520 521 if(update_flags & (1 << (UPDATE_SAMPLERS_SHIFT + s))) 522 { 523 while(num_samplers[s] && !sampler_csos[s][num_samplers[s] - 1]) 524 --num_samplers[s]; 525 if((1 << s) & caps.stages_with_sampling) 526 { 527 const unsigned num_samplers_to_bind = num_samplers[s]; 528 switch(s) 529 { 530 case PIPE_SHADER_VERTEX: 531 pipe->bind_vertex_sampler_states(pipe, num_samplers_to_bind, sampler_csos[s]); 532 break; 533 case PIPE_SHADER_FRAGMENT: 534 pipe->bind_fragment_sampler_states(pipe, num_samplers_to_bind, sampler_csos[s]); 535 break; 536 case PIPE_SHADER_GEOMETRY: 537 pipe->bind_geometry_sampler_states(pipe, num_samplers_to_bind, sampler_csos[s]); 538 break; 539 } 540 } 541 } 542 } 543 544 void update_state() 545 { 546 update_stage<D3D11_STAGE_PS>(); 547 update_stage<D3D11_STAGE_VS>(); 548 update_stage<D3D11_STAGE_GS>(); 549 #if API >= 11 550 update_stage<D3D11_STAGE_HS>(); 551 update_stage<D3D11_STAGE_DS>(); 552 update_stage<D3D11_STAGE_CS>(); 553 #endif 554 555 if(update_flags & UPDATE_VERTEX_BUFFERS) 556 { 557 while(num_vertex_buffers && !vertex_buffers[num_vertex_buffers - 1].buffer) 558 --num_vertex_buffers; 559 pipe->set_vertex_buffers(pipe, num_vertex_buffers, vertex_buffers); 560 } 561 562 update_flags = 0; 563 } 564 565 virtual void STDMETHODCALLTYPE IASetInputLayout( 566 ID3D11InputLayout *new_input_layout) 567 { 568 SYNCHRONIZED; 569 if(new_input_layout != input_layout.p) 570 { 571 input_layout = new_input_layout; 572 pipe->bind_vertex_elements_state(pipe, new_input_layout ? ((GalliumD3D11InputLayout*)new_input_layout)->object : default_input_layout); 573 } 574 } 575 576 virtual void STDMETHODCALLTYPE IAGetInputLayout( 577 ID3D11InputLayout **out_input_layout) 578 { 579 SYNCHRONIZED; 580 *out_input_layout = input_layout.ref(); 581 } 582 583 virtual void STDMETHODCALLTYPE IASetVertexBuffers( 584 unsigned start, 585 unsigned count, 586 ID3D11Buffer *const *new_vertex_buffers, 587 const unsigned *new_strides, 588 const unsigned *new_offsets) 589 { 590 SYNCHRONIZED; 591 int last_different = -1; 592 for(unsigned i = 0; i < count; ++i) 593 { 594 ID3D11Buffer* buffer = new_vertex_buffers[i]; 595 if(buffer != input_buffers[start + i].p 596 || vertex_buffers[start + i].buffer_offset != new_offsets[i] 597 || vertex_buffers[start + i].stride != new_strides[i] 598 ) 599 { 600 input_buffers[start + i] = buffer; 601 vertex_buffers[start + i].buffer = buffer ? ((GalliumD3D11Buffer*)buffer)->resource : 0; 602 vertex_buffers[start + i].buffer_offset = new_offsets[i]; 603 vertex_buffers[start + i].stride = new_strides[i]; 604 last_different = i; 605 } 606 } 607 if(last_different >= 0) 608 { 609 num_vertex_buffers = std::max(num_vertex_buffers, start + count); 610 update_flags |= UPDATE_VERTEX_BUFFERS; 611 } 612 } 613 614 virtual void STDMETHODCALLTYPE IAGetVertexBuffers( 615 unsigned start, 616 unsigned count, 617 ID3D11Buffer **out_vertex_buffers, 618 unsigned *out_strides, 619 unsigned *out_offsets) 620 { 621 SYNCHRONIZED; 622 if(out_vertex_buffers) 623 { 624 for(unsigned i = 0; i < count; ++i) 625 out_vertex_buffers[i] = input_buffers[start + i].ref(); 626 } 627 628 if(out_offsets) 629 { 630 for(unsigned i = 0; i < count; ++i) 631 out_offsets[i] = vertex_buffers[start + i].buffer_offset; 632 } 633 634 if(out_strides) 635 { 636 for(unsigned i = 0; i < count; ++i) 637 out_strides[i] = vertex_buffers[start + i].stride; 638 } 639 } 640 641 void set_index_buffer() 642 { 643 pipe_index_buffer ib; 644 if(!index_buffer) 645 { 646 memset(&ib, 0, sizeof(ib)); 647 } 648 else 649 { 650 switch(index_format) { 651 case DXGI_FORMAT_R32_UINT: 652 ib.index_size = 4; 653 strip_cut_index = 0xffffffff; 654 break; 655 case DXGI_FORMAT_R16_UINT: 656 ib.index_size = 2; 657 strip_cut_index = 0xffff; 658 break; 659 default: 660 ib.index_size = 1; 661 strip_cut_index = 0xff; 662 break; 663 } 664 ib.offset = index_offset; 665 ib.buffer = index_buffer ? ((GalliumD3D11Buffer*)index_buffer.p)->resource : 0; 666 } 667 pipe->set_index_buffer(pipe, &ib); 668 } 669 670 virtual void STDMETHODCALLTYPE IASetIndexBuffer( 671 ID3D11Buffer *new_index_buffer, 672 DXGI_FORMAT new_index_format, 673 unsigned new_index_offset) 674 { 675 SYNCHRONIZED; 676 if(index_buffer.p != new_index_buffer || index_format != new_index_format || index_offset != new_index_offset) 677 { 678 index_buffer = new_index_buffer; 679 index_format = new_index_format; 680 index_offset = new_index_offset; 681 682 set_index_buffer(); 683 } 684 } 685 686 virtual void STDMETHODCALLTYPE IAGetIndexBuffer( 687 ID3D11Buffer **out_index_buffer, 688 DXGI_FORMAT *out_index_format, 689 unsigned *out_index_offset) 690 { 691 SYNCHRONIZED; 692 if(out_index_buffer) 693 *out_index_buffer = index_buffer.ref(); 694 if(out_index_format) 695 *out_index_format = index_format; 696 if(out_index_offset) 697 *out_index_offset = index_offset; 698 } 699 700 virtual void STDMETHODCALLTYPE IASetPrimitiveTopology( 701 D3D11_PRIMITIVE_TOPOLOGY new_primitive_topology) 702 { 703 SYNCHRONIZED; 704 if(primitive_topology != new_primitive_topology) 705 { 706 if(new_primitive_topology < D3D_PRIMITIVE_TOPOLOGY_COUNT) 707 primitive_mode = d3d_to_pipe_prim[new_primitive_topology]; 708 else 709 primitive_mode = 0; 710 primitive_topology = new_primitive_topology; 711 } 712 } 713 714 virtual void STDMETHODCALLTYPE IAGetPrimitiveTopology( 715 D3D11_PRIMITIVE_TOPOLOGY *out_primitive_topology) 716 { 717 SYNCHRONIZED; 718 *out_primitive_topology = primitive_topology; 719 } 720 721 virtual void STDMETHODCALLTYPE DrawIndexed( 722 unsigned index_count, 723 unsigned start_index_location, 724 int base_vertex_location) 725 { 726 SYNCHRONIZED; 727 if(update_flags) 728 update_state(); 729 730 pipe_draw_info info; 731 info.mode = primitive_mode; 732 info.indexed = TRUE; 733 info.count = index_count; 734 info.start = start_index_location; 735 info.index_bias = base_vertex_location; 736 info.min_index = 0; 737 info.max_index = ~0; 738 info.start_instance = 0; 739 info.instance_count = 1; 740 info.primitive_restart = TRUE; 741 info.restart_index = strip_cut_index; 742 info.count_from_stream_output = NULL; 743 744 pipe->draw_vbo(pipe, &info); 745 } 746 747 virtual void STDMETHODCALLTYPE Draw( 748 unsigned vertex_count, 749 unsigned start_vertex_location) 750 { 751 SYNCHRONIZED; 752 if(update_flags) 753 update_state(); 754 755 pipe_draw_info info; 756 info.mode = primitive_mode; 757 info.indexed = FALSE; 758 info.count = vertex_count; 759 info.start = start_vertex_location; 760 info.index_bias = 0; 761 info.min_index = 0; 762 info.max_index = ~0; 763 info.start_instance = 0; 764 info.instance_count = 1; 765 info.primitive_restart = FALSE; 766 info.count_from_stream_output = NULL; 767 768 pipe->draw_vbo(pipe, &info); 769 } 770 771 virtual void STDMETHODCALLTYPE DrawIndexedInstanced( 772 unsigned index_countPerInstance, 773 unsigned instance_count, 774 unsigned start_index_location, 775 int base_vertex_location, 776 unsigned start_instance_location) 777 { 778 SYNCHRONIZED; 779 if(update_flags) 780 update_state(); 781 782 pipe_draw_info info; 783 info.mode = primitive_mode; 784 info.indexed = TRUE; 785 info.count = index_countPerInstance; 786 info.start = start_index_location; 787 info.index_bias = base_vertex_location; 788 info.min_index = 0; 789 info.max_index = ~0; 790 info.start_instance = start_instance_location; 791 info.instance_count = instance_count; 792 info.primitive_restart = TRUE; 793 info.restart_index = strip_cut_index; 794 info.count_from_stream_output = NULL; 795 796 pipe->draw_vbo(pipe, &info); 797 } 798 799 virtual void STDMETHODCALLTYPE DrawInstanced( 800 unsigned vertex_countPerInstance, 801 unsigned instance_count, 802 unsigned start_vertex_location, 803 unsigned start_instance_location) 804 { 805 SYNCHRONIZED; 806 if(update_flags) 807 update_state(); 808 809 pipe_draw_info info; 810 info.mode = primitive_mode; 811 info.indexed = FALSE; 812 info.count = vertex_countPerInstance; 813 info.start = start_vertex_location; 814 info.index_bias = 0; 815 info.min_index = 0; 816 info.max_index = ~0; 817 info.start_instance = start_instance_location; 818 info.instance_count = instance_count; 819 info.primitive_restart = FALSE; 820 info.count_from_stream_output = NULL; 821 822 pipe->draw_vbo(pipe, &info); 823 } 824 825 virtual void STDMETHODCALLTYPE DrawAuto(void) 826 { 827 if(!caps.so) 828 return; 829 830 SYNCHRONIZED; 831 if(update_flags) 832 update_state(); 833 834 pipe_draw_info info; 835 info.mode = primitive_mode; 836 info.indexed = FALSE; 837 info.count = 0; 838 info.start = 0; 839 info.index_bias = 0; 840 info.min_index = 0; 841 info.max_index = ~0; 842 info.start_instance = 0; 843 info.instance_count = 1; 844 info.primitive_restart = FALSE; 845 info.restart_index = 0; 846 info.count_from_stream_output = input_buffers[0].p->so_target; 847 848 pipe->draw_vbo(pipe, &info); 849 } 850 851 virtual void STDMETHODCALLTYPE DrawIndexedInstancedIndirect( 852 ID3D11Buffer *buffer, 853 unsigned aligned_byte_offset) 854 { 855 SYNCHRONIZED; 856 if(update_flags) 857 update_state(); 858 859 struct { 860 unsigned count; 861 unsigned instance_count; 862 unsigned start; 863 unsigned index_bias; 864 } data; 865 866 pipe_buffer_read(pipe, ((GalliumD3D11Buffer*)buffer)->resource, aligned_byte_offset, sizeof(data), &data); 867 868 pipe_draw_info info; 869 info.mode = primitive_mode; 870 info.indexed = TRUE; 871 info.start = data.start; 872 info.count = data.count; 873 info.index_bias = data.index_bias; 874 info.min_index = 0; 875 info.max_index = ~0; 876 info.start_instance = 0; 877 info.instance_count = data.instance_count; 878 info.primitive_restart = TRUE; 879 info.restart_index = strip_cut_index; 880 info.count_from_stream_output = NULL; 881 882 pipe->draw_vbo(pipe, &info); 883 } 884 885 virtual void STDMETHODCALLTYPE DrawInstancedIndirect( 886 ID3D11Buffer *buffer, 887 unsigned aligned_byte_offset) 888 { 889 SYNCHRONIZED; 890 if(update_flags) 891 update_state(); 892 893 struct { 894 unsigned count; 895 unsigned instance_count; 896 unsigned start; 897 } data; 898 899 pipe_buffer_read(pipe, ((GalliumD3D11Buffer*)buffer)->resource, aligned_byte_offset, sizeof(data), &data); 900 901 pipe_draw_info info; 902 info.mode = primitive_mode; 903 info.indexed = FALSE; 904 info.start = data.start; 905 info.count = data.count; 906 info.index_bias = 0; 907 info.min_index = 0; 908 info.max_index = ~0; 909 info.start_instance = 0; 910 info.instance_count = data.instance_count; 911 info.primitive_restart = FALSE; 912 info.count_from_stream_output = NULL; 913 914 pipe->draw_vbo(pipe, &info); 915 } 916 917 #if API >= 11 918 virtual void STDMETHODCALLTYPE Dispatch( 919 unsigned thread_group_count_x, 920 unsigned thread_group_count_y, 921 unsigned thread_group_count_z) 922 { 923 // uncomment this when this is implemented 924 // SYNCHRONIZED; 925 // if(update_flags) 926 // update_state(); 927 } 928 929 virtual void STDMETHODCALLTYPE DispatchIndirect( 930 ID3D11Buffer *buffer, 931 unsigned aligned_byte_offset) 932 { 933 // uncomment this when this is implemented 934 // SYNCHRONIZED; 935 // if(update_flags) 936 // update_state(); 937 } 938 #endif 939 940 virtual void STDMETHODCALLTYPE RSSetState( 941 ID3D11RasterizerState *new_rasterizer_state) 942 { 943 SYNCHRONIZED; 944 if(new_rasterizer_state != rasterizer_state.p) 945 { 946 rasterizer_state = new_rasterizer_state; 947 pipe->bind_rasterizer_state(pipe, new_rasterizer_state ? ((GalliumD3D11RasterizerState*)new_rasterizer_state)->object : default_rasterizer); 948 } 949 } 950 951 virtual void STDMETHODCALLTYPE RSGetState( 952 ID3D11RasterizerState **out_rasterizer_state) 953 { 954 SYNCHRONIZED; 955 *out_rasterizer_state = rasterizer_state.ref(); 956 } 957 958 void set_viewport() 959 { 960 // TODO: is depth correct? it seems D3D10/11 uses a [-1,1]x[-1,1]x[0,1] cube 961 pipe_viewport_state viewport; 962 float half_width = viewports[0].Width * 0.5f; 963 float half_height = viewports[0].Height * 0.5f; 964 965 viewport.scale[0] = half_width; 966 viewport.scale[1] = -half_height; 967 viewport.scale[2] = (viewports[0].MaxDepth - viewports[0].MinDepth); 968 viewport.scale[3] = 1.0f; 969 viewport.translate[0] = half_width + viewports[0].TopLeftX; 970 viewport.translate[1] = half_height + viewports[0].TopLeftY; 971 viewport.translate[2] = viewports[0].MinDepth; 972 viewport.translate[3] = 1.0f; 973 pipe->set_viewport_state(pipe, &viewport); 974 } 975 976 virtual void STDMETHODCALLTYPE RSSetViewports( 977 unsigned count, 978 const D3D11_VIEWPORT *new_viewports) 979 { 980 SYNCHRONIZED; 981 if(count) 982 { 983 if(memcmp(&viewports[0], &new_viewports[0], sizeof(viewports[0]))) 984 { 985 viewports[0] = new_viewports[0]; 986 set_viewport(); 987 } 988 for(unsigned i = 1; i < count; ++i) 989 viewports[i] = new_viewports[i]; 990 } 991 else if(num_viewports) 992 { 993 // TODO: what should we do here? 994 memset(&viewports[0], 0, sizeof(viewports[0])); 995 set_viewport(); 996 } 997 num_viewports = count; 998 } 999 1000 virtual void STDMETHODCALLTYPE RSGetViewports( 1001 unsigned *out_count, 1002 D3D11_VIEWPORT *out_viewports) 1003 { 1004 SYNCHRONIZED; 1005 if(out_viewports) 1006 { 1007 unsigned i; 1008 for(i = 0; i < std::min(*out_count, num_viewports); ++i) 1009 out_viewports[i] = viewports[i]; 1010 1011 memset(out_viewports + i, 0, (*out_count - i) * sizeof(D3D11_VIEWPORT)); 1012 } 1013 1014 *out_count = num_viewports; 1015 } 1016 1017 void set_scissor() 1018 { 1019 pipe_scissor_state scissor; 1020 scissor.minx = scissor_rects[0].left; 1021 scissor.miny = scissor_rects[0].top; 1022 scissor.maxx = scissor_rects[0].right; 1023 scissor.maxy = scissor_rects[0].bottom; 1024 pipe->set_scissor_state(pipe, &scissor); 1025 } 1026 1027 virtual void STDMETHODCALLTYPE RSSetScissorRects( 1028 unsigned count, 1029 const D3D11_RECT *new_rects) 1030 { 1031 SYNCHRONIZED; 1032 if(count) 1033 { 1034 if(memcmp(&scissor_rects[0], &new_rects[0], sizeof(scissor_rects[0]))) 1035 { 1036 scissor_rects[0] = new_rects[0]; 1037 set_scissor(); 1038 } 1039 for(unsigned i = 1; i < count; ++i) 1040 scissor_rects[i] = new_rects[i]; 1041 } 1042 else if(num_scissor_rects) 1043 { 1044 // TODO: what should we do here? 1045 memset(&scissor_rects[0], 0, sizeof(scissor_rects[0])); 1046 set_scissor(); 1047 } 1048 1049 num_scissor_rects = count; 1050 } 1051 1052 virtual void STDMETHODCALLTYPE RSGetScissorRects( 1053 unsigned *out_count, 1054 D3D11_RECT *out_rects) 1055 { 1056 SYNCHRONIZED; 1057 if(out_rects) 1058 { 1059 unsigned i; 1060 for(i = 0; i < std::min(*out_count, num_scissor_rects); ++i) 1061 out_rects[i] = scissor_rects[i]; 1062 1063 memset(out_rects + i, 0, (*out_count - i) * sizeof(D3D11_RECT)); 1064 } 1065 1066 *out_count = num_scissor_rects; 1067 } 1068 1069 virtual void STDMETHODCALLTYPE OMSetBlendState( 1070 ID3D11BlendState *new_blend_state, 1071 const float new_blend_factor[4], 1072 unsigned new_sample_mask) 1073 { 1074 SYNCHRONIZED; 1075 float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; 1076 1077 if(blend_state.p != new_blend_state) 1078 { 1079 pipe->bind_blend_state(pipe, new_blend_state ? ((GalliumD3D11BlendState*)new_blend_state)->object : default_blend); 1080 blend_state = new_blend_state; 1081 } 1082 1083 // Windows D3D11 does this, even though it's apparently undocumented 1084 if(!new_blend_factor) 1085 new_blend_factor = white; 1086 1087 if(memcmp(blend_color, new_blend_factor, sizeof(blend_color))) 1088 { 1089 pipe->set_blend_color(pipe, (struct pipe_blend_color*)new_blend_factor); 1090 memcpy(blend_color, new_blend_factor, sizeof(blend_color)); 1091 } 1092 1093 if(sample_mask != new_sample_mask) 1094 { 1095 pipe->set_sample_mask(pipe, new_sample_mask); 1096 sample_mask = new_sample_mask; 1097 } 1098 } 1099 1100 virtual void STDMETHODCALLTYPE OMGetBlendState( 1101 ID3D11BlendState **out_blend_state, 1102 float out_blend_factor[4], 1103 unsigned *out_sample_mask) 1104 { 1105 SYNCHRONIZED; 1106 if(out_blend_state) 1107 *out_blend_state = blend_state.ref(); 1108 if(out_blend_factor) 1109 memcpy(out_blend_factor, blend_color, sizeof(blend_color)); 1110 if(out_sample_mask) 1111 *out_sample_mask = sample_mask; 1112 } 1113 1114 void set_stencil_ref() 1115 { 1116 struct pipe_stencil_ref sref; 1117 sref.ref_value[0] = stencil_ref; 1118 sref.ref_value[1] = stencil_ref; 1119 pipe->set_stencil_ref(pipe, &sref); 1120 } 1121 1122 virtual void STDMETHODCALLTYPE OMSetDepthStencilState( 1123 ID3D11DepthStencilState *new_depth_stencil_state, 1124 unsigned new_stencil_ref) 1125 { 1126 SYNCHRONIZED; 1127 if(new_depth_stencil_state != depth_stencil_state.p) 1128 { 1129 pipe->bind_depth_stencil_alpha_state(pipe, new_depth_stencil_state ? ((GalliumD3D11DepthStencilState*)new_depth_stencil_state)->object : default_depth_stencil); 1130 depth_stencil_state = new_depth_stencil_state; 1131 } 1132 1133 if(new_stencil_ref != stencil_ref) 1134 { 1135 stencil_ref = new_stencil_ref; 1136 set_stencil_ref(); 1137 } 1138 } 1139 1140 virtual void STDMETHODCALLTYPE OMGetDepthStencilState( 1141 ID3D11DepthStencilState **out_depth_stencil_state, 1142 unsigned *out_stencil_ref) 1143 { 1144 SYNCHRONIZED; 1145 if(*out_depth_stencil_state) 1146 *out_depth_stencil_state = depth_stencil_state.ref(); 1147 if(out_stencil_ref) 1148 *out_stencil_ref = stencil_ref; 1149 } 1150 1151 void set_framebuffer() 1152 { 1153 struct pipe_framebuffer_state fb; 1154 memset(&fb, 0, sizeof(fb)); 1155 if(depth_stencil_view) 1156 { 1157 struct pipe_surface* surf = ((GalliumD3D11DepthStencilView*)depth_stencil_view.p)->object; 1158 fb.zsbuf = surf; 1159 if(surf->width > fb.width) 1160 fb.width = surf->width; 1161 if(surf->height > fb.height) 1162 fb.height = surf->height; 1163 } 1164 fb.nr_cbufs = num_render_target_views; 1165 unsigned i; 1166 for(i = 0; i < num_render_target_views; ++i) 1167 { 1168 if(render_target_views[i]) 1169 { 1170 struct pipe_surface* surf = ((GalliumD3D11RenderTargetView*)render_target_views[i].p)->object; 1171 fb.cbufs[i] = surf; 1172 if(surf->width > fb.width) 1173 fb.width = surf->width; 1174 if(surf->height > fb.height) 1175 fb.height = surf->height; 1176 } 1177 } 1178 1179 pipe->set_framebuffer_state(pipe, &fb); 1180 } 1181 1182 /* 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. 1183 * Hopefully nobody relies on this happening 1184 */ 1185 1186 virtual void STDMETHODCALLTYPE OMSetRenderTargets( 1187 unsigned count, 1188 ID3D11RenderTargetView *const *new_render_target_views, 1189 ID3D11DepthStencilView *new_depth_stencil_view) 1190 { 1191 SYNCHRONIZED; 1192 1193 bool update = false; 1194 unsigned i, num; 1195 1196 if(depth_stencil_view.p != new_depth_stencil_view) { 1197 update = true; 1198 depth_stencil_view = new_depth_stencil_view; 1199 } 1200 1201 if(!new_render_target_views) 1202 count = 0; 1203 1204 for(num = 0, i = 0; i < count; ++i) { 1205 #if API >= 11 1206 // XXX: is unbinding the UAVs here correct ? 1207 om_unordered_access_views[i] = (ID3D11UnorderedAccessView*)NULL; 1208 #endif 1209 if(new_render_target_views[i] != render_target_views[i].p) { 1210 update = true; 1211 render_target_views[i] = new_render_target_views[i]; 1212 } 1213 if(new_render_target_views[i]) 1214 num = i + 1; 1215 } 1216 if(num != num_render_target_views) { 1217 update = true; 1218 for(; i < num_render_target_views; ++i) 1219 render_target_views[i] = (ID3D11RenderTargetView*)NULL; 1220 } 1221 num_render_target_views = num; 1222 if(update) 1223 set_framebuffer(); 1224 } 1225 1226 virtual void STDMETHODCALLTYPE OMGetRenderTargets( 1227 unsigned count, 1228 ID3D11RenderTargetView **out_render_target_views, 1229 ID3D11DepthStencilView **out_depth_stencil_view) 1230 { 1231 SYNCHRONIZED; 1232 if(out_render_target_views) 1233 { 1234 unsigned i; 1235 for(i = 0; i < std::min(num_render_target_views, count); ++i) 1236 out_render_target_views[i] = render_target_views[i].ref(); 1237 1238 for(; i < count; ++i) 1239 out_render_target_views[i] = 0; 1240 } 1241 1242 if(out_depth_stencil_view) 1243 *out_depth_stencil_view = depth_stencil_view.ref(); 1244 } 1245 1246 #if API >= 11 1247 /* TODO: what is this supposed to do _exactly_? are we doing the right thing? */ 1248 virtual void STDMETHODCALLTYPE OMSetRenderTargetsAndUnorderedAccessViews( 1249 unsigned rtv_count, 1250 ID3D11RenderTargetView *const *new_render_target_views, 1251 ID3D11DepthStencilView *new_depth_stencil_view, 1252 unsigned uav_start, 1253 unsigned uav_count, 1254 ID3D11UnorderedAccessView *const *new_unordered_access_views, 1255 const unsigned *new_uav_initial_counts) 1256 { 1257 SYNCHRONIZED; 1258 if(rtv_count != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) 1259 OMSetRenderTargets(rtv_count, new_render_target_views, new_depth_stencil_view); 1260 1261 if(uav_count != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) 1262 { 1263 for(unsigned i = 0; i < uav_count; ++i) 1264 { 1265 om_unordered_access_views[uav_start + i] = new_unordered_access_views[i]; 1266 render_target_views[uav_start + i] = (ID3D11RenderTargetView*)0; 1267 } 1268 } 1269 } 1270 1271 virtual void STDMETHODCALLTYPE OMGetRenderTargetsAndUnorderedAccessViews( 1272 unsigned rtv_count, 1273 ID3D11RenderTargetView **out_render_target_views, 1274 ID3D11DepthStencilView **out_depth_stencil_view, 1275 unsigned uav_start, 1276 unsigned uav_count, 1277 ID3D11UnorderedAccessView **out_unordered_access_views) 1278 { 1279 SYNCHRONIZED; 1280 if(out_render_target_views) 1281 OMGetRenderTargets(rtv_count, out_render_target_views, out_depth_stencil_view); 1282 1283 if(out_unordered_access_views) 1284 { 1285 for(unsigned i = 0; i < uav_count; ++i) 1286 out_unordered_access_views[i] = om_unordered_access_views[uav_start + i].ref(); 1287 } 1288 } 1289 #endif 1290 1291 virtual void STDMETHODCALLTYPE SOSetTargets( 1292 unsigned count, 1293 ID3D11Buffer *const *new_so_targets, 1294 const unsigned *new_offsets) 1295 { 1296 SYNCHRONIZED; 1297 1298 unsigned new_count, i; 1299 bool changed = false; 1300 1301 uint32_t append_mask = 0xffffffff; 1302 1303 if(!new_so_targets) 1304 count = 0; 1305 for(new_count = 0, i = 0; i < count; ++i) 1306 { 1307 GalliumD3D11Buffer* buffer = static_cast<GalliumD3D11Buffer*>(new_so_targets[i]); 1308 1309 if(buffer != so_buffers[i].p) 1310 { 1311 changed = true; 1312 so_buffers[i] = buffer; 1313 so_targets[i] = buffer ? buffer->so_target : 0; 1314 } 1315 if(!buffer) 1316 continue; 1317 new_count = i + 1; 1318 1319 if(new_offsets[i] == (unsigned)-1) 1320 { 1321 assert(so_targets[i]); 1322 continue; 1323 } 1324 append_mask &= ~(1 << i); 1325 1326 if(!so_targets[i] || new_offsets[i] != so_targets[i]->buffer_offset) 1327 { 1328 pipe_so_target_reference(&buffer->so_target, NULL); 1329 buffer->so_target = pipe->create_stream_output_target( 1330 pipe, buffer->resource, new_offsets[i], buffer->resource->width0 - new_offsets[i]); 1331 so_targets[i] = buffer->so_target; 1332 changed = true; 1333 } 1334 } 1335 if(i < num_so_targets) { 1336 changed = true; 1337 for(; i < num_so_targets; ++i) 1338 so_buffers[i] = (GalliumD3D11Buffer*)0; 1339 } 1340 num_so_targets = new_count; 1341 1342 if(likely(caps.so) && (changed || append_mask != 0xffffffff)) 1343 pipe->set_stream_output_targets(pipe, num_so_targets, so_targets, append_mask); 1344 } 1345 1346 virtual void STDMETHODCALLTYPE SOGetTargets( 1347 unsigned count, 1348 ID3D11Buffer **out_so_targets 1349 #if API < 11 1350 , UINT *out_offsets 1351 #endif 1352 ) 1353 { 1354 SYNCHRONIZED; 1355 for(unsigned i = 0; i < count; ++i) 1356 { 1357 out_so_targets[i] = so_buffers[i].ref(); 1358 #if API < 11 1359 out_offsets[i] = so_targets[i]->buffer_offset; 1360 #endif 1361 } 1362 } 1363 1364 virtual void STDMETHODCALLTYPE Begin( 1365 ID3D11Asynchronous *async) 1366 { 1367 SYNCHRONIZED; 1368 if(caps.queries) 1369 pipe->begin_query(pipe, ((GalliumD3D11Asynchronous<>*)async)->query); 1370 } 1371 1372 virtual void STDMETHODCALLTYPE End( 1373 ID3D11Asynchronous *async) 1374 { 1375 SYNCHRONIZED; 1376 if(caps.queries) 1377 pipe->end_query(pipe, ((GalliumD3D11Asynchronous<>*)async)->query); 1378 } 1379 1380 virtual HRESULT STDMETHODCALLTYPE GetData( 1381 ID3D11Asynchronous *iasync, 1382 void *out_data, 1383 unsigned data_size, 1384 unsigned get_data_flags) 1385 { 1386 SYNCHRONIZED; 1387 if(!caps.queries) 1388 return E_NOTIMPL; 1389 1390 GalliumD3D11Asynchronous<>* async = (GalliumD3D11Asynchronous<>*)iasync; 1391 void* tmp_data = alloca(async->data_size); 1392 memset(tmp_data, 0, async->data_size); // sizeof(BOOL) is 4, sizeof(boolean) is 1 1393 boolean ret = pipe->get_query_result(pipe, async->query, !(get_data_flags & D3D11_ASYNC_GETDATA_DONOTFLUSH), tmp_data); 1394 if(out_data) 1395 { 1396 memcpy(out_data, tmp_data, std::min(async->data_size, data_size)); 1397 } 1398 return ret ? S_OK : S_FALSE; 1399 } 1400 1401 void set_render_condition() 1402 { 1403 if(caps.render_condition) 1404 { 1405 if(!render_predicate) 1406 pipe->render_condition(pipe, 0, 0); 1407 else 1408 { 1409 GalliumD3D11Predicate* predicate = (GalliumD3D11Predicate*)render_predicate.p; 1410 if(!render_predicate_value && predicate->desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE) 1411 { 1412 unsigned mode = (predicate->desc.MiscFlags & D3D11_QUERY_MISC_PREDICATEHINT) ? PIPE_RENDER_COND_NO_WAIT : PIPE_RENDER_COND_WAIT; 1413 pipe->render_condition(pipe, predicate->query, mode); 1414 } 1415 else 1416 { 1417 /* TODO: add inverted predication to Gallium*/ 1418 pipe->render_condition(pipe, 0, 0); 1419 } 1420 } 1421 } 1422 } 1423 1424 virtual void STDMETHODCALLTYPE SetPredication( 1425 ID3D11Predicate *new_predicate, 1426 BOOL new_predicate_value) 1427 { 1428 SYNCHRONIZED; 1429 if(render_predicate.p != new_predicate || render_predicate_value != new_predicate_value) 1430 { 1431 render_predicate = new_predicate; 1432 render_predicate_value = new_predicate_value; 1433 set_render_condition(); 1434 } 1435 } 1436 1437 virtual void STDMETHODCALLTYPE GetPredication( 1438 ID3D11Predicate **out_predicate, 1439 BOOL *out_predicate_value) 1440 { 1441 SYNCHRONIZED; 1442 if(out_predicate) 1443 *out_predicate = render_predicate.ref(); 1444 if(out_predicate_value) 1445 *out_predicate_value = render_predicate_value; 1446 } 1447 1448 static unsigned d3d11_subresource_to_level(struct pipe_resource* resource, unsigned subresource) 1449 { 1450 if(subresource <= resource->last_level) 1451 { 1452 return subresource; 1453 } 1454 else 1455 { 1456 unsigned levels = resource->last_level + 1; 1457 return subresource % levels; 1458 } 1459 } 1460 1461 static unsigned d3d11_subresource_to_layer(struct pipe_resource* resource, unsigned subresource) 1462 { 1463 if(subresource <= resource->last_level) 1464 { 1465 return 0; 1466 } 1467 else 1468 { 1469 unsigned levels = resource->last_level + 1; 1470 return subresource / levels; 1471 } 1472 } 1473 1474 1475 /* TODO: deferred contexts will need a different implementation of this, 1476 * because we can't put the transfer info into the resource itself. 1477 * Also, there are very different restrictions, for obvious reasons. 1478 */ 1479 virtual HRESULT STDMETHODCALLTYPE Map( 1480 ID3D11Resource *iresource, 1481 unsigned subresource, 1482 D3D11_MAP map_type, 1483 unsigned map_flags, 1484 D3D11_MAPPED_SUBRESOURCE *mapped_resource) 1485 { 1486 SYNCHRONIZED; 1487 GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)iresource; 1488 if(resource->transfers.count(subresource)) 1489 return E_FAIL; 1490 unsigned level = d3d11_subresource_to_level(resource->resource, subresource); 1491 unsigned layer = d3d11_subresource_to_layer(resource->resource, subresource); 1492 pipe_box box = d3d11_to_pipe_box(resource->resource, level, 0); 1493 box.z += layer; 1494 unsigned usage = 0; 1495 if(map_type == D3D11_MAP_READ) 1496 usage = PIPE_TRANSFER_READ; 1497 else if(map_type == D3D11_MAP_WRITE) 1498 usage = PIPE_TRANSFER_WRITE; 1499 else if(map_type == D3D11_MAP_READ_WRITE) 1500 usage = PIPE_TRANSFER_READ_WRITE; 1501 else if(map_type == D3D11_MAP_WRITE_DISCARD) 1502 usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD; 1503 else if(map_type == D3D11_MAP_WRITE_NO_OVERWRITE) 1504 usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED; 1505 else 1506 return E_INVALIDARG; 1507 if(map_type & D3D10_MAP_FLAG_DO_NOT_WAIT) 1508 usage |= PIPE_TRANSFER_DONTBLOCK; 1509 struct pipe_transfer* transfer = pipe->get_transfer(pipe, resource->resource, level, usage, &box); 1510 if(!transfer) { 1511 if(map_type & D3D10_MAP_FLAG_DO_NOT_WAIT) 1512 return DXGI_ERROR_WAS_STILL_DRAWING; 1513 else 1514 return E_FAIL; 1515 } 1516 resource->transfers[subresource] = transfer; 1517 mapped_resource->pData = pipe->transfer_map(pipe, transfer); 1518 mapped_resource->RowPitch = transfer->stride; 1519 mapped_resource->DepthPitch = transfer->layer_stride; 1520 return S_OK; 1521 } 1522 1523 virtual void STDMETHODCALLTYPE Unmap( 1524 ID3D11Resource *iresource, 1525 unsigned subresource) 1526 { 1527 SYNCHRONIZED; 1528 GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)iresource; 1529 std::unordered_map<unsigned, pipe_transfer*>::iterator i = resource->transfers.find(subresource); 1530 if(i != resource->transfers.end()) 1531 { 1532 pipe->transfer_unmap(pipe, i->second); 1533 pipe->transfer_destroy(pipe, i->second); 1534 resource->transfers.erase(i); 1535 } 1536 } 1537 1538 virtual void STDMETHODCALLTYPE CopySubresourceRegion( 1539 ID3D11Resource *dst_resource, 1540 unsigned dst_subresource, 1541 unsigned dst_x, 1542 unsigned dst_y, 1543 unsigned dst_z, 1544 ID3D11Resource *src_resource, 1545 unsigned src_subresource, 1546 const D3D11_BOX *src_box) 1547 { 1548 SYNCHRONIZED; 1549 GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource; 1550 GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)src_resource; 1551 unsigned dst_level = d3d11_subresource_to_level(dst->resource, dst_subresource); 1552 unsigned dst_layer = d3d11_subresource_to_layer(dst->resource, dst_subresource); 1553 unsigned src_level = d3d11_subresource_to_level(src->resource, src_subresource); 1554 unsigned src_layer = d3d11_subresource_to_layer(src->resource, src_subresource); 1555 pipe_box box = d3d11_to_pipe_box(src->resource, src_level, src_box); 1556 dst_z += dst_layer; 1557 box.z += src_layer; 1558 { 1559 pipe->resource_copy_region(pipe, 1560 dst->resource, dst_level, dst_x, dst_y, dst_z, 1561 src->resource, src_level, &box); 1562 } 1563 } 1564 1565 virtual void STDMETHODCALLTYPE CopyResource( 1566 ID3D11Resource *dst_resource, 1567 ID3D11Resource *src_resource) 1568 { 1569 SYNCHRONIZED; 1570 GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource; 1571 GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)src_resource; 1572 unsigned level; 1573 for(level = 0; level <= dst->resource->last_level; ++level) 1574 { 1575 pipe_box box; 1576 box.x = box.y = box.z = 0; 1577 box.width = u_minify(dst->resource->width0, level); 1578 box.height = u_minify(dst->resource->height0, level); 1579 if(dst->resource->target == PIPE_TEXTURE_3D) 1580 box.depth = u_minify(dst->resource->depth0, level); 1581 else 1582 box.depth = dst->resource->array_size; 1583 pipe->resource_copy_region(pipe, 1584 dst->resource, level, 0, 0, 0, 1585 src->resource, level, &box); 1586 } 1587 } 1588 1589 virtual void STDMETHODCALLTYPE UpdateSubresource( 1590 ID3D11Resource *dst_resource, 1591 unsigned dst_subresource, 1592 const D3D11_BOX *pDstBox, 1593 const void *pSrcData, 1594 unsigned src_row_pitch, 1595 unsigned src_depth_pitch) 1596 { 1597 SYNCHRONIZED; 1598 GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource; 1599 unsigned dst_level = d3d11_subresource_to_level(dst->resource, dst_subresource); 1600 unsigned dst_layer = d3d11_subresource_to_layer(dst->resource, dst_subresource); 1601 pipe_box box = d3d11_to_pipe_box(dst->resource, dst_level, pDstBox); 1602 box.z += dst_layer; 1603 pipe->transfer_inline_write(pipe, dst->resource, dst_level, PIPE_TRANSFER_WRITE, &box, pSrcData, src_row_pitch, src_depth_pitch); 1604 } 1605 1606 #if API >= 11 1607 virtual void STDMETHODCALLTYPE CopyStructureCount( 1608 ID3D11Buffer *dst_buffer, 1609 unsigned dst_aligned_byte_offset, 1610 ID3D11UnorderedAccessView *src_view) 1611 { 1612 SYNCHRONIZED; 1613 } 1614 #endif 1615 1616 virtual void STDMETHODCALLTYPE ClearRenderTargetView( 1617 ID3D11RenderTargetView *render_target_view, 1618 const float color[4]) 1619 { 1620 SYNCHRONIZED; 1621 GalliumD3D11RenderTargetView* view = ((GalliumD3D11RenderTargetView*)render_target_view); 1622 union pipe_color_union cc; 1623 cc.f[0] = color[0]; 1624 cc.f[1] = color[1]; 1625 cc.f[2] = color[2]; 1626 cc.f[3] = color[3]; 1627 pipe->clear_render_target(pipe, view->object, &cc, 0, 0, view->object->width, view->object->height); 1628 } 1629 1630 virtual void STDMETHODCALLTYPE ClearDepthStencilView( 1631 ID3D11DepthStencilView *depth_stencil_view, 1632 unsigned clear_flags, 1633 float depth, 1634 UINT8 stencil) 1635 { 1636 SYNCHRONIZED; 1637 GalliumD3D11DepthStencilView* view = ((GalliumD3D11DepthStencilView*)depth_stencil_view); 1638 unsigned flags = 0; 1639 if(clear_flags & D3D11_CLEAR_DEPTH) 1640 flags |= PIPE_CLEAR_DEPTH; 1641 if(clear_flags & D3D11_CLEAR_STENCIL) 1642 flags |= PIPE_CLEAR_STENCIL; 1643 pipe->clear_depth_stencil(pipe, view->object, flags, depth, stencil, 0, 0, view->object->width, view->object->height); 1644 } 1645 1646 #if API >= 11 1647 virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewUint( 1648 ID3D11UnorderedAccessView *unordered_access_view, 1649 const unsigned values[4]) 1650 { 1651 SYNCHRONIZED; 1652 } 1653 1654 virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewFloat( 1655 ID3D11UnorderedAccessView *unordered_access_view, 1656 const float values[4]) 1657 { 1658 SYNCHRONIZED; 1659 } 1660 #endif 1661 1662 void restore_gallium_state_blit_only() 1663 { 1664 pipe->bind_blend_state(pipe, blend_state.p ? blend_state.p->object : default_blend); 1665 pipe->bind_depth_stencil_alpha_state(pipe, depth_stencil_state.p ? depth_stencil_state.p->object : default_depth_stencil); 1666 pipe->bind_rasterizer_state(pipe, rasterizer_state.p ? rasterizer_state.p->object : default_rasterizer); 1667 pipe->bind_vertex_elements_state(pipe, input_layout.p ? input_layout.p->object : default_input_layout); 1668 pipe->bind_fs_state(pipe, shaders[D3D11_STAGE_PS].p ? shaders[D3D11_STAGE_PS].p->object : default_shaders[PIPE_SHADER_FRAGMENT]); 1669 pipe->bind_vs_state(pipe, shaders[D3D11_STAGE_VS].p ? shaders[D3D11_STAGE_VS].p->object : default_shaders[PIPE_SHADER_VERTEX]); 1670 if(caps.gs) 1671 pipe->bind_gs_state(pipe, shaders[D3D11_STAGE_GS].p ? shaders[D3D11_STAGE_GS].p->object : default_shaders[PIPE_SHADER_GEOMETRY]); 1672 if(caps.so && num_so_targets) 1673 pipe->set_stream_output_targets(pipe, num_so_targets, so_targets, ~0); 1674 set_framebuffer(); 1675 set_viewport(); 1676 set_render_condition(); 1677 1678 update_flags |= UPDATE_VERTEX_BUFFERS | (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_PS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_PS)); 1679 } 1680 1681 virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly() 1682 { 1683 SYNCHRONIZED; 1684 restore_gallium_state_blit_only(); 1685 } 1686 1687 virtual void STDMETHODCALLTYPE GenerateMips( 1688 ID3D11ShaderResourceView *shader_resource_view) 1689 { 1690 SYNCHRONIZED; 1691 1692 GalliumD3D11ShaderResourceView* view = (GalliumD3D11ShaderResourceView*)shader_resource_view; 1693 if(caps.gs) 1694 pipe->bind_gs_state(pipe, 0); 1695 if(caps.so && num_so_targets) 1696 pipe->set_stream_output_targets(pipe, 0, NULL, 0); 1697 if(pipe->render_condition) 1698 pipe->render_condition(pipe, 0, 0); 1699 for(unsigned layer = view->object->u.tex.first_layer; layer <= view->object->u.tex.last_layer; ++layer) 1700 util_gen_mipmap(gen_mipmap, view->object, layer, view->object->u.tex.first_level, view->object->u.tex.last_level, PIPE_TEX_FILTER_LINEAR); 1701 restore_gallium_state_blit_only(); 1702 } 1703 1704 virtual void STDMETHODCALLTYPE RestoreGalliumState() 1705 { 1706 SYNCHRONIZED; 1707 restore_gallium_state_blit_only(); 1708 1709 set_index_buffer(); 1710 set_stencil_ref(); 1711 pipe->set_blend_color(pipe, (struct pipe_blend_color*)blend_color); 1712 pipe->set_sample_mask(pipe, sample_mask); 1713 1714 for(unsigned s = 0; s < 3; ++s) 1715 { 1716 unsigned num = std::min(caps.constant_buffers[s], (unsigned)D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); 1717 for(unsigned i = 0; i < num; ++i) 1718 pipe_set_constant_buffer(pipe, s, i, constant_buffers[s][i].p ? constant_buffers[s][i].p->resource : 0); 1719 } 1720 1721 update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_VS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_VS)); 1722 update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_GS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_GS)); 1723 1724 set_scissor(); 1725 } 1726 1727 #if API >= 11 1728 /* TODO: hack SRVs or sampler states to handle this, or add to Gallium */ 1729 virtual void STDMETHODCALLTYPE SetResourceMinLOD( 1730 ID3D11Resource *iresource, 1731 float min_lod) 1732 { 1733 SYNCHRONIZED; 1734 GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)iresource; 1735 if(resource->min_lod != min_lod) 1736 { 1737 // TODO: actually do anything? 1738 resource->min_lod = min_lod; 1739 } 1740 } 1741 1742 virtual float STDMETHODCALLTYPE GetResourceMinLOD( 1743 ID3D11Resource *iresource) 1744 { 1745 SYNCHRONIZED; 1746 GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)iresource; 1747 return resource->min_lod; 1748 } 1749 #endif 1750 1751 virtual void STDMETHODCALLTYPE ResolveSubresource( 1752 ID3D11Resource *dst_resource, 1753 unsigned dst_subresource, 1754 ID3D11Resource *src_resource, 1755 unsigned src_subresource, 1756 DXGI_FORMAT format) 1757 { 1758 SYNCHRONIZED; 1759 GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource; 1760 GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)src_resource; 1761 struct pipe_resolve_info info; 1762 1763 info.dst.res = dst->resource; 1764 info.src.res = src->resource; 1765 info.dst.level = 0; 1766 info.dst.layer = d3d11_subresource_to_layer(dst->resource, dst_subresource); 1767 info.src.layer = d3d11_subresource_to_layer(src->resource, src_subresource); 1768 1769 info.src.x0 = 0; 1770 info.src.x1 = info.src.res->width0; 1771 info.src.y0 = 0; 1772 info.src.y1 = info.src.res->height0; 1773 info.dst.x0 = 0; 1774 info.dst.x1 = info.dst.res->width0; 1775 info.dst.y0 = 0; 1776 info.dst.y1 = info.dst.res->height0; 1777 1778 info.mask = PIPE_MASK_RGBA | PIPE_MASK_ZS; 1779 1780 pipe->resource_resolve(pipe, &info); 1781 } 1782 1783 #if API >= 11 1784 virtual void STDMETHODCALLTYPE ExecuteCommandList( 1785 ID3D11CommandList *command_list, 1786 BOOL restore_context_state) 1787 { 1788 SYNCHRONIZED; 1789 } 1790 1791 virtual HRESULT STDMETHODCALLTYPE FinishCommandList( 1792 BOOL restore_deferred_context_state, 1793 ID3D11CommandList **out_command_list) 1794 { 1795 SYNCHRONIZED; 1796 return E_NOTIMPL; 1797 } 1798 #endif 1799 1800 virtual void STDMETHODCALLTYPE ClearState(void) 1801 { 1802 /* we don't take a lock here because we would deadlock otherwise 1803 * TODO: this is probably incorrect, because ClearState should likely be atomic. 1804 * However, I can't think of any correct usage that would be affected by this 1805 * being non-atomic, and making this atomic is quite expensive and complicates 1806 * the code 1807 */ 1808 1809 // we qualify all calls so that we avoid virtual dispatch and might get them inlined 1810 // TODO: make sure all this gets inlined, which might require more compiler flags 1811 // TODO: optimize this 1812 #if API >= 11 1813 GalliumD3D11DeviceContext::PSSetShader(0, 0, 0); 1814 GalliumD3D11DeviceContext::GSSetShader(0, 0, 0); 1815 GalliumD3D11DeviceContext::VSSetShader(0, 0, 0); 1816 GalliumD3D11DeviceContext::HSSetShader(0, 0, 0); 1817 GalliumD3D11DeviceContext::DSSetShader(0, 0, 0); 1818 GalliumD3D11DeviceContext::CSSetShader(0, 0, 0); 1819 #else 1820 GalliumD3D11DeviceContext::PSSetShader(0); 1821 GalliumD3D11DeviceContext::GSSetShader(0); 1822 GalliumD3D11DeviceContext::VSSetShader(0); 1823 #endif 1824 1825 GalliumD3D11DeviceContext::IASetInputLayout(0); 1826 GalliumD3D11DeviceContext::IASetIndexBuffer(0, DXGI_FORMAT_UNKNOWN, 0); 1827 GalliumD3D11DeviceContext::RSSetState(0); 1828 GalliumD3D11DeviceContext::OMSetDepthStencilState(0, 0); 1829 GalliumD3D11DeviceContext::OMSetBlendState(0, (float*)zero_data, ~0); 1830 GalliumD3D11DeviceContext::SetPredication(0, 0); 1831 GalliumD3D11DeviceContext::IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED); 1832 1833 GalliumD3D11DeviceContext::PSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data); 1834 GalliumD3D11DeviceContext::GSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data); 1835 GalliumD3D11DeviceContext::VSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data); 1836 #if API >= 11 1837 GalliumD3D11DeviceContext::HSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data); 1838 GalliumD3D11DeviceContext::DSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data); 1839 GalliumD3D11DeviceContext::CSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data); 1840 #endif 1841 1842 GalliumD3D11DeviceContext::IASetVertexBuffers(0, num_vertex_buffers, (ID3D11Buffer**)zero_data, (unsigned*)zero_data, (unsigned*)zero_data); 1843 #if API >= 11 1844 GalliumD3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews(0, 0, 0 , 0, 0, 0, 0); 1845 #else 1846 GalliumD3D11DeviceContext::OMSetRenderTargets(0, 0, 0 ); 1847 #endif 1848 GalliumD3D11DeviceContext::SOSetTargets(0, 0, 0); 1849 1850 GalliumD3D11DeviceContext::PSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_PS], (ID3D11ShaderResourceView**)zero_data); 1851 GalliumD3D11DeviceContext::GSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_GS], (ID3D11ShaderResourceView**)zero_data); 1852 GalliumD3D11DeviceContext::VSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_VS], (ID3D11ShaderResourceView**)zero_data); 1853 #if API >= 11 1854 GalliumD3D11DeviceContext::HSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_HS], (ID3D11ShaderResourceView**)zero_data); 1855 GalliumD3D11DeviceContext::DSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_DS], (ID3D11ShaderResourceView**)zero_data); 1856 GalliumD3D11DeviceContext::CSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_CS], (ID3D11ShaderResourceView**)zero_data); 1857 #endif 1858 1859 GalliumD3D11DeviceContext::PSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_PS], (ID3D11SamplerState**)zero_data); 1860 GalliumD3D11DeviceContext::GSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_GS], (ID3D11SamplerState**)zero_data); 1861 GalliumD3D11DeviceContext::VSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_VS], (ID3D11SamplerState**)zero_data); 1862 #if API >= 11 1863 GalliumD3D11DeviceContext::HSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_HS], (ID3D11SamplerState**)zero_data); 1864 GalliumD3D11DeviceContext::DSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_DS], (ID3D11SamplerState**)zero_data); 1865 GalliumD3D11DeviceContext::CSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_CS], (ID3D11SamplerState**)zero_data); 1866 #endif 1867 1868 GalliumD3D11DeviceContext::RSSetViewports(0, 0); 1869 GalliumD3D11DeviceContext::RSSetScissorRects(0, 0); 1870 } 1871 1872 virtual void STDMETHODCALLTYPE Flush(void) 1873 { 1874 SYNCHRONIZED; 1875 pipe->flush(pipe, 0); 1876 } 1877 1878 /* In Direct3D 10, if the reference count of an object drops to 0, it is automatically 1879 * cleanly unbound from the pipeline. 1880 * In Direct3D 11, the pipeline holds a reference. 1881 * 1882 * Note that instead of always scanning the pipeline on destruction, we could 1883 * maintain the internal reference count on DirectX 10 and use it to check if an 1884 * object is still bound. 1885 * Presumably, on average, scanning is faster if the application is well written. 1886 */ 1887 #if API < 11 1888 #define IMPLEMENT_SIMPLE_UNBIND(name, member, gallium, def) \ 1889 void Unbind##name(ID3D11##name* state) \ 1890 { \ 1891 SYNCHRONIZED; \ 1892 if((void*)state == (void*)member.p) \ 1893 { \ 1894 member.p = 0; \ 1895 pipe->bind_##gallium##_state(pipe, default_##def); \ 1896 } \ 1897 } 1898 IMPLEMENT_SIMPLE_UNBIND(BlendState, blend_state, blend, blend) 1899 IMPLEMENT_SIMPLE_UNBIND(RasterizerState, rasterizer_state, rasterizer, rasterizer) 1900 IMPLEMENT_SIMPLE_UNBIND(DepthStencilState, depth_stencil_state, depth_stencil_alpha, depth_stencil) 1901 IMPLEMENT_SIMPLE_UNBIND(InputLayout, input_layout, vertex_elements, input_layout) 1902 IMPLEMENT_SIMPLE_UNBIND(PixelShader, shaders[D3D11_STAGE_PS], fs, shaders[D3D11_STAGE_PS]) 1903 IMPLEMENT_SIMPLE_UNBIND(VertexShader, shaders[D3D11_STAGE_VS], vs, shaders[D3D11_STAGE_VS]) 1904 IMPLEMENT_SIMPLE_UNBIND(GeometryShader, shaders[D3D11_STAGE_GS], gs, shaders[D3D11_STAGE_GS]) 1905 1906 void UnbindPredicate(ID3D11Predicate* predicate) 1907 { 1908 SYNCHRONIZED; 1909 if(predicate == render_predicate) 1910 { 1911 render_predicate.p = NULL; 1912 render_predicate_value = 0; 1913 pipe->render_condition(pipe, 0, 0); 1914 } 1915 } 1916 1917 void UnbindSamplerState(ID3D11SamplerState* state) 1918 { 1919 SYNCHRONIZED; 1920 for(unsigned s = 0; s < D3D11_STAGES; ++s) 1921 { 1922 for(unsigned i = 0; i < num_samplers[s]; ++i) 1923 { 1924 if(samplers[s][i] == state) 1925 { 1926 samplers[s][i].p = NULL; 1927 sampler_csos[s][i] = NULL; 1928 update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + s)); 1929 } 1930 } 1931 } 1932 } 1933 1934 void UnbindBuffer(ID3D11Buffer* buffer) 1935 { 1936 SYNCHRONIZED; 1937 if(buffer == index_buffer) 1938 { 1939 index_buffer.p = 0; 1940 index_format = DXGI_FORMAT_UNKNOWN; 1941 index_offset = 0; 1942 struct pipe_index_buffer ib; 1943 memset(&ib, 0, sizeof(ib)); 1944 pipe->set_index_buffer(pipe, &ib); 1945 } 1946 1947 for(unsigned i = 0; i < num_vertex_buffers; ++i) 1948 { 1949 if(buffer == input_buffers[i]) 1950 { 1951 input_buffers[i].p = 0; 1952 memset(&vertex_buffers[num_vertex_buffers], 0, sizeof(vertex_buffers[num_vertex_buffers])); 1953 update_flags |= UPDATE_VERTEX_BUFFERS; 1954 } 1955 } 1956 1957 for(unsigned s = 0; s < D3D11_STAGES; ++s) 1958 { 1959 for(unsigned i = 0; i < sizeof(constant_buffers) / sizeof(constant_buffers[0]); ++i) 1960 { 1961 if(constant_buffers[s][i] == buffer) 1962 { 1963 constant_buffers[s][i] = (ID3D10Buffer*)NULL; 1964 pipe_set_constant_buffer(pipe, s, i, NULL); 1965 } 1966 } 1967 } 1968 } 1969 1970 void UnbindDepthStencilView(ID3D11DepthStencilView * view) 1971 { 1972 SYNCHRONIZED; 1973 if(view == depth_stencil_view) 1974 { 1975 depth_stencil_view.p = NULL; 1976 set_framebuffer(); 1977 } 1978 } 1979 1980 void UnbindRenderTargetView(ID3D11RenderTargetView* view) 1981 { 1982 SYNCHRONIZED; 1983 bool any_bound = false; 1984 for(unsigned i = 0; i < num_render_target_views; ++i) 1985 { 1986 if(render_target_views[i] == view) 1987 { 1988 render_target_views[i].p = NULL; 1989 any_bound = true; 1990 } 1991 } 1992 if(any_bound) 1993 set_framebuffer(); 1994 } 1995 1996 void UnbindShaderResourceView(ID3D11ShaderResourceView* view) 1997 { 1998 SYNCHRONIZED; 1999 for(unsigned s = 0; s < D3D11_STAGES; ++s) 2000 { 2001 for(unsigned i = 0; i < num_shader_resource_views[s]; ++i) 2002 { 2003 if(shader_resource_views[s][i] == view) 2004 { 2005 shader_resource_views[s][i].p = NULL; 2006 sampler_views[s][i] = NULL; 2007 update_flags |= (1 << (UPDATE_VIEWS_SHIFT + s)); 2008 } 2009 } 2010 } 2011 } 2012 #endif 2013 2014 #undef SYNCHRONIZED 2015 }; 2016 2017 #if API >= 11 2018 /* This approach serves two purposes. 2019 * First, we don't want to do an atomic operation to manipulate the reference 2020 * count every time something is bound/unbound to the pipeline, since they are 2021 * expensive. 2022 * Fortunately, the immediate context can only be used by a single thread, so 2023 * we don't have to use them, as long as a separate reference count is used 2024 * (see dual_refcnt_t). 2025 * 2026 * Second, we want to avoid the Device -> DeviceContext -> bound DeviceChild -> Device 2027 * garbage cycle. 2028 * To avoid it, DeviceChild doesn't hold a reference to Device as usual, but adds 2029 * one for each external reference count, while internal nonatomic_add_ref doesn't 2030 * add any. 2031 * 2032 * Note that ideally we would to eliminate the non-atomic op too, but this is more 2033 * complicated, since we would either need to use garbage collection and give up 2034 * deterministic destruction (especially bad for large textures), or scan the whole 2035 * pipeline state every time the reference count of object drops to 0, which risks 2036 * pathological slowdowns. 2037 * 2038 * Since this microoptimization should matter relatively little, let's avoid it for now. 2039 * 2040 * Note that deferred contexts don't use this, since as a whole, they must thread-safe. 2041 * Eliminating the atomic ops for deferred contexts seems substantially harder. 2042 * This might be a problem if they are used in a one-shot multithreaded rendering 2043 * fashion, where SMP cacheline bouncing on the reference count may be visible. 2044 * 2045 * The idea would be to attach a structure of reference counts indexed by deferred 2046 * context id to each object. Ideally, this should be organized like ext2 block pointers. 2047 * 2048 * Every deferred context would get a reference count in its own cacheline. 2049 * The external count is protected by a lock bit, and there is also a "lock bit" in each 2050 * internal count. 2051 * 2052 * When the external count has to be dropped to 0, the lock bit is taken and all internal 2053 * reference counts are scanned, taking a count of them. A flag would also be set on them. 2054 * Deferred context manipulation would notice the flag, and update the count. 2055 * Once the count goes to zero, the object is freed. 2056 * 2057 * The problem of this is that if the external reference count ping-pongs between 2058 * zero and non-zero, the scans will take a lot of time. 2059 * 2060 * The idea to solve this is to compute the scans in a binary-tree like fashion, where 2061 * each binary tree node would have a "determined bit", which would be invalidated 2062 * by manipulations. 2063 * 2064 * However, all this complexity might actually be a loss in most cases, so let's just 2065 * stick to a single atomic refcnt for now. 2066 * 2067 * Also, we don't even support deferred contexts yet, so this can wait. 2068 */ 2069 struct nonatomic_device_child_ptr_traits 2070 { 2071 static void add_ref(void* p) 2072 { 2073 if(p) 2074 ((GalliumD3D11DeviceChild<>*)p)->nonatomic_add_ref(); 2075 } 2076 2077 static void release(void* p) 2078 { 2079 if(p) 2080 ((GalliumD3D11DeviceChild<>*)p)->nonatomic_release(); 2081 } 2082 }; 2083 2084 struct GalliumD3D11ImmediateDeviceContext 2085 : public GalliumD3D11DeviceContext<nonatomic_device_child_ptr_traits> 2086 { 2087 GalliumD3D11ImmediateDeviceContext(GalliumD3D11Screen* device, pipe_context* pipe, unsigned context_flags = 0) 2088 : GalliumD3D11DeviceContext<nonatomic_device_child_ptr_traits>(device, pipe, context_flags) 2089 { 2090 // not necessary, but tests that the API at least basically works 2091 ClearState(); 2092 } 2093 2094 /* we do this since otherwise we would have a garbage cycle between this and the device */ 2095 virtual ULONG STDMETHODCALLTYPE AddRef() 2096 { 2097 return this->device->AddRef(); 2098 } 2099 2100 virtual ULONG STDMETHODCALLTYPE Release() 2101 { 2102 return this->device->Release(); 2103 } 2104 2105 virtual D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType() 2106 { 2107 return D3D11_DEVICE_CONTEXT_IMMEDIATE; 2108 } 2109 }; 2110 2111 static ID3D11DeviceContext* GalliumD3D11ImmediateDeviceContext_Create(GalliumD3D11Screen* device, struct pipe_context* pipe, bool owns_pipe) 2112 { 2113 return new GalliumD3D11ImmediateDeviceContext(device, pipe, owns_pipe); 2114 } 2115 2116 static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(ID3D11DeviceContext* context) 2117 { 2118 ((GalliumD3D11ImmediateDeviceContext*)context)->RestoreGalliumState(); 2119 } 2120 2121 static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(ID3D11DeviceContext* context) 2122 { 2123 ((GalliumD3D11ImmediateDeviceContext*)context)->RestoreGalliumStateBlitOnly(); 2124 } 2125 2126 static void GalliumD3D11ImmediateDeviceContext_Destroy(ID3D11DeviceContext* context) 2127 { 2128 delete (GalliumD3D11ImmediateDeviceContext*)context; 2129 } 2130 #endif 2131