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