d3d11_screen.h revision 3dff43d8974f3eab650df613ac56d92a1f81d8ec
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(STREAM_OUTPUT), 76 UTIL_CHECK_CAP(CONDITIONAL_RENDER), 77 UTIL_CHECK_CAP(PRIMITIVE_RESTART), 78 UTIL_CHECK_CAP(TGSI_INSTANCEID), 79 UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8), 80 UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13), 81 UTIL_CHECK_INT(MAX_TEXTURE_ARRAY_LAYERS, 512), 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_STREAM_OUTPUT); 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 GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void* shader_bytecode, SIZE_T bytecode_length 1351#if API >= 11 1352 , ID3D11ClassLinkage *class_linkage 1353#endif 1354 ) 1355 { 1356 bool dump = debug_get_option_dump_shaders(); 1357 1358 dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(shader_bytecode, bytecode_length); 1359 if(!sm4_chunk) 1360 return 0; 1361 1362 std::auto_ptr<sm4_program> sm4(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size))); 1363 if(!sm4.get()) 1364 return 0; 1365 1366 if(dump) 1367 sm4->dump(); 1368 1369 struct dxbc_chunk_signature* sig; 1370 1371 sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_INPUT_SIGNATURE); 1372 if(sig) 1373 sm4->num_params_in = dxbc_parse_signature(sig, &sm4->params_in); 1374 1375 sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_OUTPUT_SIGNATURE); 1376 if(sig) 1377 sm4->num_params_out = dxbc_parse_signature(sig, &sm4->params_out); 1378 1379 sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_PATCH_SIGNATURE); 1380 if(sig) 1381 sm4->num_params_patch = dxbc_parse_signature(sig, &sm4->params_patch); 1382 1383 struct pipe_shader_state tgsi_shader; 1384 memset(&tgsi_shader, 0, sizeof(tgsi_shader)); 1385 tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4); 1386 if(!tgsi_shader.tokens) 1387 return 0; 1388 1389 if(dump) 1390 tgsi_dump(tgsi_shader.tokens, 0); 1391 1392 void* shader_cso; 1393 GalliumD3D11Shader<>* shader; 1394 1395 switch(type) 1396 { 1397 case PIPE_SHADER_VERTEX: 1398 shader_cso = immediate_pipe->create_vs_state(immediate_pipe, &tgsi_shader); 1399 shader = (GalliumD3D11Shader<>*)new GalliumD3D11VertexShader(this, shader_cso); 1400 break; 1401 case PIPE_SHADER_FRAGMENT: 1402 shader_cso = immediate_pipe->create_fs_state(immediate_pipe, &tgsi_shader); 1403 shader = (GalliumD3D11Shader<>*)new GalliumD3D11PixelShader(this, shader_cso); 1404 break; 1405 case PIPE_SHADER_GEOMETRY: 1406 shader_cso = immediate_pipe->create_gs_state(immediate_pipe, &tgsi_shader); 1407 shader = (GalliumD3D11Shader<>*)new GalliumD3D11GeometryShader(this, shader_cso); 1408 break; 1409 default: 1410 shader_cso = 0; 1411 shader = 0; 1412 break; 1413 } 1414 1415 free((void*)tgsi_shader.tokens); 1416 return shader; 1417 } 1418 1419#if API >= 11 1420#define CREATE_SHADER_ARGS \ 1421 const void *shader_bytecode, \ 1422 SIZE_T bytecode_length, \ 1423 ID3D11ClassLinkage *class_linkage 1424#define PASS_SHADER_ARGS shader_bytecode, bytecode_length, class_linkage 1425#else 1426#define CREATE_SHADER_ARGS \ 1427 const void *shader_bytecode, \ 1428 SIZE_T bytecode_length 1429#define PASS_SHADER_ARGS shader_bytecode, bytecode_length 1430#endif 1431 1432#define IMPLEMENT_CREATE_SHADER(Stage, GALLIUM) \ 1433 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \ 1434 CREATE_SHADER_ARGS, \ 1435 ID3D11##Stage##Shader **out_shader) \ 1436 { \ 1437 SYNCHRONIZED; \ 1438 GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS); \ 1439 if(!shader) \ 1440 return E_FAIL; \ 1441 if(out_shader) \ 1442 { \ 1443 *out_shader = shader; \ 1444 return S_OK; \ 1445 } \ 1446 else \ 1447 { \ 1448 shader->Release(); \ 1449 return S_FALSE; \ 1450 } \ 1451 } 1452 1453#define IMPLEMENT_NOTIMPL_CREATE_SHADER(Stage) \ 1454 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \ 1455 CREATE_SHADER_ARGS, \ 1456 ID3D11##Stage##Shader **out_shader) \ 1457 { \ 1458 return E_NOTIMPL; \ 1459 } 1460 1461 IMPLEMENT_CREATE_SHADER(Vertex, VERTEX) 1462 IMPLEMENT_CREATE_SHADER(Pixel, FRAGMENT) 1463 IMPLEMENT_CREATE_SHADER(Geometry, GEOMETRY) 1464#if API >= 11 1465 IMPLEMENT_NOTIMPL_CREATE_SHADER(Hull) 1466 IMPLEMENT_NOTIMPL_CREATE_SHADER(Domain) 1467 IMPLEMENT_NOTIMPL_CREATE_SHADER(Compute) 1468#endif 1469 1470 virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput( 1471 const void *shader_bytecode, 1472 SIZE_T bytecode_length, 1473 const D3D11_SO_DECLARATION_ENTRY *so_declaration, 1474 unsigned num_entries, 1475#if API >= 11 1476 const unsigned *buffer_strides, 1477 unsigned num_strides, 1478 unsigned rasterized_stream, 1479 ID3D11ClassLinkage *class_linkage, 1480#else 1481 UINT output_stream_stride, 1482#endif 1483 ID3D11GeometryShader **out_geometry_shader) 1484 { 1485 SYNCHRONIZED; 1486 1487 return E_NOTIMPL; 1488 1489 // remember to return S_FALSE if ppGeometyShader == NULL and the shader is OK 1490 } 1491 1492#if API >= 11 1493 virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage( 1494 ID3D11ClassLinkage **out_linkage) 1495 { 1496 SYNCHRONIZED; 1497 1498 return E_NOTIMPL; 1499 } 1500#endif 1501 1502 virtual HRESULT STDMETHODCALLTYPE CreateQuery( 1503 const D3D11_QUERY_DESC *query_desc, 1504 ID3D11Query **out_query) 1505 { 1506 SYNCHRONIZED; 1507 1508 if(invalid(query_desc->Query >= D3D11_QUERY_COUNT)) 1509 return E_INVALIDARG; 1510 unsigned query_type = d3d11_to_pipe_query[query_desc->Query]; 1511 if(query_type >= PIPE_QUERY_TYPES) 1512 return E_NOTIMPL; 1513 1514 if(!out_query) 1515 return S_FALSE; 1516 1517 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type); 1518 if(!query) 1519 return E_FAIL; 1520 1521 *out_query = new GalliumD3D11Query(this, query, d3d11_query_size[query_desc->Query], *query_desc); 1522 return S_OK; 1523 } 1524 1525 virtual HRESULT STDMETHODCALLTYPE CreatePredicate( 1526 const D3D11_QUERY_DESC *predicate_desc, 1527 ID3D11Predicate **out_predicate) 1528 { 1529 SYNCHRONIZED; 1530 1531 unsigned query_type; 1532 switch(predicate_desc->Query) 1533 { 1534 case D3D11_QUERY_SO_OVERFLOW_PREDICATE: 1535 query_type = PIPE_QUERY_SO_OVERFLOW_PREDICATE; 1536 break; 1537 case D3D11_QUERY_OCCLUSION_PREDICATE: 1538 query_type = PIPE_QUERY_OCCLUSION_PREDICATE; 1539 break; 1540 default: 1541 return E_INVALIDARG; 1542 } 1543 1544 if(out_predicate) 1545 return S_FALSE; 1546 1547 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type); 1548 if(!query) 1549 return E_FAIL; 1550 1551 *out_predicate = new GalliumD3D11Predicate(this, query, sizeof(BOOL), *predicate_desc); 1552 return S_OK; 1553 } 1554 1555 1556 virtual HRESULT STDMETHODCALLTYPE CreateCounter( 1557 const D3D11_COUNTER_DESC *counter_desc, 1558 ID3D11Counter **out_counter) 1559 { 1560 SYNCHRONIZED; 1561 1562 return E_NOTIMPL; 1563 1564 // remember to return S_FALSE if out_counter == NULL and everything is OK 1565 } 1566 1567#if API >= 11 1568 virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext( 1569 unsigned context_flags, 1570 ID3D11DeviceContext **out_deferred_context) 1571 { 1572 SYNCHRONIZED; 1573 1574 // TODO: this will have to be implemented using a new Gallium util module 1575 return E_NOTIMPL; 1576 1577 // remember to return S_FALSE if out_counter == NULL and everything is OK 1578 } 1579#endif 1580 1581 virtual HRESULT STDMETHODCALLTYPE OpenSharedResource( 1582 HANDLE resource, 1583 REFIID iid, 1584 void **out_resource) 1585 { 1586 SYNCHRONIZED; 1587 1588 // TODO: the problem here is that we need to communicate dimensions somehow 1589 return E_NOTIMPL; 1590 1591 // remember to return S_FALSE if out_counter == NULL and everything is OK 1592#if 0 1593 struct pipe_resou rce templat; 1594 struct winsys_handle handle; 1595 handle.stride = 0; 1596 handle.handle = resource; 1597 handle.type = DRM_API_HANDLE_TYPE_SHARED; 1598 screen->resource_from_handle(screen, &templat, &handle); 1599#endif 1600 } 1601 1602#if API < 11 1603 /* these are documented as "Not implemented". 1604 * According to the UMDDI documentation, they apparently turn on a 1605 * (width + 1) x (height + 1) convolution filter for 1-bit textures. 1606 * Probably nothing uses these, assuming it has ever been implemented anywhere. 1607 */ 1608 void STDMETHODCALLTYPE SetTextFilterSize( 1609 UINT width, 1610 UINT height 1611 ) 1612 {} 1613 1614 virtual void STDMETHODCALLTYPE GetTextFilterSize( 1615 UINT *width, 1616 UINT *height 1617 ) 1618 {} 1619#endif 1620 1621#if API >= 11 1622 virtual void STDMETHODCALLTYPE RestoreGalliumState() 1623 { 1624 GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(immediate_context); 1625 } 1626 1627 virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly() 1628 { 1629 GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(immediate_context); 1630 } 1631#endif 1632 1633 virtual struct pipe_context* STDMETHODCALLTYPE GetGalliumContext(void) 1634 { 1635 return immediate_pipe; 1636 } 1637 1638#undef SYNCHRONIZED 1639}; 1640