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