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