d3d11_screen.h revision 14193da589275969be31dbdb3280bb48cd24d0c0
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 27DEBUG_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 */ 33static 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 */ 42static 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 */ 55static 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 70static 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 92template<bool threadsafe> 93struct 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.scissor = !!rasterizer_desc->ScissorEnable; 582 state.multisample = !!rasterizer_desc->MultisampleEnable; 583 state.line_smooth = !!rasterizer_desc->AntialiasedLineEnable; 584 state.flatshade_first = 1; 585 state.line_width = 1.0f; 586 state.point_size = 1.0f; 587 588 /* TODO: is this correct? */ 589 state.point_quad_rasterization = 1; 590 591 if(!out_rasterizer_state) 592 return S_FALSE; 593 594 void* object = immediate_pipe->create_rasterizer_state(immediate_pipe, &state); 595 if(!object) 596 return E_FAIL; 597 598 *out_rasterizer_state = new GalliumD3D11RasterizerState(this, object, *rasterizer_desc, !rasterizer_desc->DepthClipEnable); 599 return S_OK; 600 } 601 602 virtual HRESULT STDMETHODCALLTYPE CreateSamplerState( 603 const D3D11_SAMPLER_DESC *sampler_desc, 604 ID3D11SamplerState **out_sampler_state) 605 { 606 SYNCHRONIZED; 607 608 pipe_sampler_state state; 609 memset(&state, 0, sizeof(state)); 610 state.normalized_coords = 1; 611 state.min_mip_filter = (sampler_desc->Filter & 1); 612 state.mag_img_filter = ((sampler_desc->Filter >> 2) & 1); 613 state.min_img_filter = ((sampler_desc->Filter >> 4) & 1); 614 if(sampler_desc->Filter & 0x40) 615 state.max_anisotropy = sampler_desc->MaxAnisotropy; 616 if(sampler_desc->Filter & 0x80) 617 { 618 state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; 619 state.compare_func = sampler_desc->ComparisonFunc - 1; 620 } 621 state.wrap_s = d3d11_to_pipe_wrap[sampler_desc->AddressU]; 622 state.wrap_t = d3d11_to_pipe_wrap[sampler_desc->AddressV]; 623 state.wrap_r = d3d11_to_pipe_wrap[sampler_desc->AddressW]; 624 state.lod_bias = sampler_desc->MipLODBias; 625 memcpy(state.border_color.f, sampler_desc->BorderColor, sizeof(state.border_color)); 626 state.min_lod = sampler_desc->MinLOD; 627 state.max_lod = sampler_desc->MaxLOD; 628 629 if(!out_sampler_state) 630 return S_FALSE; 631 632 void* object = immediate_pipe->create_sampler_state(immediate_pipe, &state); 633 if(!object) 634 return E_FAIL; 635 636 *out_sampler_state = new GalliumD3D11SamplerState(this, object, *sampler_desc); 637 return S_OK; 638 } 639 640 virtual HRESULT STDMETHODCALLTYPE CreateInputLayout( 641 const D3D11_INPUT_ELEMENT_DESC *input_element_descs, 642 unsigned count, 643 const void *shader_bytecode_with_input_signature, 644 SIZE_T bytecode_length, 645 ID3D11InputLayout **out_input_layout) 646 { 647 SYNCHRONIZED; 648 649 if(count > D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT) 650 return E_INVALIDARG; 651 assert(D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT <= PIPE_MAX_ATTRIBS); 652 653 // putting semantics matching in the core API seems to be a (minor) design mistake 654 655 struct dxbc_chunk_signature* sig = dxbc_find_signature(shader_bytecode_with_input_signature, bytecode_length, DXBC_FIND_INPUT_SIGNATURE); 656 D3D11_SIGNATURE_PARAMETER_DESC* params; 657 unsigned num_params = dxbc_parse_signature(sig, ¶ms); 658 659 typedef std::unordered_map<std::pair<c_string, unsigned>, unsigned> semantic_to_idx_map_t; 660 semantic_to_idx_map_t semantic_to_idx_map; 661 for(unsigned i = 0; i < count; ++i) 662 semantic_to_idx_map[std::make_pair(c_string(input_element_descs[i].SemanticName), input_element_descs[i].SemanticIndex)] = i; 663 664 struct pipe_vertex_element elements[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT]; 665 666 enum pipe_format formats[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT]; 667 unsigned offsets[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT]; 668 669 offsets[0] = 0; 670 for(unsigned i = 0; i < count; ++i) 671 { 672 formats[i] = dxgi_to_pipe_format[input_element_descs[i].Format]; 673 674 if(likely(input_element_descs[i].AlignedByteOffset != D3D11_APPEND_ALIGNED_ELEMENT)) 675 { 676 offsets[i] = input_element_descs[i].AlignedByteOffset; 677 } 678 else if(i > 0) 679 { 680 unsigned align_mask = util_format_description(formats[i])->channel[0].size; 681 if(align_mask & 7) // e.g. R10G10B10A2 682 align_mask = 32; 683 align_mask = (align_mask / 8) - 1; 684 685 offsets[i] = (offsets[i - 1] + util_format_get_blocksize(formats[i - 1]) + align_mask) & ~align_mask; 686 } 687 } 688 689 // TODO: check for & report errors (e.g. ambiguous layouts, unmatched semantics) 690 691 unsigned num_params_to_use = 0; 692 for(unsigned i = 0; i < num_params && num_params_to_use < D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT; ++i) 693 { 694 if(!strcasecmp(params[i].SemanticName, "SV_INSTANCEID") || 695 !strcasecmp(params[i].SemanticName, "SV_VERTEXID")) 696 continue; 697 const unsigned n = num_params_to_use++; 698 699 semantic_to_idx_map_t::iterator iter = semantic_to_idx_map.find(std::make_pair(c_string(params[i].SemanticName), params[i].SemanticIndex)); 700 701 if(iter != semantic_to_idx_map.end()) 702 { 703 unsigned idx = iter->second; 704 705 elements[n].src_format = formats[idx]; 706 elements[n].src_offset = offsets[idx]; 707 elements[n].vertex_buffer_index = input_element_descs[idx].InputSlot; 708 elements[n].instance_divisor = input_element_descs[idx].InstanceDataStepRate; 709 if (input_element_descs[idx].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA) 710 if (elements[n].instance_divisor == 0) 711 elements[n].instance_divisor = ~0; // XXX: can't specify 'never' to gallium 712 } 713 else 714 { 715 // XXX: undefined input, is this valid or should we return an error ? 716 elements[n].src_format = PIPE_FORMAT_NONE; 717 elements[n].src_offset = 0; 718 elements[n].vertex_buffer_index = 0; 719 elements[n].instance_divisor = 0; 720 } 721 } 722 723 free(params); 724 725 if(!out_input_layout) 726 return S_FALSE; 727 728 void* object = immediate_pipe->create_vertex_elements_state(immediate_pipe, num_params_to_use, elements); 729 if(!object) 730 return E_FAIL; 731 732 *out_input_layout = new GalliumD3D11InputLayout(this, object); 733 return S_OK; 734 } 735 736 static unsigned d3d11_to_pipe_bind_flags(unsigned bind_flags) 737 { 738 unsigned bind = 0; 739 if(bind_flags & D3D11_BIND_VERTEX_BUFFER) 740 bind |= PIPE_BIND_VERTEX_BUFFER; 741 if(bind_flags & D3D11_BIND_INDEX_BUFFER) 742 bind |= PIPE_BIND_INDEX_BUFFER; 743 if(bind_flags & D3D11_BIND_CONSTANT_BUFFER) 744 bind |= PIPE_BIND_CONSTANT_BUFFER; 745 if(bind_flags & D3D11_BIND_SHADER_RESOURCE) 746 bind |= PIPE_BIND_SAMPLER_VIEW; 747 if(bind_flags & D3D11_BIND_STREAM_OUTPUT) 748 bind |= PIPE_BIND_STREAM_OUTPUT; 749 if(bind_flags & D3D11_BIND_RENDER_TARGET) 750 bind |= PIPE_BIND_RENDER_TARGET; 751 if(bind_flags & D3D11_BIND_DEPTH_STENCIL) 752 bind |= PIPE_BIND_DEPTH_STENCIL; 753 return bind; 754 } 755 756 inline HRESULT create_resource( 757 pipe_texture_target target, 758 unsigned width, 759 unsigned height, 760 unsigned depth, 761 unsigned mip_levels, 762 unsigned array_size, 763 DXGI_FORMAT format, 764 const DXGI_SAMPLE_DESC* SampleDesc, 765 D3D11_USAGE usage, 766 unsigned bind_flags, 767 unsigned c_p_u_access_flags, 768 unsigned misc_flags, 769 const D3D11_SUBRESOURCE_DATA *initial_data, 770 DXGI_USAGE dxgi_usage, 771 struct pipe_resource** ppresource 772 ) 773 { 774 if(invalid(format >= DXGI_FORMAT_COUNT)) 775 return E_INVALIDARG; 776 if(misc_flags & D3D11_RESOURCE_MISC_TEXTURECUBE) 777 { 778 if(target != PIPE_TEXTURE_2D) 779 return E_INVALIDARG; 780 target = PIPE_TEXTURE_CUBE; 781 if(array_size % 6) 782 return E_INVALIDARG; 783 } 784 else if(array_size > 1) 785 { 786 switch (target) { 787 case PIPE_TEXTURE_1D: target = PIPE_TEXTURE_1D_ARRAY; break; 788 case PIPE_TEXTURE_2D: target = PIPE_TEXTURE_2D_ARRAY; break; 789 default: 790 return E_INVALIDARG; 791 } 792 } 793 /* TODO: msaa */ 794 struct pipe_resource templat; 795 memset(&templat, 0, sizeof(templat)); 796 templat.target = target; 797 templat.width0 = width; 798 templat.height0 = height; 799 templat.depth0 = depth; 800 templat.array_size = array_size; 801 if(mip_levels) 802 templat.last_level = mip_levels - 1; 803 else 804 templat.last_level = MAX2(MAX2(util_logbase2(templat.width0), util_logbase2(templat.height0)), util_logbase2(templat.depth0)); 805 templat.format = dxgi_to_pipe_format[format]; 806 if(bind_flags & D3D11_BIND_DEPTH_STENCIL) { 807 // colour formats are not depth-renderable, but depth/stencil-formats may be colour-renderable 808 switch(format) 809 { 810 case DXGI_FORMAT_R32_TYPELESS: templat.format = PIPE_FORMAT_Z32_FLOAT; break; 811 case DXGI_FORMAT_R16_TYPELESS: templat.format = PIPE_FORMAT_Z16_UNORM; break; 812 default: 813 break; 814 } 815 } 816 templat.bind = d3d11_to_pipe_bind_flags(bind_flags); 817 if(c_p_u_access_flags & D3D11_CPU_ACCESS_READ) 818 templat.bind |= PIPE_BIND_TRANSFER_READ; 819 if(c_p_u_access_flags & D3D11_CPU_ACCESS_WRITE) 820 templat.bind |= PIPE_BIND_TRANSFER_WRITE; 821 if(misc_flags & D3D11_RESOURCE_MISC_SHARED) 822 templat.bind |= PIPE_BIND_SHARED; 823 if(misc_flags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE) 824 templat.bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE; 825 if(dxgi_usage & DXGI_USAGE_BACK_BUFFER) 826 templat.bind |= PIPE_BIND_DISPLAY_TARGET; 827 templat.usage = d3d11_to_pipe_usage[usage]; 828 if(invalid(!templat.format)) 829 return E_NOTIMPL; 830 831 if(!ppresource) 832 return S_FALSE; 833 834 struct pipe_resource* resource = screen->resource_create(screen, &templat); 835 if(!resource) 836 return E_FAIL; 837 if(initial_data) 838 { 839 for(unsigned slice = 0; slice < array_size; ++slice) 840 { 841 for(unsigned level = 0; level <= templat.last_level; ++level) 842 { 843 struct pipe_box box; 844 box.x = box.y = 0; 845 box.z = slice; 846 box.width = u_minify(width, level); 847 box.height = u_minify(height, level); 848 box.depth = u_minify(depth, level); 849 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); 850 ++initial_data; 851 } 852 } 853 } 854 *ppresource = resource; 855 return S_OK; 856 } 857 858 static unsigned d3d_to_dxgi_usage(unsigned bind, unsigned misc) 859 { 860 unsigned dxgi_usage = 0; 861 if(bind |= D3D11_BIND_RENDER_TARGET) 862 dxgi_usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT; 863 if(bind & D3D11_BIND_SHADER_RESOURCE) 864 dxgi_usage |= DXGI_USAGE_SHADER_INPUT; 865#if API >= 11 866 if(bind & D3D11_BIND_UNORDERED_ACCESS) 867 dxgi_usage |= DXGI_USAGE_UNORDERED_ACCESS; 868#endif 869 if(misc & D3D11_RESOURCE_MISC_SHARED) 870 dxgi_usage |= DXGI_USAGE_SHARED; 871 return dxgi_usage; 872 } 873 874 virtual HRESULT STDMETHODCALLTYPE CreateTexture1D( 875 const D3D11_TEXTURE1D_DESC *desc, 876 const D3D11_SUBRESOURCE_DATA *initial_data, 877 ID3D11Texture1D **out_texture1d) 878 { 879 SYNCHRONIZED; 880 881 struct pipe_resource* resource; 882 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags); 883 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); 884 if(hr != S_OK) 885 return hr; 886 D3D11_TEXTURE1D_DESC cdesc = *desc; 887 cdesc.MipLevels = resource->last_level + 1; 888 *out_texture1d = new GalliumD3D11Texture1D(this, resource, cdesc, dxgi_usage); 889 return S_OK; 890 } 891 892 virtual HRESULT STDMETHODCALLTYPE CreateTexture2D( 893 const D3D11_TEXTURE2D_DESC *desc, 894 const D3D11_SUBRESOURCE_DATA *initial_data, 895 ID3D11Texture2D **out_texture2d) 896 { 897 SYNCHRONIZED; 898 899 struct pipe_resource* resource; 900 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags); 901 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); 902 if(hr != S_OK) 903 return hr; 904 D3D11_TEXTURE2D_DESC cdesc = *desc; 905 cdesc.MipLevels = resource->last_level + 1; 906 if(cdesc.MipLevels == 1 && cdesc.ArraySize == 1) 907 *out_texture2d = new GalliumD3D11Surface(this, resource, cdesc, dxgi_usage); 908 else 909 *out_texture2d = new GalliumD3D11Texture2D(this, resource, cdesc, dxgi_usage); 910 return S_OK; 911 } 912 913 virtual HRESULT STDMETHODCALLTYPE CreateTexture3D( 914 const D3D11_TEXTURE3D_DESC *desc, 915 const D3D11_SUBRESOURCE_DATA *initial_data, 916 ID3D11Texture3D **out_texture3d) 917 { 918 SYNCHRONIZED; 919 920 struct pipe_resource* resource; 921 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags); 922 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); 923 if(hr != S_OK) 924 return hr; 925 D3D11_TEXTURE3D_DESC cdesc = *desc; 926 cdesc.MipLevels = resource->last_level + 1; 927 *out_texture3d = new GalliumD3D11Texture3D(this, resource, cdesc, dxgi_usage); 928 return S_OK; 929 } 930 931 virtual HRESULT STDMETHODCALLTYPE CreateBuffer( 932 const D3D11_BUFFER_DESC *desc, 933 const D3D11_SUBRESOURCE_DATA *initial_data, 934 ID3D11Buffer **out_buffer) 935 { 936 SYNCHRONIZED; 937 938 struct pipe_resource* resource; 939 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags); 940 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); 941 if(hr != S_OK) 942 return hr; 943 *out_buffer = new GalliumD3D11Buffer(this, resource, *desc, dxgi_usage); 944 return S_OK; 945 } 946 947 virtual HRESULT STDMETHODCALLTYPE OpenGalliumResource( 948 struct pipe_resource* resource, 949 IUnknown** dxgi_resource) 950 { 951 SYNCHRONIZED; 952 953 /* TODO: maybe support others */ 954 assert(resource->target == PIPE_TEXTURE_2D); 955 *dxgi_resource = 0; 956 D3D11_TEXTURE2D_DESC desc; 957 memset(&desc, 0, sizeof(desc)); 958 desc.Width = resource->width0; 959 desc.Height = resource->height0; 960 init_pipe_to_dxgi_format(); 961 desc.Format = pipe_to_dxgi_format[resource->format]; 962 desc.SampleDesc.Count = resource->nr_samples; 963 desc.SampleDesc.Quality = 0; 964 desc.ArraySize = 1; 965 desc.MipLevels = resource->last_level + 1; 966 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 967 if(resource->bind & PIPE_BIND_RENDER_TARGET) 968 desc.BindFlags |= D3D11_BIND_RENDER_TARGET; 969 if(resource->bind & PIPE_BIND_DEPTH_STENCIL) 970 desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL; 971 if(resource->bind & PIPE_BIND_SAMPLER_VIEW) 972 desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; 973 if(resource->bind & PIPE_BIND_SHARED) 974 desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED; 975 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc.BindFlags, desc.MiscFlags); 976 if(desc.MipLevels == 1 && desc.ArraySize == 1) 977 *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Surface(this, resource, desc, dxgi_usage); 978 else 979 *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Texture2D(this, resource, desc, dxgi_usage); 980 return S_OK; 981 } 982 983 virtual HRESULT STDMETHODCALLTYPE CreateSurface( 984 const DXGI_SURFACE_DESC *dxgi_desc, 985 unsigned count, 986 DXGI_USAGE usage, 987 const DXGI_SHARED_RESOURCE *shared_resource, 988 IDXGISurface **out_surface) 989 { 990 SYNCHRONIZED; 991 992 D3D11_TEXTURE2D_DESC desc; 993 memset(&desc, 0, sizeof(desc)); 994 995 struct pipe_resource* resource; 996 desc.Width = dxgi_desc->Width; 997 desc.Height = dxgi_desc->Height; 998 desc.Format = dxgi_desc->Format; 999 desc.SampleDesc = dxgi_desc->SampleDesc; 1000 desc.ArraySize = count; 1001 desc.MipLevels = 1; 1002 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 1003 if(usage & DXGI_USAGE_RENDER_TARGET_OUTPUT) 1004 desc.BindFlags |= D3D11_BIND_RENDER_TARGET; 1005 if(usage & DXGI_USAGE_SHADER_INPUT) 1006 desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; 1007#if API >= 11 1008 if(usage & DXGI_USAGE_UNORDERED_ACCESS) 1009 desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; 1010#endif 1011 if(usage & DXGI_USAGE_SHARED) 1012 desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED; 1013 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); 1014 if(hr != S_OK) 1015 return hr; 1016 *out_surface = new GalliumD3D11Surface(this, resource, desc, usage); 1017 return S_OK; 1018 } 1019 1020 virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView( 1021 ID3D11Resource *iresource, 1022 const D3D11_SHADER_RESOURCE_VIEW_DESC *desc, 1023 ID3D11ShaderResourceView **out_srv) 1024 { 1025#if API >= 11 1026 D3D11_SHADER_RESOURCE_VIEW_DESC def_desc; 1027#else 1028 if(desc->ViewDimension == D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY) 1029 return E_INVALIDARG; 1030 D3D10_SHADER_RESOURCE_VIEW_DESC1 desc1; 1031 memset(&desc1, 0, sizeof(desc1)); 1032 memcpy(&desc1, desc, sizeof(*desc)); 1033 return CreateShaderResourceView1(iresource, &desc1, (ID3D10ShaderResourceView1**)out_srv); 1034 } 1035 1036 virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView1( 1037 ID3D11Resource *iresource, 1038 const D3D10_SHADER_RESOURCE_VIEW_DESC1 *desc, 1039 ID3D10ShaderResourceView1 **out_srv) 1040 { 1041 D3D10_SHADER_RESOURCE_VIEW_DESC1 def_desc; 1042#endif 1043 SYNCHRONIZED; 1044 1045 const struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource; 1046 1047 if(!desc) 1048 { 1049 init_pipe_to_dxgi_format(); 1050 memset(&def_desc, 0, sizeof(def_desc)); 1051 def_desc.Format = pipe_to_dxgi_format[resource->format]; 1052 switch(resource->target) 1053 { 1054 case PIPE_BUFFER: 1055 def_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; 1056 def_desc.Buffer.ElementWidth = resource->width0; 1057 break; 1058 case PIPE_TEXTURE_1D: 1059 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; 1060 def_desc.Texture1D.MipLevels = resource->last_level + 1; 1061 break; 1062 case PIPE_TEXTURE_1D_ARRAY: 1063 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; 1064 def_desc.Texture1DArray.MipLevels = resource->last_level + 1; 1065 def_desc.Texture1DArray.ArraySize = resource->array_size; 1066 break; 1067 case PIPE_TEXTURE_2D: 1068 case PIPE_TEXTURE_RECT: 1069 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 1070 def_desc.Texture2D.MipLevels = resource->last_level + 1; 1071 break; 1072 case PIPE_TEXTURE_2D_ARRAY: 1073 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; 1074 def_desc.Texture2DArray.MipLevels = resource->last_level + 1; 1075 def_desc.Texture2DArray.ArraySize = resource->array_size; 1076 break; 1077 case PIPE_TEXTURE_3D: 1078 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; 1079 def_desc.Texture3D.MipLevels = resource->last_level + 1; 1080 break; 1081 case PIPE_TEXTURE_CUBE: 1082 if(resource->array_size > 6) 1083 { 1084 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY; 1085 def_desc.TextureCubeArray.NumCubes = resource->array_size / 6; 1086 } 1087 else 1088 { 1089 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; 1090 } 1091 def_desc.TextureCube.MipLevels = resource->last_level + 1; 1092 break; 1093 default: 1094 return E_INVALIDARG; 1095 } 1096 desc = &def_desc; 1097 } 1098 1099 struct pipe_sampler_view templat; 1100 memset(&templat, 0, sizeof(templat)); 1101 if(invalid(format >= DXGI_FORMAT_COUNT)) 1102 return E_INVALIDARG; 1103 templat.format = (desc->Format == DXGI_FORMAT_UNKNOWN) ? resource->format : dxgi_to_pipe_format[desc->Format]; 1104 if(!templat.format) 1105 return E_NOTIMPL; 1106 templat.swizzle_r = PIPE_SWIZZLE_RED; 1107 templat.swizzle_g = PIPE_SWIZZLE_GREEN; 1108 templat.swizzle_b = PIPE_SWIZZLE_BLUE; 1109 templat.swizzle_a = PIPE_SWIZZLE_ALPHA; 1110 1111 templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource; 1112 switch(desc->ViewDimension) 1113 { 1114 case D3D11_SRV_DIMENSION_TEXTURE1DARRAY: 1115 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: 1116 case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY: 1117 templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice; 1118 templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice + desc->Texture1DArray.ArraySize - 1; 1119 if (desc->ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) { 1120 templat.u.tex.first_layer *= 6; 1121 templat.u.tex.last_layer *= 6; 1122 } 1123 // fall through 1124 case D3D11_SRV_DIMENSION_TEXTURE1D: 1125 case D3D11_SRV_DIMENSION_TEXTURE2D: 1126 case D3D11_SRV_DIMENSION_TEXTURE3D: 1127 case D3D11_SRV_DIMENSION_TEXTURECUBE: 1128 // yes, this works for all of these types 1129 templat.u.tex.first_level = desc->Texture1D.MostDetailedMip; 1130 if(desc->Texture1D.MipLevels == (unsigned)-1) 1131 templat.u.tex.last_level = templat.texture->last_level; 1132 else 1133 templat.u.tex.last_level = templat.u.tex.first_level + desc->Texture1D.MipLevels - 1; 1134 assert(templat.u.tex.last_level >= templat.u.tex.first_level); 1135 break; 1136 case D3D11_SRV_DIMENSION_BUFFER: 1137 templat.u.buf.first_element = desc->Buffer.ElementOffset; 1138 templat.u.buf.last_element = desc->Buffer.ElementOffset + desc->Buffer.ElementWidth - 1; 1139 break; 1140 case D3D11_SRV_DIMENSION_TEXTURE2DMS: 1141 case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: 1142 return E_NOTIMPL; 1143 default: 1144 return E_INVALIDARG; 1145 } 1146 1147 if(!out_srv) 1148 return S_FALSE; 1149 1150 struct pipe_sampler_view* view = immediate_pipe->create_sampler_view(immediate_pipe, templat.texture, &templat); 1151 if(!view) 1152 return E_FAIL; 1153 *out_srv = new GalliumD3D11ShaderResourceView(this, (GalliumD3D11Resource<>*)iresource, view, *desc); 1154 return S_OK; 1155 } 1156 1157#if API >= 11 1158 virtual HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView( 1159 ID3D11Resource *resource, 1160 const D3D11_UNORDERED_ACCESS_VIEW_DESC *desc, 1161 ID3D11UnorderedAccessView **out_uav) 1162 { 1163 SYNCHRONIZED; 1164 1165 return E_NOTIMPL; 1166 1167 // remember to return S_FALSE and not crash if out_u_a_view == 0 and parameters are valid 1168 } 1169#endif 1170 1171 virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView( 1172 ID3D11Resource *iresource, 1173 const D3D11_RENDER_TARGET_VIEW_DESC *desc, 1174 ID3D11RenderTargetView **out_rtv) 1175 { 1176 SYNCHRONIZED; 1177 1178 const struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource; 1179 1180 D3D11_RENDER_TARGET_VIEW_DESC def_desc; 1181 if(!desc) 1182 { 1183 init_pipe_to_dxgi_format(); 1184 memset(&def_desc, 0, sizeof(def_desc)); 1185 def_desc.Format = pipe_to_dxgi_format[resource->format]; 1186 switch(resource->target) 1187 { 1188 case PIPE_BUFFER: 1189 def_desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER; 1190 def_desc.Buffer.ElementWidth = resource->width0; 1191 break; 1192 case PIPE_TEXTURE_1D: 1193 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D; 1194 break; 1195 case PIPE_TEXTURE_1D_ARRAY: 1196 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY; 1197 def_desc.Texture1DArray.ArraySize = resource->array_size; 1198 break; 1199 case PIPE_TEXTURE_2D: 1200 case PIPE_TEXTURE_RECT: 1201 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; 1202 break; 1203 case PIPE_TEXTURE_2D_ARRAY: 1204 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; 1205 def_desc.Texture2DArray.ArraySize = resource->array_size; 1206 break; 1207 case PIPE_TEXTURE_3D: 1208 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; 1209 def_desc.Texture3D.WSize = resource->depth0; 1210 break; 1211 case PIPE_TEXTURE_CUBE: 1212 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; 1213 def_desc.Texture2DArray.ArraySize = 6; 1214 break; 1215 default: 1216 return E_INVALIDARG; 1217 } 1218 desc = &def_desc; 1219 } 1220 1221 struct pipe_surface templat; 1222 memset(&templat, 0, sizeof(templat)); 1223 if(invalid(desc->format >= DXGI_FORMAT_COUNT)) 1224 return E_INVALIDARG; 1225 templat.format = (desc->Format == DXGI_FORMAT_UNKNOWN) ? resource->format : dxgi_to_pipe_format[desc->Format]; 1226 if(!templat.format) 1227 return E_NOTIMPL; 1228 templat.usage = PIPE_BIND_RENDER_TARGET; 1229 templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource; 1230 1231 switch(desc->ViewDimension) 1232 { 1233 case D3D11_RTV_DIMENSION_TEXTURE1D: 1234 case D3D11_RTV_DIMENSION_TEXTURE2D: 1235 templat.u.tex.level = desc->Texture1D.MipSlice; 1236 break; 1237 case D3D11_RTV_DIMENSION_TEXTURE3D: 1238 templat.u.tex.level = desc->Texture3D.MipSlice; 1239 templat.u.tex.first_layer = desc->Texture3D.FirstWSlice; 1240 templat.u.tex.last_layer = desc->Texture3D.FirstWSlice + desc->Texture3D.WSize - 1; 1241 break; 1242 case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: 1243 case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: 1244 templat.u.tex.level = desc->Texture1DArray.MipSlice; 1245 templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice; 1246 templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice + desc->Texture1DArray.ArraySize - 1; 1247 break; 1248 case D3D11_RTV_DIMENSION_BUFFER: 1249 templat.u.buf.first_element = desc->Buffer.ElementOffset; 1250 templat.u.buf.last_element = desc->Buffer.ElementOffset + desc->Buffer.ElementWidth - 1; 1251 break; 1252 case D3D11_RTV_DIMENSION_TEXTURE2DMS: 1253 case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: 1254 return E_NOTIMPL; 1255 default: 1256 return E_INVALIDARG; 1257 } 1258 1259 if(!out_rtv) 1260 return S_FALSE; 1261 1262 struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat); 1263 if(!surface) 1264 return E_FAIL; 1265 *out_rtv = new GalliumD3D11RenderTargetView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc); 1266 return S_OK; 1267 } 1268 1269 virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilView( 1270 ID3D11Resource *iresource, 1271 const D3D11_DEPTH_STENCIL_VIEW_DESC *desc, 1272 ID3D11DepthStencilView **out_depth_stencil_view) 1273 { 1274 SYNCHRONIZED; 1275 1276 const struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource; 1277 1278 D3D11_DEPTH_STENCIL_VIEW_DESC def_desc; 1279 if(!desc) 1280 { 1281 init_pipe_to_dxgi_format(); 1282 memset(&def_desc, 0, sizeof(def_desc)); 1283 def_desc.Format = pipe_to_dxgi_format[resource->format]; 1284 switch(resource->target) 1285 { 1286 case PIPE_TEXTURE_1D: 1287 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D; 1288 break; 1289 case PIPE_TEXTURE_1D_ARRAY: 1290 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY; 1291 def_desc.Texture1DArray.ArraySize = resource->array_size; 1292 break; 1293 case PIPE_TEXTURE_2D: 1294 case PIPE_TEXTURE_RECT: 1295 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; 1296 break; 1297 case PIPE_TEXTURE_2D_ARRAY: 1298 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; 1299 def_desc.Texture2DArray.ArraySize = resource->array_size; 1300 break; 1301 case PIPE_TEXTURE_CUBE: 1302 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; 1303 def_desc.Texture2DArray.ArraySize = 6; 1304 break; 1305 default: 1306 return E_INVALIDARG; 1307 } 1308 desc = &def_desc; 1309 } 1310 1311 struct pipe_surface templat; 1312 memset(&templat, 0, sizeof(templat)); 1313 if(invalid(desc->format >= DXGI_FORMAT_COUNT)) 1314 return E_INVALIDARG; 1315 templat.format = (desc->Format == DXGI_FORMAT_UNKNOWN) ? resource->format : dxgi_to_pipe_format[desc->Format]; 1316 if(!templat.format) 1317 return E_NOTIMPL; 1318 templat.usage = PIPE_BIND_DEPTH_STENCIL; 1319 templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource; 1320 1321 switch(desc->ViewDimension) 1322 { 1323 case D3D11_DSV_DIMENSION_TEXTURE1D: 1324 case D3D11_DSV_DIMENSION_TEXTURE2D: 1325 templat.u.tex.level = desc->Texture1D.MipSlice; 1326 break; 1327 case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: 1328 case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: 1329 templat.u.tex.level = desc->Texture1DArray.MipSlice; 1330 templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice; 1331 templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice + desc->Texture1DArray.ArraySize - 1; 1332 break; 1333 case D3D11_DSV_DIMENSION_TEXTURE2DMS: 1334 case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: 1335 return E_NOTIMPL; 1336 default: 1337 return E_INVALIDARG; 1338 } 1339 1340 if(!out_depth_stencil_view) 1341 return S_FALSE; 1342 1343 struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat); 1344 if(!surface) 1345 return E_FAIL; 1346 *out_depth_stencil_view = new GalliumD3D11DepthStencilView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc); 1347 return S_OK; 1348 } 1349 1350#define D3D1X_SHVER_GEOMETRY_SHADER 2 /* D3D11_SHVER_GEOMETRY_SHADER */ 1351 1352 GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void* shader_bytecode, SIZE_T bytecode_length 1353#if API >= 11 1354 , ID3D11ClassLinkage *class_linkage 1355#endif 1356 , struct pipe_stream_output_info* so_info) 1357 { 1358 bool dump = debug_get_option_dump_shaders(); 1359 1360 std::auto_ptr<sm4_program> sm4(0); 1361 1362 dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(shader_bytecode, bytecode_length); 1363 if(!sm4_chunk) 1364 { 1365 if(so_info) 1366 sm4.reset(new sm4_program()); 1367 } 1368 else 1369 { 1370 sm4.reset(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size))); 1371 // check if this is a dummy GS, in which case we only need a place to store the signature 1372 if(sm4.get() && so_info && sm4->version.type != D3D1X_SHVER_GEOMETRY_SHADER) 1373 sm4.reset(new sm4_program()); 1374 } 1375 if(!sm4.get()) 1376 return 0; 1377 1378 if(dump) 1379 sm4->dump(); 1380 1381 struct dxbc_chunk_signature* sig; 1382 1383 sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_INPUT_SIGNATURE); 1384 if(sig) 1385 sm4->num_params_in = dxbc_parse_signature(sig, &sm4->params_in); 1386 1387 sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_OUTPUT_SIGNATURE); 1388 if(sig) 1389 sm4->num_params_out = dxbc_parse_signature(sig, &sm4->params_out); 1390 1391 sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_PATCH_SIGNATURE); 1392 if(sig) 1393 sm4->num_params_patch = dxbc_parse_signature(sig, &sm4->params_patch); 1394 1395 struct pipe_shader_state tgsi_shader; 1396 memset(&tgsi_shader, 0, sizeof(tgsi_shader)); 1397 if(so_info) 1398 memcpy(&tgsi_shader.stream_output, so_info, sizeof(tgsi_shader.stream_output)); 1399 1400 if(so_info && sm4->version.type != D3D1X_SHVER_GEOMETRY_SHADER) 1401 tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi_linkage_only(*sm4); 1402 else 1403 tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4); 1404 if(!tgsi_shader.tokens) 1405 return 0; 1406 1407 if(dump) 1408 tgsi_dump(tgsi_shader.tokens, 0); 1409 1410 void* shader_cso; 1411 GalliumD3D11Shader<>* shader; 1412 1413 switch(type) 1414 { 1415 case PIPE_SHADER_VERTEX: 1416 shader_cso = immediate_pipe->create_vs_state(immediate_pipe, &tgsi_shader); 1417 shader = (GalliumD3D11Shader<>*)new GalliumD3D11VertexShader(this, shader_cso); 1418 break; 1419 case PIPE_SHADER_FRAGMENT: 1420 shader_cso = immediate_pipe->create_fs_state(immediate_pipe, &tgsi_shader); 1421 shader = (GalliumD3D11Shader<>*)new GalliumD3D11PixelShader(this, shader_cso); 1422 break; 1423 case PIPE_SHADER_GEOMETRY: 1424 shader_cso = immediate_pipe->create_gs_state(immediate_pipe, &tgsi_shader); 1425 shader = (GalliumD3D11Shader<>*)new GalliumD3D11GeometryShader(this, shader_cso); 1426 break; 1427 default: 1428 shader_cso = 0; 1429 shader = 0; 1430 break; 1431 } 1432 1433 free((void*)tgsi_shader.tokens); 1434 return shader; 1435 } 1436 1437#if API >= 11 1438#define CREATE_SHADER_ARGS \ 1439 const void *shader_bytecode, \ 1440 SIZE_T bytecode_length, \ 1441 ID3D11ClassLinkage *class_linkage 1442#define PASS_SHADER_ARGS shader_bytecode, bytecode_length, class_linkage 1443#else 1444#define CREATE_SHADER_ARGS \ 1445 const void *shader_bytecode, \ 1446 SIZE_T bytecode_length 1447#define PASS_SHADER_ARGS shader_bytecode, bytecode_length 1448#endif 1449 1450#define IMPLEMENT_CREATE_SHADER(Stage, GALLIUM) \ 1451 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \ 1452 CREATE_SHADER_ARGS, \ 1453 ID3D11##Stage##Shader **out_shader) \ 1454 { \ 1455 SYNCHRONIZED; \ 1456 GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS, NULL); \ 1457 if(!shader) \ 1458 return E_FAIL; \ 1459 if(out_shader) \ 1460 { \ 1461 *out_shader = shader; \ 1462 return S_OK; \ 1463 } \ 1464 else \ 1465 { \ 1466 shader->Release(); \ 1467 return S_FALSE; \ 1468 } \ 1469 } 1470 1471#define IMPLEMENT_NOTIMPL_CREATE_SHADER(Stage) \ 1472 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \ 1473 CREATE_SHADER_ARGS, \ 1474 ID3D11##Stage##Shader **out_shader) \ 1475 { \ 1476 return E_NOTIMPL; \ 1477 } 1478 1479 IMPLEMENT_CREATE_SHADER(Vertex, VERTEX) 1480 IMPLEMENT_CREATE_SHADER(Pixel, FRAGMENT) 1481 IMPLEMENT_CREATE_SHADER(Geometry, GEOMETRY) 1482#if API >= 11 1483 IMPLEMENT_NOTIMPL_CREATE_SHADER(Hull) 1484 IMPLEMENT_NOTIMPL_CREATE_SHADER(Domain) 1485 IMPLEMENT_NOTIMPL_CREATE_SHADER(Compute) 1486#endif 1487 1488 virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput( 1489 const void *shader_bytecode, 1490 SIZE_T bytecode_length, 1491 const D3D11_SO_DECLARATION_ENTRY *so_declaration, 1492 unsigned num_entries, 1493#if API >= 11 1494 const unsigned *buffer_strides, 1495 unsigned num_strides, 1496 unsigned rasterized_stream, 1497 ID3D11ClassLinkage *class_linkage, 1498#else 1499 UINT output_stream_stride, 1500#endif 1501 ID3D11GeometryShader **out_geometry_shader) 1502 { 1503 SYNCHRONIZED; 1504 GalliumD3D11GeometryShader* gs; 1505 1506#if API >= 11 1507 if(rasterized_stream != 0) 1508 return E_NOTIMPL; // not yet supported by gallium 1509#endif 1510 struct dxbc_chunk_signature* sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_OUTPUT_SIGNATURE); 1511 if(!sig) 1512 return E_INVALIDARG; 1513 D3D11_SIGNATURE_PARAMETER_DESC* out; 1514 unsigned num_outputs = dxbc_parse_signature(sig, &out); 1515 1516 struct pipe_stream_output_info so; 1517 memset(&so, 0, sizeof(so)); 1518 1519#if API >= 11 1520 if(num_strides) 1521 so.stride = buffer_strides[0]; 1522 if(num_strides > 1) 1523 debug_printf("Warning: multiple user-specified strides not implemented !\n"); 1524#else 1525 so.stride = output_stream_stride; 1526#endif 1527 1528 for(unsigned i = 0; i < num_entries; ++i) 1529 { 1530 unsigned j; 1531 for(j = 0; j < num_outputs; ++j) 1532 if(out[j].SemanticIndex == so_declaration[i].SemanticIndex && !strcasecmp(out[j].SemanticName, so_declaration[i].SemanticName)) 1533 break; 1534 if(j >= num_outputs) 1535 continue; 1536 const int first_comp = ffs(out[j].Mask) - 1 + so_declaration[i].StartComponent; 1537 so.output[i].output_buffer = so_declaration[i].OutputSlot; 1538 so.output[i].register_index = out[j].Register; 1539 so.output[i].register_mask = ((1 << so_declaration[i].ComponentCount) - 1) << first_comp; 1540 ++so.num_outputs; 1541 } 1542 if(out) 1543 free(out); 1544 1545 gs = reinterpret_cast<GalliumD3D11GeometryShader*>(create_stage_shader(PIPE_SHADER_GEOMETRY, PASS_SHADER_ARGS, &so)); 1546 if(!gs) 1547 return E_FAIL; 1548 1549 if(!out_geometry_shader) { 1550 gs->Release(); 1551 return S_FALSE; 1552 } 1553 *out_geometry_shader = gs; 1554 1555 return S_OK; 1556 } 1557 1558#if API >= 11 1559 virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage( 1560 ID3D11ClassLinkage **out_linkage) 1561 { 1562 SYNCHRONIZED; 1563 1564 return E_NOTIMPL; 1565 } 1566#endif 1567 1568 virtual HRESULT STDMETHODCALLTYPE CreateQuery( 1569 const D3D11_QUERY_DESC *query_desc, 1570 ID3D11Query **out_query) 1571 { 1572 SYNCHRONIZED; 1573 1574 if(invalid(query_desc->Query >= D3D11_QUERY_COUNT)) 1575 return E_INVALIDARG; 1576 unsigned query_type = d3d11_to_pipe_query[query_desc->Query]; 1577 if(query_type >= PIPE_QUERY_TYPES) 1578 return E_NOTIMPL; 1579 1580 if(!out_query) 1581 return S_FALSE; 1582 1583 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type); 1584 if(!query) 1585 return E_FAIL; 1586 1587 *out_query = new GalliumD3D11Query(this, query, d3d11_query_size[query_desc->Query], *query_desc); 1588 return S_OK; 1589 } 1590 1591 virtual HRESULT STDMETHODCALLTYPE CreatePredicate( 1592 const D3D11_QUERY_DESC *predicate_desc, 1593 ID3D11Predicate **out_predicate) 1594 { 1595 SYNCHRONIZED; 1596 1597 unsigned query_type; 1598 switch(predicate_desc->Query) 1599 { 1600 case D3D11_QUERY_SO_OVERFLOW_PREDICATE: 1601 query_type = PIPE_QUERY_SO_OVERFLOW_PREDICATE; 1602 break; 1603 case D3D11_QUERY_OCCLUSION_PREDICATE: 1604 query_type = PIPE_QUERY_OCCLUSION_PREDICATE; 1605 break; 1606 default: 1607 return E_INVALIDARG; 1608 } 1609 1610 if(out_predicate) 1611 return S_FALSE; 1612 1613 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type); 1614 if(!query) 1615 return E_FAIL; 1616 1617 *out_predicate = new GalliumD3D11Predicate(this, query, sizeof(BOOL), *predicate_desc); 1618 return S_OK; 1619 } 1620 1621 1622 virtual HRESULT STDMETHODCALLTYPE CreateCounter( 1623 const D3D11_COUNTER_DESC *counter_desc, 1624 ID3D11Counter **out_counter) 1625 { 1626 SYNCHRONIZED; 1627 1628 return E_NOTIMPL; 1629 1630 // remember to return S_FALSE if out_counter == NULL and everything is OK 1631 } 1632 1633#if API >= 11 1634 virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext( 1635 unsigned context_flags, 1636 ID3D11DeviceContext **out_deferred_context) 1637 { 1638 SYNCHRONIZED; 1639 1640 // TODO: this will have to be implemented using a new Gallium util module 1641 return E_NOTIMPL; 1642 1643 // remember to return S_FALSE if out_counter == NULL and everything is OK 1644 } 1645#endif 1646 1647 virtual HRESULT STDMETHODCALLTYPE OpenSharedResource( 1648 HANDLE resource, 1649 REFIID iid, 1650 void **out_resource) 1651 { 1652 SYNCHRONIZED; 1653 1654 // TODO: the problem here is that we need to communicate dimensions somehow 1655 return E_NOTIMPL; 1656 1657 // remember to return S_FALSE if out_counter == NULL and everything is OK 1658#if 0 1659 struct pipe_resou rce templat; 1660 struct winsys_handle handle; 1661 handle.stride = 0; 1662 handle.handle = resource; 1663 handle.type = DRM_API_HANDLE_TYPE_SHARED; 1664 screen->resource_from_handle(screen, &templat, &handle); 1665#endif 1666 } 1667 1668#if API < 11 1669 /* these are documented as "Not implemented". 1670 * According to the UMDDI documentation, they apparently turn on a 1671 * (width + 1) x (height + 1) convolution filter for 1-bit textures. 1672 * Probably nothing uses these, assuming it has ever been implemented anywhere. 1673 */ 1674 void STDMETHODCALLTYPE SetTextFilterSize( 1675 UINT width, 1676 UINT height 1677 ) 1678 {} 1679 1680 virtual void STDMETHODCALLTYPE GetTextFilterSize( 1681 UINT *width, 1682 UINT *height 1683 ) 1684 {} 1685#endif 1686 1687#if API >= 11 1688 virtual void STDMETHODCALLTYPE RestoreGalliumState() 1689 { 1690 GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(immediate_context); 1691 } 1692 1693 virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly() 1694 { 1695 GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(immediate_context); 1696 } 1697#endif 1698 1699 virtual struct pipe_context* STDMETHODCALLTYPE GetGalliumContext(void) 1700 { 1701 return immediate_pipe; 1702 } 1703 1704#undef SYNCHRONIZED 1705}; 1706