d3d11_screen.h revision 8224256946619fb25278718bbf4703e3b9d60c93
1/************************************************************************** 2 * 3 * Copyright 2010 Luca Barbieri 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27/* These cap sets are much more correct than the ones in u_caps.c */ 28/* TODO: it seems cube levels should be the same as 2D levels */ 29 30/* DX 9_1 */ 31static unsigned caps_dx_9_1[] = { 32 UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1), 33 UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */ 34 UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 8), /* 256 */ 35 UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */ 36 UTIL_CHECK_TERMINATE 37}; 38 39/* DX 9_2 */ 40static unsigned caps_dx_9_2[] = { 41 UTIL_CHECK_CAP(OCCLUSION_QUERY), 42 UTIL_CHECK_CAP(TWO_SIDED_STENCIL), 43 UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP), 44 UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE), 45 UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1), 46 UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */ 47 UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */ 48 UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */ 49 UTIL_CHECK_TERMINATE 50}; 51 52/* DX 9_3 */ 53static unsigned caps_dx_9_3[] = { 54 UTIL_CHECK_CAP(OCCLUSION_QUERY), 55 UTIL_CHECK_CAP(TWO_SIDED_STENCIL), 56 UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP), 57 UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE), 58 UTIL_CHECK_CAP(SM3), 59 //UTIL_CHECK_CAP(INSTANCING), 60 UTIL_CHECK_CAP(OCCLUSION_QUERY), 61 UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4), 62 UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13), /* 4096 */ 63 UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */ 64 UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */ 65 UTIL_CHECK_TERMINATE 66}; 67 68 69// this is called "screen" because in the D3D10 case it's only part of the device 70template<bool threadsafe> 71struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen 72{ 73 D3D_FEATURE_LEVEL feature_level; 74 int format_support[PIPE_FORMAT_COUNT]; 75 unsigned creation_flags; 76 unsigned exception_mode; 77 maybe_mutex_t<threadsafe> mutex; 78 79/* TODO: Direct3D 11 specifies that fine-grained locking should be used if the driver supports it. 80 * Right now, I don't trust Gallium drivers to get this right. 81 */ 82#define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(mutex) 83 84 GalliumD3D11ScreenImpl(struct pipe_screen* screen, struct pipe_context* immediate_pipe, BOOL owns_immediate_pipe,unsigned creation_flags, IDXGIAdapter* adapter) 85 : GalliumD3D11Screen(screen, immediate_pipe, adapter), creation_flags(creation_flags) 86 { 87 memset(&screen_caps, 0, sizeof(screen_caps)); 88 screen_caps.gs = screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0; 89 screen_caps.so = !!screen->get_param(screen, PIPE_CAP_STREAM_OUTPUT); 90 screen_caps.queries = screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY); 91 screen_caps.render_condition = screen_caps.queries; 92 for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i) 93 screen_caps.constant_buffers[i] = screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_CONST_BUFFERS); 94 screen_caps.stages = 0; 95 for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i) 96 { 97 if(!screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_INSTRUCTIONS)) 98 break; 99 screen_caps.stages = i + 1; 100 } 101 102 memset(format_support, 0xff, sizeof(format_support)); 103 104 float default_level; 105 /* don't even attempt to autodetect D3D10 level support, since it's just not fully implemented yet */ 106 if(util_check_caps(screen, caps_dx_9_3)) 107 default_level = 9.3; 108 else if(util_check_caps(screen, caps_dx_9_2)) 109 default_level = 9.2; 110 else if(util_check_caps(screen, caps_dx_9_1)) 111 default_level = 9.1; 112 else 113 { 114 _debug_printf("Warning: driver does not even meet D3D_FEATURE_LEVEL_9_1 features, advertising it anyway!\n"); 115 default_level = 9.1; 116 } 117 118 char default_level_name[64]; 119 sprintf(default_level_name, "%.1f", default_level); 120 float feature_level_number = atof(debug_get_option("D3D11_FEATURE_LEVEL", default_level_name)); 121 if(!feature_level_number) 122 feature_level_number = default_level; 123 124#if API >= 11 125 if(feature_level_number >= 11.0f) 126 feature_level = D3D_FEATURE_LEVEL_11_0; 127 else 128#endif 129 if(feature_level_number >= 10.1f) 130 feature_level = D3D_FEATURE_LEVEL_10_1; 131 else if(feature_level_number >= 10.0f) 132 feature_level = D3D_FEATURE_LEVEL_10_0; 133 else if(feature_level_number >= 9.3f) 134 feature_level = D3D_FEATURE_LEVEL_9_3; 135 else if(feature_level_number >= 9.2f) 136 feature_level = D3D_FEATURE_LEVEL_9_2; 137 else 138 feature_level = D3D_FEATURE_LEVEL_9_1; 139 140#if API >= 11 141 immediate_context = GalliumD3D11ImmediateDeviceContext_Create(this, immediate_pipe, owns_immediate_pipe); 142#endif 143 } 144 145 ~GalliumD3D11ScreenImpl() 146 { 147#if API >= 11 148 GalliumD3D11ImmediateDeviceContext_Destroy(immediate_context); 149#endif 150 } 151 152 virtual D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel(void) 153 { 154 return feature_level; 155 } 156 157 virtual unsigned STDMETHODCALLTYPE GetCreationFlags(void) 158 { 159 return creation_flags; 160 } 161 162 virtual HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(void) 163 { 164 return S_OK; 165 } 166 167#if API >= 11 168 virtual void STDMETHODCALLTYPE GetImmediateContext( 169 ID3D11DeviceContext **ppImmediateContext) 170 { 171 immediate_context->AddRef(); 172 *ppImmediateContext = immediate_context; 173 } 174#endif 175 176 virtual HRESULT STDMETHODCALLTYPE SetExceptionMode(unsigned RaiseFlags) 177 { 178 exception_mode = RaiseFlags; 179 return S_OK; 180 } 181 182 virtual unsigned STDMETHODCALLTYPE GetExceptionMode(void) 183 { 184 return exception_mode; 185 } 186 187 virtual HRESULT STDMETHODCALLTYPE CheckCounter( 188 const D3D11_COUNTER_DESC *pDesc, 189 D3D11_COUNTER_TYPE *pType, 190 unsigned *pActiveCounters, 191 LPSTR szName, 192 unsigned *pNameLength, 193 LPSTR szUnits, 194 unsigned *pUnitsLength, 195 LPSTR szDescription, 196 unsigned *pDescriptionLength) 197 { 198 return E_NOTIMPL; 199 } 200 201 virtual void STDMETHODCALLTYPE CheckCounterInfo( 202 D3D11_COUNTER_INFO *pCounterInfo) 203 { 204 /* none supported at the moment */ 205 pCounterInfo->LastDeviceDependentCounter = (D3D11_COUNTER)0; 206 pCounterInfo->NumSimultaneousCounters = 0; 207 pCounterInfo->NumDetectableParallelUnits = 1; 208 } 209 210#if API >= 11 211 virtual HRESULT STDMETHODCALLTYPE CheckFeatureSupport( 212 D3D11_FEATURE Feature, 213 void *pFeatureSupportData, 214 unsigned FeatureSupportDataSize) 215 { 216 SYNCHRONIZED; 217 218 switch(Feature) 219 { 220 case D3D11_FEATURE_THREADING: 221 { 222 D3D11_FEATURE_DATA_THREADING* data = (D3D11_FEATURE_DATA_THREADING*)pFeatureSupportData; 223 if(FeatureSupportDataSize != sizeof(*data)) 224 return E_INVALIDARG; 225 226 data->DriverCommandLists = FALSE; 227 data->DriverConcurrentCreates = FALSE; 228 return S_OK; 229 } 230 case D3D11_FEATURE_DOUBLES: 231 { 232 D3D11_FEATURE_DATA_DOUBLES* data = (D3D11_FEATURE_DATA_DOUBLES*)pFeatureSupportData; 233 if(FeatureSupportDataSize != sizeof(*data)) 234 return E_INVALIDARG; 235 236 data->DoublePrecisionFloatShaderOps = FALSE; 237 return S_OK; 238 } 239 case D3D11_FEATURE_FORMAT_SUPPORT: 240 { 241 D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)pFeatureSupportData; 242 if(FeatureSupportDataSize != sizeof(*data)) 243 return E_INVALIDARG; 244 245 return this->CheckFormatSupport(data->InFormat, &data->OutFormatSupport); 246 } 247 case D3D11_FEATURE_FORMAT_SUPPORT2: 248 { 249 D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)pFeatureSupportData; 250 if(FeatureSupportDataSize != sizeof(*data)) 251 return E_INVALIDARG; 252 253 data->OutFormatSupport = 0; 254 /* TODO: should this be S_OK? */ 255 return E_INVALIDARG; 256 } 257 case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS: 258 { 259 D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS* data = (D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS*)pFeatureSupportData; 260 if(FeatureSupportDataSize != sizeof(*data)) 261 return E_INVALIDARG; 262 263 data->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = FALSE; 264 return S_OK; 265 } 266 default: 267 return E_INVALIDARG; 268 } 269 } 270#endif 271 272 virtual HRESULT STDMETHODCALLTYPE CheckFormatSupport( 273 DXGI_FORMAT Format, 274 unsigned *pFormatSupport 275 ) 276 { 277 SYNCHRONIZED; 278 279 /* TODO: MSAA, advanced features */ 280 pipe_format format = dxgi_to_pipe_format[Format]; 281 if(!format) 282 return E_INVALIDARG; 283 284 int support = format_support[format]; 285 if(support < 0) 286 { 287 support = 0; 288 unsigned buffer = D3D11_FORMAT_SUPPORT_BUFFER | D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER | D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER; 289 unsigned sampler_view = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN; 290 if(util_format_is_depth_or_stencil(format)) 291 sampler_view |= D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON; 292 293 /* TODO: do this properly when Gallium drivers actually support index/vertex format queries */ 294 if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER, 0) 295 || (screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_INDEX_BUFFER, 0) 296 || format == PIPE_FORMAT_R8_UNORM)) 297 support |= buffer; 298 if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_STREAM_OUTPUT, 0)) 299 support |= buffer | D3D11_FORMAT_SUPPORT_SO_BUFFER; 300 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_1D, 0, PIPE_BIND_SAMPLER_VIEW, 0)) 301 support |= D3D11_FORMAT_SUPPORT_TEXTURE1D | sampler_view; 302 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0)) 303 support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | sampler_view; 304 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_CUBE, 0, PIPE_BIND_SAMPLER_VIEW, 0)) 305 support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | sampler_view; 306 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_3D, 0, PIPE_BIND_SAMPLER_VIEW, 0)) 307 support |= D3D11_FORMAT_SUPPORT_TEXTURE3D | sampler_view; 308 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET, 0)) 309 support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_BLENDABLE; 310 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) 311 support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DEPTH_STENCIL; 312 if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DISPLAY_TARGET, 0)) 313 support |= D3D11_FORMAT_SUPPORT_DISPLAY; 314 format_support[format] = support; 315 } 316 *pFormatSupport = support; 317 return S_OK; 318 } 319 320 virtual HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels( 321 DXGI_FORMAT Format, 322 unsigned SampleCount, 323 unsigned *pNumQualityLevels 324 ) 325 { 326 SYNCHRONIZED; 327 328 *pNumQualityLevels = 0; 329 return S_OK; 330 } 331 332 template<typename T, typename U> 333 bool convert_blend_state(T& to, const U& from, unsigned BlendEnable, unsigned RenderTargetWriteMask) 334 { 335 if(invalid(0 336 || from.SrcBlend >= D3D11_BLEND_COUNT 337 || from.SrcBlendAlpha >= D3D11_BLEND_COUNT 338 || from.DestBlend >= D3D11_BLEND_COUNT 339 || from.DestBlendAlpha >= D3D11_BLEND_COUNT 340 || from.BlendOp >= 6 341 || from.BlendOpAlpha >= 6 342 || !from.BlendOp 343 || !from.BlendOpAlpha 344 )) 345 return false; 346 347 to.blend_enable = BlendEnable; 348 349 to.rgb_func = from.BlendOp - 1; 350 to.alpha_func = from.BlendOpAlpha - 1; 351 352 to.rgb_src_factor = d3d11_to_pipe_blend[from.SrcBlend]; 353 to.alpha_src_factor = d3d11_to_pipe_blend[from.SrcBlendAlpha]; 354 to.rgb_dst_factor = d3d11_to_pipe_blend[from.DestBlend]; 355 to.alpha_dst_factor = d3d11_to_pipe_blend[from.DestBlendAlpha]; 356 357 to.colormask = RenderTargetWriteMask & 0xf; 358 return true; 359 } 360 361#if API >= 11 362 virtual HRESULT STDMETHODCALLTYPE CreateBlendState( 363 const D3D11_BLEND_DESC *pBlendStateDesc, 364 ID3D11BlendState **ppBlendState 365 ) 366#else 367 virtual HRESULT STDMETHODCALLTYPE CreateBlendState1( 368 const D3D10_BLEND_DESC1 *pBlendStateDesc, 369 ID3D10BlendState1 **ppBlendState 370 ) 371#endif 372 { 373 SYNCHRONIZED; 374 375 pipe_blend_state state; 376 memset(&state, 0, sizeof(state)); 377 state.alpha_to_coverage = !!pBlendStateDesc->AlphaToCoverageEnable; 378 state.independent_blend_enable = !!pBlendStateDesc->IndependentBlendEnable; 379 assert(PIPE_MAX_COLOR_BUFS >= 8); 380 for(unsigned i = 0; i < 8; ++i) 381 { 382 if(!convert_blend_state( 383 state.rt[i], 384 pBlendStateDesc->RenderTarget[i], 385 pBlendStateDesc->RenderTarget[i].BlendEnable, 386 pBlendStateDesc->RenderTarget[i].RenderTargetWriteMask)) 387 return E_INVALIDARG; 388 } 389 390 if(!ppBlendState) 391 return S_FALSE; 392 393 void* object = immediate_pipe->create_blend_state(immediate_pipe, &state); 394 if(!object) 395 return E_FAIL; 396 397 *ppBlendState = new GalliumD3D11BlendState(this, object, *pBlendStateDesc); 398 return S_OK; 399 } 400 401#if API < 11 402 virtual HRESULT STDMETHODCALLTYPE CreateBlendState( 403 const D3D10_BLEND_DESC *pBlendStateDesc, 404 ID3D10BlendState **ppBlendState 405 ) 406 { 407 SYNCHRONIZED; 408 409 pipe_blend_state state; 410 memset(&state, 0, sizeof(state)); 411 state.alpha_to_coverage = !!pBlendStateDesc->AlphaToCoverageEnable; 412 assert(PIPE_MAX_COLOR_BUFS >= 8); 413 for(unsigned i = 0; i < 8; ++i) 414 { 415 if(!convert_blend_state( 416 state.rt[i], 417 *pBlendStateDesc, 418 pBlendStateDesc->BlendEnable[i], 419 pBlendStateDesc->RenderTargetWriteMask[i])) 420 return E_INVALIDARG; 421 } 422 423 for(unsigned i = 1; i < 8; ++i) 424 { 425 if(memcmp(&state.rt[0], &state.rt[i], sizeof(state.rt[0]))) 426 { 427 state.independent_blend_enable = TRUE; 428 break; 429 } 430 } 431 432 void* object = immediate_pipe->create_blend_state(immediate_pipe, &state); 433 if(!object) 434 return E_FAIL; 435 436 *ppBlendState = new GalliumD3D11BlendState(this, object, *pBlendStateDesc); 437 return S_OK; 438 } 439#endif 440 441 virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilState( 442 const D3D11_DEPTH_STENCIL_DESC *pDepthStencilStateDesc, 443 ID3D11DepthStencilState **ppDepthStencilState 444 ) 445 { 446 SYNCHRONIZED; 447 448 pipe_depth_stencil_alpha_state state; 449 memset(&state, 0, sizeof(state)); 450 state.depth.enabled = !!pDepthStencilStateDesc->DepthEnable; 451 state.depth.writemask = pDepthStencilStateDesc->DepthWriteMask; 452 state.depth.func = pDepthStencilStateDesc->DepthFunc - 1; 453 state.stencil[0].enabled = !!pDepthStencilStateDesc->StencilEnable; 454 state.stencil[0].writemask = pDepthStencilStateDesc->StencilWriteMask; 455 state.stencil[0].valuemask = pDepthStencilStateDesc->StencilReadMask; 456 state.stencil[0].zpass_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->FrontFace.StencilPassOp]; 457 state.stencil[0].fail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->FrontFace.StencilFailOp]; 458 state.stencil[0].zfail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->FrontFace.StencilDepthFailOp]; 459 state.stencil[0].func = pDepthStencilStateDesc->FrontFace.StencilFunc - 1; 460 state.stencil[1].enabled = !!pDepthStencilStateDesc->StencilEnable; 461 state.stencil[1].writemask = pDepthStencilStateDesc->StencilWriteMask; 462 state.stencil[1].valuemask = pDepthStencilStateDesc->StencilReadMask; 463 state.stencil[1].zpass_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->BackFace.StencilPassOp]; 464 state.stencil[1].fail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->BackFace.StencilFailOp]; 465 state.stencil[1].zfail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->BackFace.StencilDepthFailOp]; 466 state.stencil[1].func = pDepthStencilStateDesc->BackFace.StencilFunc - 1; 467 468 if(!ppDepthStencilState) 469 return S_FALSE; 470 471 void* object = immediate_pipe->create_depth_stencil_alpha_state(immediate_pipe, &state); 472 if(!object) 473 return E_FAIL; 474 475 *ppDepthStencilState = new GalliumD3D11DepthStencilState(this, object, *pDepthStencilStateDesc); 476 return S_OK; 477 } 478 479 virtual HRESULT STDMETHODCALLTYPE CreateRasterizerState( 480 const D3D11_RASTERIZER_DESC *pRasterizerDesc, 481 ID3D11RasterizerState **ppRasterizerState) 482 { 483 SYNCHRONIZED; 484 485 pipe_rasterizer_state state; 486 memset(&state, 0, sizeof(state)); 487 state.gl_rasterization_rules = 1; /* D3D10/11 use GL rules */ 488 state.fill_front = state.fill_back = (pRasterizerDesc->FillMode == D3D11_FILL_WIREFRAME) ? PIPE_POLYGON_MODE_LINE : PIPE_POLYGON_MODE_FILL; 489 if(pRasterizerDesc->CullMode == D3D11_CULL_FRONT) 490 state.cull_face = PIPE_FACE_FRONT; 491 else if(pRasterizerDesc->CullMode == D3D11_CULL_BACK) 492 state.cull_face = PIPE_FACE_BACK; 493 else 494 state.cull_face = PIPE_FACE_NONE; 495 state.front_ccw = !!pRasterizerDesc->FrontCounterClockwise; 496 /* TODO: is this correct? */ 497 /* TODO: we are ignoring DepthBiasClamp! */ 498 state.offset_tri = state.offset_line = state.offset_point = pRasterizerDesc->SlopeScaledDepthBias || pRasterizerDesc->DepthBias; 499 state.offset_scale = pRasterizerDesc->SlopeScaledDepthBias; 500 state.offset_units = pRasterizerDesc->DepthBias; 501 state.scissor = !!pRasterizerDesc->ScissorEnable; 502 state.multisample = !!pRasterizerDesc->MultisampleEnable; 503 state.line_smooth = !!pRasterizerDesc->AntialiasedLineEnable; 504 505 /* TODO: is this correct? */ 506 state.point_quad_rasterization = 1; 507 508 if(!ppRasterizerState) 509 return S_FALSE; 510 511 void* object = immediate_pipe->create_rasterizer_state(immediate_pipe, &state); 512 if(!object) 513 return E_FAIL; 514 515 *ppRasterizerState = new GalliumD3D11RasterizerState(this, object, *pRasterizerDesc, !pRasterizerDesc->DepthClipEnable); 516 return S_OK; 517 } 518 519 virtual HRESULT STDMETHODCALLTYPE CreateSamplerState( 520 const D3D11_SAMPLER_DESC *pSamplerDesc, 521 ID3D11SamplerState **ppSamplerState) 522 { 523 SYNCHRONIZED; 524 525 pipe_sampler_state state; 526 memset(&state, 0, sizeof(state)); 527 state.normalized_coords = 1; 528 state.min_mip_filter = (pSamplerDesc->Filter & 1); 529 state.mag_img_filter = ((pSamplerDesc->Filter >> 2) & 1); 530 state.min_img_filter = ((pSamplerDesc->Filter >> 4) & 1); 531 if(pSamplerDesc->Filter & 0x40) 532 state.max_anisotropy = pSamplerDesc->MaxAnisotropy; 533 if(pSamplerDesc->Filter & 0x80) 534 { 535 state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; 536 state.compare_func = pSamplerDesc->ComparisonFunc; 537 } 538 state.wrap_s = d3d11_to_pipe_wrap[pSamplerDesc->AddressU]; 539 state.wrap_t = d3d11_to_pipe_wrap[pSamplerDesc->AddressV]; 540 state.wrap_r = d3d11_to_pipe_wrap[pSamplerDesc->AddressW]; 541 state.lod_bias = pSamplerDesc->MipLODBias; 542 memcpy(state.border_color, pSamplerDesc->BorderColor, sizeof(state.border_color)); 543 state.min_lod = pSamplerDesc->MinLOD; 544 state.max_lod = pSamplerDesc->MaxLOD; 545 546 if(!ppSamplerState) 547 return S_FALSE; 548 549 void* object = immediate_pipe->create_sampler_state(immediate_pipe, &state); 550 if(!object) 551 return E_FAIL; 552 553 *ppSamplerState = new GalliumD3D11SamplerState(this, object, *pSamplerDesc); 554 return S_OK; 555 } 556 557 virtual HRESULT STDMETHODCALLTYPE CreateInputLayout( 558 const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs, 559 unsigned NumElements, 560 const void *pShaderBytecodeWithInputSignature, 561 SIZE_T BytecodeLength, 562 ID3D11InputLayout **ppInputLayout) 563 { 564 SYNCHRONIZED; 565 566 if(NumElements > D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT) 567 return E_INVALIDARG; 568 assert(D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT <= PIPE_MAX_ATTRIBS); 569 570 // putting semantics matching in the core API seems to be a (minor) design mistake 571 572 struct dxbc_chunk_signature* sig = dxbc_find_signature(pShaderBytecodeWithInputSignature, BytecodeLength, false); 573 D3D11_SIGNATURE_PARAMETER_DESC* params; 574 unsigned num_params = dxbc_parse_signature(sig, ¶ms); 575 576 typedef std::unordered_map<std::pair<c_string, unsigned>, unsigned> semantic_to_idx_map_t; 577 semantic_to_idx_map_t semantic_to_idx_map; 578 for(unsigned i = 0; i < NumElements; ++i) 579 semantic_to_idx_map[std::make_pair(c_string(pInputElementDescs[i].SemanticName), pInputElementDescs[i].SemanticIndex)] = i; 580 581 struct pipe_vertex_element elements[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT]; 582 583 unsigned num_params_to_use = std::min(num_params, (unsigned)D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT); 584 for(unsigned i = 0; i < num_params_to_use; ++i) 585 { 586 int idx = -1; 587 semantic_to_idx_map_t::iterator iter = semantic_to_idx_map.find(std::make_pair(c_string(params[i].SemanticName), params[i].SemanticIndex)); 588 if(iter != semantic_to_idx_map.end()) 589 idx = iter->second; 590 591 // TODO: I kind of doubt Gallium drivers will like null elements; should we do something about it, either here, in the interface, or in the drivers? 592 // TODO: also, in which cases should we return errors? (i.e. duplicate semantics in vs, duplicate semantics in layout, unmatched semantic in vs, unmatched semantic in layout) 593 memset(&elements[i], 0, sizeof(elements[i])); 594 if(idx >= 0) 595 { 596 elements[i].src_format = dxgi_to_pipe_format[pInputElementDescs[idx].Format]; 597 elements[i].src_offset = pInputElementDescs[idx].AlignedByteOffset; 598 elements[i].vertex_buffer_index = pInputElementDescs[idx].InputSlot; 599 elements[i].instance_divisor = pInputElementDescs[idx].InstanceDataStepRate; 600 } 601 } 602 603 free(params); 604 605 if(!ppInputLayout) 606 return S_FALSE; 607 608 void* object = immediate_pipe->create_vertex_elements_state(immediate_pipe, num_params_to_use, elements); 609 if(!object) 610 return E_FAIL; 611 612 *ppInputLayout = new GalliumD3D11InputLayout(this, object); 613 return S_OK; 614 } 615 616 static unsigned d3d11_to_pipe_bind_flags(unsigned BindFlags) 617 { 618 unsigned bind = 0; 619 if(BindFlags & D3D11_BIND_VERTEX_BUFFER) 620 bind |= PIPE_BIND_VERTEX_BUFFER; 621 if(BindFlags & D3D11_BIND_INDEX_BUFFER) 622 bind |= PIPE_BIND_INDEX_BUFFER; 623 if(BindFlags & D3D11_BIND_CONSTANT_BUFFER) 624 bind |= PIPE_BIND_CONSTANT_BUFFER; 625 if(BindFlags & D3D11_BIND_SHADER_RESOURCE) 626 bind |= PIPE_BIND_SAMPLER_VIEW; 627 if(BindFlags & D3D11_BIND_STREAM_OUTPUT) 628 bind |= PIPE_BIND_STREAM_OUTPUT; 629 if(BindFlags & D3D11_BIND_RENDER_TARGET) 630 bind |= PIPE_BIND_RENDER_TARGET; 631 if(BindFlags & D3D11_BIND_DEPTH_STENCIL) 632 bind |= PIPE_BIND_DEPTH_STENCIL; 633 return bind; 634 } 635 636 inline HRESULT create_resource( 637 pipe_texture_target target, 638 unsigned Width, 639 unsigned Height, 640 unsigned Depth, 641 unsigned MipLevels, 642 unsigned ArraySize, 643 DXGI_FORMAT Format, 644 const DXGI_SAMPLE_DESC* SampleDesc, 645 D3D11_USAGE Usage, 646 unsigned BindFlags, 647 unsigned CPUAccessFlags, 648 unsigned MiscFlags, 649 const D3D11_SUBRESOURCE_DATA *pInitialData, 650 DXGI_USAGE dxgi_usage, 651 struct pipe_resource** ppresource 652 ) 653 { 654 if(invalid(Format >= DXGI_FORMAT_COUNT)) 655 return E_INVALIDARG; 656 if(MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) 657 { 658 if(target != PIPE_TEXTURE_2D) 659 return E_INVALIDARG; 660 target = PIPE_TEXTURE_CUBE; 661 662 if(ArraySize != 6) 663 return E_NOTIMPL; 664 } 665 else 666 { 667 if(ArraySize > 1) 668 return E_NOTIMPL; 669 ArraySize = 1; 670 } 671 /* TODO: msaa */ 672 struct pipe_resource templat; 673 memset(&templat, 0, sizeof(templat)); 674 templat.target = target; 675 templat.width0 = Width; 676 templat.height0 = Height; 677 templat.depth0 = Depth; 678 templat.last_level = MipLevels ? (MipLevels - 1) : 0; 679 templat.format = dxgi_to_pipe_format[Format]; 680 templat.bind = d3d11_to_pipe_bind_flags(BindFlags); 681 if(CPUAccessFlags & D3D11_CPU_ACCESS_READ) 682 templat.bind |= PIPE_BIND_TRANSFER_READ; 683 if(CPUAccessFlags & D3D11_CPU_ACCESS_WRITE) 684 templat.bind |= PIPE_BIND_TRANSFER_WRITE; 685 if(MiscFlags & D3D11_RESOURCE_MISC_SHARED) 686 templat.bind |= PIPE_BIND_SHARED; 687 if(MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE) 688 templat.bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE; 689 if(dxgi_usage & DXGI_USAGE_BACK_BUFFER) 690 templat.bind |= PIPE_BIND_DISPLAY_TARGET; 691 templat.usage = d3d11_to_pipe_usage[Usage]; 692 if(invalid(!templat.format)) 693 return E_NOTIMPL; 694 695 if(!ppresource) 696 return S_FALSE; 697 698 struct pipe_resource* resource = screen->resource_create(screen, &templat); 699 if(!resource) 700 return E_FAIL; 701 if(pInitialData) 702 { 703 for(unsigned slice = 0; slice < ArraySize; ++slice) 704 { 705 for(unsigned level = 0; level <= templat.last_level; ++level) 706 { 707 struct pipe_subresource sr; 708 sr.level = level; 709 sr.face = slice; 710 struct pipe_box box; 711 box.x = box.y = box.z = 0; 712 box.width = u_minify(Width, level); 713 box.height = u_minify(Height, level); 714 box.depth = u_minify(Depth, level); 715 immediate_pipe->transfer_inline_write(immediate_pipe, resource, sr, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_UNSYNCHRONIZED, &box, pInitialData->pSysMem, pInitialData->SysMemPitch, pInitialData->SysMemSlicePitch); 716 ++pInitialData; 717 } 718 } 719 } 720 *ppresource = resource; 721 return S_OK; 722 } 723 724 static unsigned d3d_to_dxgi_usage(unsigned bind, unsigned misc) 725 { 726 unsigned dxgi_usage = 0; 727 if(bind |= D3D11_BIND_RENDER_TARGET) 728 dxgi_usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT; 729 if(bind & D3D11_BIND_SHADER_RESOURCE) 730 dxgi_usage |= DXGI_USAGE_SHADER_INPUT; 731#if API >= 11 732 if(bind & D3D11_BIND_UNORDERED_ACCESS) 733 dxgi_usage |= DXGI_USAGE_UNORDERED_ACCESS; 734#endif 735 if(misc & D3D11_RESOURCE_MISC_SHARED) 736 dxgi_usage |= DXGI_USAGE_SHARED; 737 return dxgi_usage; 738 } 739 740 virtual HRESULT STDMETHODCALLTYPE CreateTexture1D( 741 const D3D11_TEXTURE1D_DESC *pDesc, 742 const D3D11_SUBRESOURCE_DATA *pInitialData, 743 ID3D11Texture1D **ppTexture1D) 744 { 745 SYNCHRONIZED; 746 747 struct pipe_resource* resource; 748 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags); 749 HRESULT hr = create_resource(PIPE_TEXTURE_1D, pDesc->Width, 1, 1, pDesc->MipLevels, pDesc->ArraySize, pDesc->Format, 0, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppTexture1D ? &resource : 0); 750 if(hr != S_OK) 751 return hr; 752 *ppTexture1D = new GalliumD3D11Texture1D(this, resource, *pDesc, dxgi_usage); 753 return S_OK; 754 } 755 756 virtual HRESULT STDMETHODCALLTYPE CreateTexture2D( 757 const D3D11_TEXTURE2D_DESC *pDesc, 758 const D3D11_SUBRESOURCE_DATA *pInitialData, 759 ID3D11Texture2D **ppTexture2D) 760 { 761 SYNCHRONIZED; 762 763 struct pipe_resource* resource; 764 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags); 765 HRESULT hr = create_resource(PIPE_TEXTURE_2D, pDesc->Width, pDesc->Height, 1, pDesc->MipLevels, pDesc->ArraySize, pDesc->Format, &pDesc->SampleDesc, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppTexture2D ? &resource : 0); 766 if(hr != S_OK) 767 return hr; 768 if(pDesc->MipLevels == 1 && pDesc->ArraySize == 1) 769 *ppTexture2D = new GalliumD3D11Surface(this, resource, *pDesc, dxgi_usage); 770 else 771 *ppTexture2D = new GalliumD3D11Texture2D(this, resource, *pDesc, dxgi_usage); 772 return S_OK; 773 } 774 775 virtual HRESULT STDMETHODCALLTYPE CreateTexture3D( 776 const D3D11_TEXTURE3D_DESC *pDesc, 777 const D3D11_SUBRESOURCE_DATA *pInitialData, 778 ID3D11Texture3D **ppTexture3D) 779 { 780 SYNCHRONIZED; 781 782 struct pipe_resource* resource; 783 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags); 784 HRESULT hr = create_resource(PIPE_TEXTURE_3D, pDesc->Width, pDesc->Height, pDesc->Depth, pDesc->MipLevels, 1, pDesc->Format, 0, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppTexture3D ? &resource : 0); 785 if(hr != S_OK) 786 return hr; 787 *ppTexture3D = new GalliumD3D11Texture3D(this, resource, *pDesc, dxgi_usage); 788 return S_OK; 789 } 790 791 virtual HRESULT STDMETHODCALLTYPE CreateBuffer( 792 const D3D11_BUFFER_DESC *pDesc, 793 const D3D11_SUBRESOURCE_DATA *pInitialData, 794 ID3D11Buffer **ppBuffer) 795 { 796 SYNCHRONIZED; 797 798#if API >= 11 799 if(pDesc->StructureByteStride > 1) 800 return E_NOTIMPL; 801#endif 802 struct pipe_resource* resource; 803 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags); 804 HRESULT hr = create_resource(PIPE_BUFFER, pDesc->ByteWidth, 1, 1, 1, 1, DXGI_FORMAT_R8_UNORM, 0, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppBuffer ? &resource : 0); 805 if(hr != S_OK) 806 return hr; 807 *ppBuffer = new GalliumD3D11Buffer(this, resource, *pDesc, dxgi_usage); 808 return S_OK; 809 } 810 811 virtual HRESULT STDMETHODCALLTYPE OpenGalliumResource( 812 struct pipe_resource* resource, 813 IUnknown** dxgi_resource) 814 { 815 SYNCHRONIZED; 816 817 /* TODO: maybe support others */ 818 assert(resource->target == PIPE_TEXTURE_2D); 819 *dxgi_resource = 0; 820 D3D11_TEXTURE2D_DESC desc; 821 memset(&desc, 0, sizeof(desc)); 822 desc.Width = resource->width0; 823 desc.Height = resource->height0; 824 init_pipe_to_dxgi_format(); 825 desc.Format = pipe_to_dxgi_format[resource->format]; 826 desc.SampleDesc.Count = resource->nr_samples; 827 desc.SampleDesc.Quality = 0; 828 desc.ArraySize = 1; 829 desc.MipLevels = resource->last_level + 1; 830 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 831 if(resource->bind & PIPE_BIND_RENDER_TARGET) 832 desc.BindFlags |= D3D11_BIND_RENDER_TARGET; 833 if(resource->bind & PIPE_BIND_DEPTH_STENCIL) 834 desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL; 835 if(resource->bind & PIPE_BIND_SAMPLER_VIEW) 836 desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; 837 if(resource->bind & PIPE_BIND_SHARED) 838 desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED; 839 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc.BindFlags, desc.MiscFlags); 840 if(desc.MipLevels == 1 && desc.ArraySize == 1) 841 *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Surface(this, resource, desc, dxgi_usage); 842 else 843 *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Texture2D(this, resource, desc, dxgi_usage); 844 return S_OK; 845 } 846 847 virtual HRESULT STDMETHODCALLTYPE CreateSurface( 848 const DXGI_SURFACE_DESC *pDesc, 849 unsigned NumSurfaces, 850 DXGI_USAGE Usage, 851 const DXGI_SHARED_RESOURCE *pSharedResource, 852 IDXGISurface **ppSurface) 853 { 854 SYNCHRONIZED; 855 856 D3D11_TEXTURE2D_DESC desc; 857 memset(&desc, 0, sizeof(desc)); 858 859 struct pipe_resource* resource; 860 desc.Width = pDesc->Width; 861 desc.Height = pDesc->Height; 862 desc.Format = pDesc->Format; 863 desc.SampleDesc = pDesc->SampleDesc; 864 desc.ArraySize = NumSurfaces; 865 desc.MipLevels = 1; 866 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 867 if(Usage & DXGI_USAGE_RENDER_TARGET_OUTPUT) 868 desc.BindFlags |= D3D11_BIND_RENDER_TARGET; 869 if(Usage & DXGI_USAGE_SHADER_INPUT) 870 desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; 871#if API >= 11 872 if(Usage & DXGI_USAGE_UNORDERED_ACCESS) 873 desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; 874#endif 875 if(Usage & DXGI_USAGE_SHARED) 876 desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED; 877 HRESULT hr = create_resource(PIPE_TEXTURE_2D, pDesc->Width, pDesc->Height, 1, 1, NumSurfaces, pDesc->Format, &pDesc->SampleDesc, D3D11_USAGE_DEFAULT, desc.BindFlags, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE, desc.MiscFlags, 0, Usage, &resource); 878 if(hr != S_OK) 879 return hr; 880 *ppSurface = new GalliumD3D11Surface(this, resource, desc, Usage); 881 return S_OK; 882 } 883 884 virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView( 885 ID3D11Resource *pResource, 886 const D3D11_SHADER_RESOURCE_VIEW_DESC *pDesc, 887 ID3D11ShaderResourceView **ppSRView) 888 { 889#if API >= 11 890 D3D11_SHADER_RESOURCE_VIEW_DESC def_desc; 891#else 892 if(pDesc->ViewDimension == D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY) 893 return E_INVALIDARG; 894 D3D10_SHADER_RESOURCE_VIEW_DESC1 desc1; 895 memset(&desc1, 0, sizeof(desc1)); 896 memcpy(&desc1, pDesc, sizeof(*pDesc)); 897 return CreateShaderResourceView1(pResource, &desc1, (ID3D10ShaderResourceView1**)ppSRView); 898 } 899 900 virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView1( 901 ID3D11Resource *pResource, 902 const D3D10_SHADER_RESOURCE_VIEW_DESC1 *pDesc, 903 ID3D10ShaderResourceView1 **ppSRView) 904 { 905 D3D10_SHADER_RESOURCE_VIEW_DESC1 def_desc; 906#endif 907 SYNCHRONIZED; 908 909 if(!pDesc) 910 { 911 struct pipe_resource* resource = ((GalliumD3D11Resource<>*)pResource)->resource; 912 init_pipe_to_dxgi_format(); 913 memset(&def_desc, 0, sizeof(def_desc)); 914 def_desc.Format = pipe_to_dxgi_format[resource->format]; 915 switch(resource->target) 916 { 917 case PIPE_BUFFER: 918 def_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; 919 def_desc.Buffer.ElementWidth = 1; 920#if API >= 11 921 def_desc.Buffer.NumElements = resource->width0; 922#endif 923 break; 924 case PIPE_TEXTURE_1D: 925 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; 926 def_desc.Texture1D.MipLevels = resource->last_level + 1; 927 break; 928 case PIPE_TEXTURE_2D: 929 case PIPE_TEXTURE_RECT: 930 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 931 def_desc.Texture2D.MipLevels = resource->last_level + 1; 932 break; 933 case PIPE_TEXTURE_3D: 934 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; 935 def_desc.Texture3D.MipLevels = resource->last_level + 1; 936 break; 937 case PIPE_TEXTURE_CUBE: 938 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; 939 def_desc.TextureCube.MipLevels = resource->last_level + 1; 940 break; 941 default: 942 return E_INVALIDARG; 943 } 944 pDesc = &def_desc; 945 } 946 947 struct pipe_sampler_view templat; 948 memset(&templat, 0, sizeof(templat)); 949 if(invalid(Format >= DXGI_FORMAT_COUNT)) 950 return E_INVALIDARG; 951 templat.format = dxgi_to_pipe_format[pDesc->Format]; 952 if(!templat.format) 953 return E_NOTIMPL; 954 templat.swizzle_r = PIPE_SWIZZLE_RED; 955 templat.swizzle_g = PIPE_SWIZZLE_GREEN; 956 templat.swizzle_b = PIPE_SWIZZLE_BLUE; 957 templat.swizzle_a = PIPE_SWIZZLE_ALPHA; 958 959 templat.texture = ((GalliumD3D11Resource<>*)pResource)->resource; 960 switch(pDesc->ViewDimension) 961 { 962 case D3D11_SRV_DIMENSION_TEXTURE1D: 963 case D3D11_SRV_DIMENSION_TEXTURE2D: 964 case D3D11_SRV_DIMENSION_TEXTURE3D: 965 case D3D11_SRV_DIMENSION_TEXTURE1DARRAY: 966 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: 967 /* yes, this works for all of these types (but TODO: texture arrays) */ 968 templat.first_level = pDesc->Texture1D.MostDetailedMip; 969 templat.last_level = templat.first_level + pDesc->Texture1D.MipLevels - 1; 970 break; 971 case D3D11_SRV_DIMENSION_BUFFER: 972 case D3D11_SRV_DIMENSION_TEXTURE2DMS: 973 case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: 974 return E_NOTIMPL; 975 default: 976 return E_INVALIDARG; 977 } 978 979 if(!ppSRView) 980 return S_FALSE; 981 982 struct pipe_sampler_view* view = immediate_pipe->create_sampler_view(immediate_pipe, templat.texture, &templat); 983 if(!view) 984 return E_FAIL; 985 *ppSRView = new GalliumD3D11ShaderResourceView(this, (GalliumD3D11Resource<>*)pResource, view, *pDesc); 986 return S_OK; 987 } 988 989#if API >= 11 990 virtual HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView( 991 ID3D11Resource *pResource, 992 const D3D11_UNORDERED_ACCESS_VIEW_DESC *pDesc, 993 ID3D11UnorderedAccessView **ppUAView) 994 { 995 SYNCHRONIZED; 996 997 return E_NOTIMPL; 998 999 // remember to return S_FALSE and not crash if ppUAView == 0 and parameters are valid 1000 } 1001#endif 1002 1003 virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView( 1004 ID3D11Resource *pResource, 1005 const D3D11_RENDER_TARGET_VIEW_DESC *pDesc, 1006 ID3D11RenderTargetView **ppRTView) 1007 { 1008 SYNCHRONIZED; 1009 1010 D3D11_RENDER_TARGET_VIEW_DESC def_desc; 1011 if(!pDesc) 1012 { 1013 struct pipe_resource* resource = ((GalliumD3D11Resource<>*)pResource)->resource; 1014 init_pipe_to_dxgi_format(); 1015 memset(&def_desc, 0, sizeof(def_desc)); 1016 def_desc.Format = pipe_to_dxgi_format[resource->format]; 1017 switch(resource->target) 1018 { 1019 case PIPE_BUFFER: 1020 def_desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER; 1021 def_desc.Buffer.ElementWidth = 1; 1022#if API >= 11 1023 def_desc.Buffer.NumElements = resource->width0; 1024#endif 1025 break; 1026 case PIPE_TEXTURE_1D: 1027 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D; 1028 break; 1029 case PIPE_TEXTURE_2D: 1030 case PIPE_TEXTURE_RECT: 1031 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; 1032 break; 1033 case PIPE_TEXTURE_3D: 1034 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; 1035 def_desc.Texture3D.WSize = resource->depth0; 1036 break; 1037 case PIPE_TEXTURE_CUBE: 1038 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; 1039 def_desc.Texture2DArray.ArraySize = 6; 1040 break; 1041 default: 1042 return E_INVALIDARG; 1043 } 1044 pDesc = &def_desc; 1045 } 1046 1047 unsigned zslice = 0; 1048 unsigned face = 0; 1049 unsigned level; 1050 enum pipe_format format; 1051 if(invalid(pDesc->Format >= DXGI_FORMAT_COUNT)) 1052 return E_INVALIDARG; 1053 format = dxgi_to_pipe_format[pDesc->Format]; 1054 if(!format) 1055 return E_NOTIMPL; 1056 1057 switch(pDesc->ViewDimension) 1058 { 1059 case D3D11_RTV_DIMENSION_TEXTURE1D: 1060 case D3D11_RTV_DIMENSION_TEXTURE2D: 1061 level = pDesc->Texture1D.MipSlice; 1062 break; 1063 case D3D11_RTV_DIMENSION_TEXTURE3D: 1064 level = pDesc->Texture3D.MipSlice; 1065 zslice = pDesc->Texture3D.FirstWSlice; 1066 break; 1067 case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: 1068 case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: 1069 level = pDesc->Texture1DArray.MipSlice; 1070 face = pDesc->Texture1DArray.FirstArraySlice; 1071 break; 1072 case D3D11_RTV_DIMENSION_BUFFER: 1073 case D3D11_RTV_DIMENSION_TEXTURE2DMS: 1074 case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: 1075 return E_NOTIMPL; 1076 default: 1077 return E_INVALIDARG; 1078 } 1079 1080 if(!ppRTView) 1081 return S_FALSE; 1082 1083 struct pipe_surface* surface = screen->get_tex_surface(screen, 1084 ((GalliumD3D11Resource<>*)pResource)->resource, 1085 face, level, zslice, PIPE_BIND_RENDER_TARGET); 1086 if(!surface) 1087 return E_FAIL; 1088 /* muhahahahaha, let's hope this actually works */ 1089 surface->format = format; 1090 *ppRTView = new GalliumD3D11RenderTargetView(this, (GalliumD3D11Resource<>*)pResource, surface, *pDesc); 1091 return S_OK; 1092 } 1093 1094 virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilView( 1095 ID3D11Resource *pResource, 1096 const D3D11_DEPTH_STENCIL_VIEW_DESC *pDesc, 1097 ID3D11DepthStencilView **ppDepthStencilView) 1098 { 1099 SYNCHRONIZED; 1100 1101 D3D11_DEPTH_STENCIL_VIEW_DESC def_desc; 1102 if(!pDesc) 1103 { 1104 struct pipe_resource* resource = ((GalliumD3D11Resource<>*)pResource)->resource; 1105 init_pipe_to_dxgi_format(); 1106 memset(&def_desc, 0, sizeof(def_desc)); 1107 def_desc.Format = pipe_to_dxgi_format[resource->format]; 1108 switch(resource->target) 1109 { 1110 case PIPE_TEXTURE_1D: 1111 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D; 1112 break; 1113 case PIPE_TEXTURE_2D: 1114 case PIPE_TEXTURE_RECT: 1115 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; 1116 break; 1117 case PIPE_TEXTURE_CUBE: 1118 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; 1119 def_desc.Texture2DArray.ArraySize = 6; 1120 break; 1121 default: 1122 return E_INVALIDARG; 1123 } 1124 pDesc = &def_desc; 1125 } 1126 1127 unsigned zslice = 0; 1128 unsigned face = 0; 1129 unsigned level; 1130 enum pipe_format format; 1131 if(invalid(pDesc->Format >= DXGI_FORMAT_COUNT)) 1132 return E_INVALIDARG; 1133 format = dxgi_to_pipe_format[pDesc->Format]; 1134 if(!format) 1135 return E_NOTIMPL; 1136 1137 switch(pDesc->ViewDimension) 1138 { 1139 case D3D11_DSV_DIMENSION_TEXTURE1D: 1140 case D3D11_DSV_DIMENSION_TEXTURE2D: 1141 level = pDesc->Texture1D.MipSlice; 1142 break; 1143 case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: 1144 case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: 1145 level = pDesc->Texture1DArray.MipSlice; 1146 face = pDesc->Texture1DArray.FirstArraySlice; 1147 break; 1148 case D3D11_DSV_DIMENSION_TEXTURE2DMS: 1149 case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: 1150 return E_NOTIMPL; 1151 default: 1152 return E_INVALIDARG; 1153 } 1154 1155 if(!ppDepthStencilView) 1156 return S_FALSE; 1157 1158 struct pipe_surface* surface = screen->get_tex_surface(screen, 1159 ((GalliumD3D11Resource<>*)pResource)->resource, 1160 face, level, zslice, PIPE_BIND_DEPTH_STENCIL); 1161 if(!surface) 1162 return E_FAIL; 1163 /* muhahahahaha, let's hope this actually works */ 1164 surface->format = format; 1165 *ppDepthStencilView = new GalliumD3D11DepthStencilView(this, (GalliumD3D11Resource<>*)pResource, surface, *pDesc); 1166 return S_OK; 1167 } 1168 1169 GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void *pShaderBytecode, SIZE_T BytecodeLength 1170#if API >= 11 1171 , ID3D11ClassLinkage *pClassLinkage 1172#endif 1173 ) 1174 { 1175 dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(pShaderBytecode, BytecodeLength); 1176 if(!sm4_chunk) 1177 return 0; 1178 1179 std::auto_ptr<sm4_program> sm4(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size))); 1180 if(!sm4.get()) 1181 return 0; 1182 1183 struct pipe_shader_state tgsi_shader; 1184 memset(&tgsi_shader, 0, sizeof(tgsi_shader)); 1185 tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4); 1186 if(!tgsi_shader.tokens) 1187 return 0; 1188 1189 void* shader_cso; 1190 GalliumD3D11Shader<>* shader; 1191 1192 switch(type) 1193 { 1194 case PIPE_SHADER_VERTEX: 1195 shader_cso = immediate_pipe->create_vs_state(immediate_pipe, &tgsi_shader); 1196 shader = (GalliumD3D11Shader<>*)new GalliumD3D11VertexShader(this, shader_cso); 1197 break; 1198 case PIPE_SHADER_FRAGMENT: 1199 shader_cso = immediate_pipe->create_fs_state(immediate_pipe, &tgsi_shader); 1200 shader = (GalliumD3D11Shader<>*)new GalliumD3D11PixelShader(this, shader_cso); 1201 break; 1202 case PIPE_SHADER_GEOMETRY: 1203 shader_cso = immediate_pipe->create_gs_state(immediate_pipe, &tgsi_shader); 1204 shader = (GalliumD3D11Shader<>*)new GalliumD3D11GeometryShader(this, shader_cso); 1205 break; 1206 default: 1207 shader_cso = 0; 1208 shader = 0; 1209 break; 1210 } 1211 1212 if(shader) 1213 { 1214 shader->slot_to_resource = sm4->slot_to_resource; 1215 shader->slot_to_sampler = sm4->slot_to_sampler; 1216 } 1217 1218 free((void*)tgsi_shader.tokens); 1219 return shader; 1220 } 1221 1222#if API >= 11 1223#define CREATE_SHADER_ARGS \ 1224 const void *pShaderBytecode, \ 1225 SIZE_T BytecodeLength, \ 1226 ID3D11ClassLinkage *pClassLinkage 1227#define PASS_SHADER_ARGS pShaderBytecode, BytecodeLength, pClassLinkage 1228#else 1229#define CREATE_SHADER_ARGS \ 1230 const void *pShaderBytecode, \ 1231 SIZE_T BytecodeLength 1232#define PASS_SHADER_ARGS pShaderBytecode, BytecodeLength 1233#endif 1234 1235#define IMPLEMENT_CREATE_SHADER(Stage, GALLIUM) \ 1236 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \ 1237 CREATE_SHADER_ARGS, \ 1238 ID3D11##Stage##Shader **pp##Stage##Shader) \ 1239 { \ 1240 SYNCHRONIZED; \ 1241 GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS); \ 1242 if(!shader) \ 1243 return E_FAIL; \ 1244 if(pp##Stage##Shader) \ 1245 { \ 1246 *pp##Stage##Shader = shader; \ 1247 return S_OK; \ 1248 } \ 1249 else \ 1250 { \ 1251 shader->Release(); \ 1252 return S_FALSE; \ 1253 } \ 1254 } 1255 1256#define IMPLEMENT_NOTIMPL_CREATE_SHADER(Stage) \ 1257 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \ 1258 CREATE_SHADER_ARGS, \ 1259 ID3D11##Stage##Shader **pp##Stage##Shader) \ 1260 { \ 1261 return E_NOTIMPL; \ 1262 } 1263 1264 IMPLEMENT_CREATE_SHADER(Vertex, VERTEX) 1265 IMPLEMENT_CREATE_SHADER(Pixel, FRAGMENT) 1266 IMPLEMENT_CREATE_SHADER(Geometry, GEOMETRY) 1267#if API >= 11 1268 IMPLEMENT_NOTIMPL_CREATE_SHADER(Hull) 1269 IMPLEMENT_NOTIMPL_CREATE_SHADER(Domain) 1270 IMPLEMENT_NOTIMPL_CREATE_SHADER(Compute) 1271#endif 1272 1273 virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput( 1274 const void *pShaderBytecode, 1275 SIZE_T BytecodeLength, 1276 const D3D11_SO_DECLARATION_ENTRY *pSODeclaration, 1277 unsigned NumEntries, 1278#if API >= 11 1279 const unsigned *pBufferStrides, 1280 unsigned NumStrides, 1281 unsigned RasterizedStream, 1282 ID3D11ClassLinkage *pClassLinkage, 1283#else 1284 UINT OutputStreamStride, 1285#endif 1286 ID3D11GeometryShader **ppGeometryShader) 1287 { 1288 SYNCHRONIZED; 1289 1290 if(!ppGeometryShader) 1291 return S_FALSE; 1292 1293 return E_NOTIMPL; 1294 1295 // remember to return S_FALSE if ppGeometyShader == NULL and the shader is OK 1296 } 1297 1298#if API >= 11 1299 virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage( 1300 ID3D11ClassLinkage **ppLinkage) 1301 { 1302 SYNCHRONIZED; 1303 1304 if(!ppLinkage) 1305 return S_FALSE; 1306 1307 return E_NOTIMPL; 1308 } 1309#endif 1310 1311 virtual HRESULT STDMETHODCALLTYPE CreateQuery( 1312 const D3D11_QUERY_DESC *pQueryDesc, 1313 ID3D11Query **ppQuery) 1314 { 1315 SYNCHRONIZED; 1316 1317 if(invalid(pQueryDesc->Query >= D3D11_QUERY_COUNT)) 1318 return E_INVALIDARG; 1319 unsigned query_type = d3d11_to_pipe_query[pQueryDesc->Query]; 1320 if(!query_type) 1321 return E_NOTIMPL; 1322 1323 if(ppQuery) 1324 return S_FALSE; 1325 1326 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type); 1327 if(!query) 1328 return E_FAIL; 1329 1330 *ppQuery = new GalliumD3D11Query(this, query, d3d11_query_size[pQueryDesc->Query], *pQueryDesc); 1331 return S_OK; 1332 } 1333 1334 virtual HRESULT STDMETHODCALLTYPE CreatePredicate( 1335 const D3D11_QUERY_DESC *pPredicateDesc, 1336 ID3D11Predicate **ppPredicate) 1337 { 1338 SYNCHRONIZED; 1339 1340 unsigned query_type; 1341 switch(pPredicateDesc->Query) 1342 { 1343 case D3D11_QUERY_SO_OVERFLOW_PREDICATE: 1344 return E_NOTIMPL; 1345 case D3D11_QUERY_OCCLUSION_PREDICATE: 1346 query_type = PIPE_QUERY_OCCLUSION_COUNTER; 1347 break; 1348 default: 1349 return E_INVALIDARG; 1350 } 1351 1352 if(ppPredicate) 1353 return S_FALSE; 1354 1355 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type); 1356 if(!query) 1357 return E_FAIL; 1358 1359 *ppPredicate = new GalliumD3D11Predicate(this, query, sizeof(BOOL), *pPredicateDesc); 1360 return S_OK; 1361 } 1362 1363 1364 virtual HRESULT STDMETHODCALLTYPE CreateCounter( 1365 const D3D11_COUNTER_DESC *pCounterDesc, 1366 ID3D11Counter **ppCounter) 1367 { 1368 SYNCHRONIZED; 1369 1370 return E_NOTIMPL; 1371 1372 // remember to return S_FALSE if ppCounter == NULL and everything is OK 1373 } 1374 1375#if API >= 11 1376 virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext( 1377 unsigned ContextFlags, 1378 ID3D11DeviceContext **ppDeferredContext) 1379 { 1380 SYNCHRONIZED; 1381 1382 // TODO: this will have to be implemented using a new Gallium util module 1383 return E_NOTIMPL; 1384 1385 // remember to return S_FALSE if ppCounter == NULL and everything is OK 1386 } 1387#endif 1388 1389 virtual HRESULT STDMETHODCALLTYPE OpenSharedResource( 1390 HANDLE hResource, 1391 REFIID ReturnedInterface, 1392 void **ppResource) 1393 { 1394 SYNCHRONIZED; 1395 1396 // TODO: the problem here is that we need to communicate dimensions somehow 1397 return E_NOTIMPL; 1398 1399 // remember to return S_FALSE if ppCounter == NULL and everything is OK 1400#if 0 1401 struct pipe_resou rce templat; 1402 struct winsys_handle handle; 1403 handle.stride = 0; 1404 handle.handle = hResource; 1405 handle.type = DRM_API_HANDLE_TYPE_SHARED; 1406 screen->resource_from_handle(screen, &templat, &handle); 1407#endif 1408 } 1409 1410#if API < 11 1411 /* these are documented as "Not implemented". 1412 * According to the UMDDI documentation, they apparently turn on a 1413 * (Width + 1) x (Height + 1) convolution filter for 1-bit textures. 1414 * Probably nothing uses these, assuming it has ever been implemented anywhere. 1415 */ 1416 void STDMETHODCALLTYPE SetTextFilterSize( 1417 UINT Width, 1418 UINT Height 1419 ) 1420 {} 1421 1422 virtual void STDMETHODCALLTYPE GetTextFilterSize( 1423 UINT *Width, 1424 UINT *Height 1425 ) 1426 {} 1427#endif 1428 1429#if API >= 11 1430 virtual void STDMETHODCALLTYPE RestoreGalliumState() 1431 { 1432 GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(immediate_context); 1433 } 1434 1435 virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly() 1436 { 1437 GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(immediate_context); 1438 } 1439#endif 1440 1441 virtual struct pipe_context* STDMETHODCALLTYPE GetGalliumContext(void) 1442 { 1443 return immediate_pipe; 1444 } 1445 1446#undef SYNCHRONIZED 1447}; 1448