d3d11_screen.h revision 9f61e43b4903c6cf0ac03a479ec9ed7b15fd6ccf
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 // 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 /* TODO: is this correct? */ 508 /* TODO: we are ignoring depthBiasClamp! */ 509 state.offset_tri = state.offset_line = state.offset_point = rasterizer_desc->SlopeScaledDepthBias || rasterizer_desc->DepthBias; 510 state.offset_scale = rasterizer_desc->SlopeScaledDepthBias; 511 state.offset_units = rasterizer_desc->DepthBias; 512 state.scissor = !!rasterizer_desc->ScissorEnable; 513 state.multisample = !!rasterizer_desc->MultisampleEnable; 514 state.line_smooth = !!rasterizer_desc->AntialiasedLineEnable; 515 state.flatshade_first = 1; 516 state.line_width = 1.0f; 517 state.point_size = 1.0f; 518 519 /* TODO: is this correct? */ 520 state.point_quad_rasterization = 1; 521 522 if(!out_rasterizer_state) 523 return S_FALSE; 524 525 void* object = immediate_pipe->create_rasterizer_state(immediate_pipe, &state); 526 if(!object) 527 return E_FAIL; 528 529 *out_rasterizer_state = new GalliumD3D11RasterizerState(this, object, *rasterizer_desc, !rasterizer_desc->DepthClipEnable); 530 return S_OK; 531 } 532 533 virtual HRESULT STDMETHODCALLTYPE CreateSamplerState( 534 const D3D11_SAMPLER_DESC *sampler_desc, 535 ID3D11SamplerState **out_sampler_state) 536 { 537 SYNCHRONIZED; 538 539 pipe_sampler_state state; 540 memset(&state, 0, sizeof(state)); 541 state.normalized_coords = 1; 542 state.min_mip_filter = (sampler_desc->Filter & 1); 543 state.mag_img_filter = ((sampler_desc->Filter >> 2) & 1); 544 state.min_img_filter = ((sampler_desc->Filter >> 4) & 1); 545 if(sampler_desc->Filter & 0x40) 546 state.max_anisotropy = sampler_desc->MaxAnisotropy; 547 if(sampler_desc->Filter & 0x80) 548 { 549 state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; 550 state.compare_func = sampler_desc->ComparisonFunc; 551 } 552 state.wrap_s = d3d11_to_pipe_wrap[sampler_desc->AddressU]; 553 state.wrap_t = d3d11_to_pipe_wrap[sampler_desc->AddressV]; 554 state.wrap_r = d3d11_to_pipe_wrap[sampler_desc->AddressW]; 555 state.lod_bias = sampler_desc->MipLODBias; 556 memcpy(state.border_color.f, sampler_desc->BorderColor, sizeof(state.border_color)); 557 state.min_lod = sampler_desc->MinLOD; 558 state.max_lod = sampler_desc->MaxLOD; 559 560 if(!out_sampler_state) 561 return S_FALSE; 562 563 void* object = immediate_pipe->create_sampler_state(immediate_pipe, &state); 564 if(!object) 565 return E_FAIL; 566 567 *out_sampler_state = new GalliumD3D11SamplerState(this, object, *sampler_desc); 568 return S_OK; 569 } 570 571 virtual HRESULT STDMETHODCALLTYPE CreateInputLayout( 572 const D3D11_INPUT_ELEMENT_DESC *input_element_descs, 573 unsigned count, 574 const void *shader_bytecode_with_input_signature, 575 SIZE_T bytecode_length, 576 ID3D11InputLayout **out_input_layout) 577 { 578 SYNCHRONIZED; 579 580 if(count > D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT) 581 return E_INVALIDARG; 582 assert(D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT <= PIPE_MAX_ATTRIBS); 583 584 // putting semantics matching in the core API seems to be a (minor) design mistake 585 586 struct dxbc_chunk_signature* sig = dxbc_find_signature(shader_bytecode_with_input_signature, bytecode_length, false); 587 D3D11_SIGNATURE_PARAMETER_DESC* params; 588 unsigned num_params = dxbc_parse_signature(sig, ¶ms); 589 590 typedef std::unordered_map<std::pair<c_string, unsigned>, unsigned> semantic_to_idx_map_t; 591 semantic_to_idx_map_t semantic_to_idx_map; 592 for(unsigned i = 0; i < count; ++i) 593 semantic_to_idx_map[std::make_pair(c_string(input_element_descs[i].SemanticName), input_element_descs[i].SemanticIndex)] = i; 594 595 struct pipe_vertex_element elements[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT]; 596 597 unsigned num_params_to_use = std::min(num_params, (unsigned)D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT); 598 for(unsigned i = 0; i < num_params_to_use; ++i) 599 { 600 int idx = -1; 601 semantic_to_idx_map_t::iterator iter = semantic_to_idx_map.find(std::make_pair(c_string(params[i].SemanticName), params[i].SemanticIndex)); 602 if(iter != semantic_to_idx_map.end()) 603 idx = iter->second; 604 605 // 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? 606 // 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) 607 memset(&elements[i], 0, sizeof(elements[i])); 608 if(idx >= 0) 609 { 610 elements[i].src_format = dxgi_to_pipe_format[input_element_descs[idx].Format]; 611 elements[i].src_offset = input_element_descs[idx].AlignedByteOffset; 612 elements[i].vertex_buffer_index = input_element_descs[idx].InputSlot; 613 elements[i].instance_divisor = input_element_descs[idx].InstanceDataStepRate; 614 } 615 } 616 617 free(params); 618 619 if(!out_input_layout) 620 return S_FALSE; 621 622 void* object = immediate_pipe->create_vertex_elements_state(immediate_pipe, num_params_to_use, elements); 623 if(!object) 624 return E_FAIL; 625 626 *out_input_layout = new GalliumD3D11InputLayout(this, object); 627 return S_OK; 628 } 629 630 static unsigned d3d11_to_pipe_bind_flags(unsigned bind_flags) 631 { 632 unsigned bind = 0; 633 if(bind_flags & D3D11_BIND_VERTEX_BUFFER) 634 bind |= PIPE_BIND_VERTEX_BUFFER; 635 if(bind_flags & D3D11_BIND_INDEX_BUFFER) 636 bind |= PIPE_BIND_INDEX_BUFFER; 637 if(bind_flags & D3D11_BIND_CONSTANT_BUFFER) 638 bind |= PIPE_BIND_CONSTANT_BUFFER; 639 if(bind_flags & D3D11_BIND_SHADER_RESOURCE) 640 bind |= PIPE_BIND_SAMPLER_VIEW; 641 if(bind_flags & D3D11_BIND_STREAM_OUTPUT) 642 bind |= PIPE_BIND_STREAM_OUTPUT; 643 if(bind_flags & D3D11_BIND_RENDER_TARGET) 644 bind |= PIPE_BIND_RENDER_TARGET; 645 if(bind_flags & D3D11_BIND_DEPTH_STENCIL) 646 bind |= PIPE_BIND_DEPTH_STENCIL; 647 return bind; 648 } 649 650 inline HRESULT create_resource( 651 pipe_texture_target target, 652 unsigned width, 653 unsigned height, 654 unsigned depth, 655 unsigned mip_levels, 656 unsigned array_size, 657 DXGI_FORMAT format, 658 const DXGI_SAMPLE_DESC* SampleDesc, 659 D3D11_USAGE usage, 660 unsigned bind_flags, 661 unsigned c_p_u_access_flags, 662 unsigned misc_flags, 663 const D3D11_SUBRESOURCE_DATA *initial_data, 664 DXGI_USAGE dxgi_usage, 665 struct pipe_resource** ppresource 666 ) 667 { 668 if(invalid(format >= DXGI_FORMAT_COUNT)) 669 return E_INVALIDARG; 670 if(misc_flags & D3D11_RESOURCE_MISC_TEXTURECUBE) 671 { 672 if(target != PIPE_TEXTURE_2D) 673 return E_INVALIDARG; 674 target = PIPE_TEXTURE_CUBE; 675 676 if(array_size != 6) 677 return E_NOTIMPL; 678 } 679 else 680 { 681 if(array_size > 1) 682 return E_NOTIMPL; 683 array_size = 1; 684 } 685 /* TODO: msaa */ 686 struct pipe_resource templat; 687 memset(&templat, 0, sizeof(templat)); 688 templat.target = target; 689 templat.width0 = width; 690 templat.height0 = height; 691 templat.depth0 = depth; 692 if(mip_levels) 693 templat.last_level = mip_levels - 1; 694 else 695 templat.last_level = MAX2(MAX2(util_logbase2(templat.width0), util_logbase2(templat.height0)), util_logbase2(templat.depth0)); 696 templat.format = dxgi_to_pipe_format[format]; 697 templat.bind = d3d11_to_pipe_bind_flags(bind_flags); 698 if(c_p_u_access_flags & D3D11_CPU_ACCESS_READ) 699 templat.bind |= PIPE_BIND_TRANSFER_READ; 700 if(c_p_u_access_flags & D3D11_CPU_ACCESS_WRITE) 701 templat.bind |= PIPE_BIND_TRANSFER_WRITE; 702 if(misc_flags & D3D11_RESOURCE_MISC_SHARED) 703 templat.bind |= PIPE_BIND_SHARED; 704 if(misc_flags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE) 705 templat.bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE; 706 if(dxgi_usage & DXGI_USAGE_BACK_BUFFER) 707 templat.bind |= PIPE_BIND_DISPLAY_TARGET; 708 templat.usage = d3d11_to_pipe_usage[usage]; 709 if(invalid(!templat.format)) 710 return E_NOTIMPL; 711 712 if(!ppresource) 713 return S_FALSE; 714 715 struct pipe_resource* resource = screen->resource_create(screen, &templat); 716 if(!resource) 717 return E_FAIL; 718 if(initial_data) 719 { 720 for(unsigned slice = 0; slice < array_size; ++slice) 721 { 722 for(unsigned level = 0; level <= templat.last_level; ++level) 723 { 724 struct pipe_box box; 725 box.x = box.y = 0; 726 box.z = slice; 727 box.width = u_minify(width, level); 728 box.height = u_minify(height, level); 729 box.depth = 1; 730 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); 731 ++initial_data; 732 } 733 } 734 } 735 *ppresource = resource; 736 return S_OK; 737 } 738 739 static unsigned d3d_to_dxgi_usage(unsigned bind, unsigned misc) 740 { 741 unsigned dxgi_usage = 0; 742 if(bind |= D3D11_BIND_RENDER_TARGET) 743 dxgi_usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT; 744 if(bind & D3D11_BIND_SHADER_RESOURCE) 745 dxgi_usage |= DXGI_USAGE_SHADER_INPUT; 746#if API >= 11 747 if(bind & D3D11_BIND_UNORDERED_ACCESS) 748 dxgi_usage |= DXGI_USAGE_UNORDERED_ACCESS; 749#endif 750 if(misc & D3D11_RESOURCE_MISC_SHARED) 751 dxgi_usage |= DXGI_USAGE_SHARED; 752 return dxgi_usage; 753 } 754 755 virtual HRESULT STDMETHODCALLTYPE CreateTexture1D( 756 const D3D11_TEXTURE1D_DESC *desc, 757 const D3D11_SUBRESOURCE_DATA *initial_data, 758 ID3D11Texture1D **out_texture1d) 759 { 760 SYNCHRONIZED; 761 762 struct pipe_resource* resource; 763 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags); 764 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); 765 if(hr != S_OK) 766 return hr; 767 D3D11_TEXTURE1D_DESC cdesc = *desc; 768 cdesc.MipLevels = resource->last_level + 1; 769 *out_texture1d = new GalliumD3D11Texture1D(this, resource, cdesc, dxgi_usage); 770 return S_OK; 771 } 772 773 virtual HRESULT STDMETHODCALLTYPE CreateTexture2D( 774 const D3D11_TEXTURE2D_DESC *desc, 775 const D3D11_SUBRESOURCE_DATA *initial_data, 776 ID3D11Texture2D **out_texture2d) 777 { 778 SYNCHRONIZED; 779 780 struct pipe_resource* resource; 781 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags); 782 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); 783 if(hr != S_OK) 784 return hr; 785 D3D11_TEXTURE2D_DESC cdesc = *desc; 786 cdesc.MipLevels = resource->last_level + 1; 787 if(cdesc.MipLevels == 1 && cdesc.ArraySize == 1) 788 *out_texture2d = new GalliumD3D11Surface(this, resource, cdesc, dxgi_usage); 789 else 790 *out_texture2d = new GalliumD3D11Texture2D(this, resource, cdesc, dxgi_usage); 791 return S_OK; 792 } 793 794 virtual HRESULT STDMETHODCALLTYPE CreateTexture3D( 795 const D3D11_TEXTURE3D_DESC *desc, 796 const D3D11_SUBRESOURCE_DATA *initial_data, 797 ID3D11Texture3D **out_texture3d) 798 { 799 SYNCHRONIZED; 800 801 struct pipe_resource* resource; 802 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags); 803 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); 804 if(hr != S_OK) 805 return hr; 806 D3D11_TEXTURE3D_DESC cdesc = *desc; 807 cdesc.MipLevels = resource->last_level + 1; 808 *out_texture3d = new GalliumD3D11Texture3D(this, resource, cdesc, dxgi_usage); 809 return S_OK; 810 } 811 812 virtual HRESULT STDMETHODCALLTYPE CreateBuffer( 813 const D3D11_BUFFER_DESC *desc, 814 const D3D11_SUBRESOURCE_DATA *initial_data, 815 ID3D11Buffer **out_buffer) 816 { 817 SYNCHRONIZED; 818 819 struct pipe_resource* resource; 820 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags); 821 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); 822 if(hr != S_OK) 823 return hr; 824 *out_buffer = new GalliumD3D11Buffer(this, resource, *desc, dxgi_usage); 825 return S_OK; 826 } 827 828 virtual HRESULT STDMETHODCALLTYPE OpenGalliumResource( 829 struct pipe_resource* resource, 830 IUnknown** dxgi_resource) 831 { 832 SYNCHRONIZED; 833 834 /* TODO: maybe support others */ 835 assert(resource->target == PIPE_TEXTURE_2D); 836 *dxgi_resource = 0; 837 D3D11_TEXTURE2D_DESC desc; 838 memset(&desc, 0, sizeof(desc)); 839 desc.Width = resource->width0; 840 desc.Height = resource->height0; 841 init_pipe_to_dxgi_format(); 842 desc.Format = pipe_to_dxgi_format[resource->format]; 843 desc.SampleDesc.Count = resource->nr_samples; 844 desc.SampleDesc.Quality = 0; 845 desc.ArraySize = 1; 846 desc.MipLevels = resource->last_level + 1; 847 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 848 if(resource->bind & PIPE_BIND_RENDER_TARGET) 849 desc.BindFlags |= D3D11_BIND_RENDER_TARGET; 850 if(resource->bind & PIPE_BIND_DEPTH_STENCIL) 851 desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL; 852 if(resource->bind & PIPE_BIND_SAMPLER_VIEW) 853 desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; 854 if(resource->bind & PIPE_BIND_SHARED) 855 desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED; 856 DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc.BindFlags, desc.MiscFlags); 857 if(desc.MipLevels == 1 && desc.ArraySize == 1) 858 *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Surface(this, resource, desc, dxgi_usage); 859 else 860 *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Texture2D(this, resource, desc, dxgi_usage); 861 return S_OK; 862 } 863 864 virtual HRESULT STDMETHODCALLTYPE CreateSurface( 865 const DXGI_SURFACE_DESC *dxgi_desc, 866 unsigned count, 867 DXGI_USAGE usage, 868 const DXGI_SHARED_RESOURCE *shared_resource, 869 IDXGISurface **out_surface) 870 { 871 SYNCHRONIZED; 872 873 D3D11_TEXTURE2D_DESC desc; 874 memset(&desc, 0, sizeof(desc)); 875 876 struct pipe_resource* resource; 877 desc.Width = dxgi_desc->Width; 878 desc.Height = dxgi_desc->Height; 879 desc.Format = dxgi_desc->Format; 880 desc.SampleDesc = dxgi_desc->SampleDesc; 881 desc.ArraySize = count; 882 desc.MipLevels = 1; 883 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 884 if(usage & DXGI_USAGE_RENDER_TARGET_OUTPUT) 885 desc.BindFlags |= D3D11_BIND_RENDER_TARGET; 886 if(usage & DXGI_USAGE_SHADER_INPUT) 887 desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; 888#if API >= 11 889 if(usage & DXGI_USAGE_UNORDERED_ACCESS) 890 desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; 891#endif 892 if(usage & DXGI_USAGE_SHARED) 893 desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED; 894 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); 895 if(hr != S_OK) 896 return hr; 897 *out_surface = new GalliumD3D11Surface(this, resource, desc, usage); 898 return S_OK; 899 } 900 901 virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView( 902 ID3D11Resource *iresource, 903 const D3D11_SHADER_RESOURCE_VIEW_DESC *desc, 904 ID3D11ShaderResourceView **out_srv) 905 { 906#if API >= 11 907 D3D11_SHADER_RESOURCE_VIEW_DESC def_desc; 908#else 909 if(desc->ViewDimension == D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY) 910 return E_INVALIDARG; 911 D3D10_SHADER_RESOURCE_VIEW_DESC1 desc1; 912 memset(&desc1, 0, sizeof(desc1)); 913 memcpy(&desc1, desc, sizeof(*desc)); 914 return CreateShaderResourceView1(iresource, &desc1, (ID3D10ShaderResourceView1**)out_srv); 915 } 916 917 virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView1( 918 ID3D11Resource *iresource, 919 const D3D10_SHADER_RESOURCE_VIEW_DESC1 *desc, 920 ID3D10ShaderResourceView1 **out_srv) 921 { 922 D3D10_SHADER_RESOURCE_VIEW_DESC1 def_desc; 923#endif 924 SYNCHRONIZED; 925 926 if(!desc) 927 { 928 struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource; 929 init_pipe_to_dxgi_format(); 930 memset(&def_desc, 0, sizeof(def_desc)); 931 def_desc.Format = pipe_to_dxgi_format[resource->format]; 932 switch(resource->target) 933 { 934 case PIPE_BUFFER: 935 def_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; 936 def_desc.Buffer.ElementWidth = resource->width0; 937 break; 938 case PIPE_TEXTURE_1D: 939 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; 940 def_desc.Texture1D.MipLevels = resource->last_level + 1; 941 break; 942 case PIPE_TEXTURE_2D: 943 case PIPE_TEXTURE_RECT: 944 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 945 def_desc.Texture2D.MipLevels = resource->last_level + 1; 946 break; 947 case PIPE_TEXTURE_3D: 948 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; 949 def_desc.Texture3D.MipLevels = resource->last_level + 1; 950 break; 951 case PIPE_TEXTURE_CUBE: 952 def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; 953 def_desc.TextureCube.MipLevels = resource->last_level + 1; 954 break; 955 default: 956 return E_INVALIDARG; 957 } 958 desc = &def_desc; 959 } 960 961 struct pipe_sampler_view templat; 962 memset(&templat, 0, sizeof(templat)); 963 if(invalid(format >= DXGI_FORMAT_COUNT)) 964 return E_INVALIDARG; 965 templat.format = dxgi_to_pipe_format[desc->Format]; 966 if(!templat.format) 967 return E_NOTIMPL; 968 templat.swizzle_r = PIPE_SWIZZLE_RED; 969 templat.swizzle_g = PIPE_SWIZZLE_GREEN; 970 templat.swizzle_b = PIPE_SWIZZLE_BLUE; 971 templat.swizzle_a = PIPE_SWIZZLE_ALPHA; 972 973 templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource; 974 switch(desc->ViewDimension) 975 { 976 case D3D11_SRV_DIMENSION_TEXTURE1D: 977 case D3D11_SRV_DIMENSION_TEXTURE2D: 978 case D3D11_SRV_DIMENSION_TEXTURE3D: 979 case D3D11_SRV_DIMENSION_TEXTURE1DARRAY: 980 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: 981 /* yes, this works for all of these types (but TODO: texture arrays) */ 982 templat.u.tex.first_level = desc->Texture1D.MostDetailedMip; 983 templat.u.tex.last_level = templat.u.tex.first_level + desc->Texture1D.MipLevels - 1; 984 break; 985 case D3D11_SRV_DIMENSION_BUFFER: 986 case D3D11_SRV_DIMENSION_TEXTURE2DMS: 987 case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: 988 return E_NOTIMPL; 989 default: 990 return E_INVALIDARG; 991 } 992 993 if(!out_srv) 994 return S_FALSE; 995 996 struct pipe_sampler_view* view = immediate_pipe->create_sampler_view(immediate_pipe, templat.texture, &templat); 997 if(!view) 998 return E_FAIL; 999 *out_srv = new GalliumD3D11ShaderResourceView(this, (GalliumD3D11Resource<>*)iresource, view, *desc); 1000 return S_OK; 1001 } 1002 1003#if API >= 11 1004 virtual HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView( 1005 ID3D11Resource *resource, 1006 const D3D11_UNORDERED_ACCESS_VIEW_DESC *desc, 1007 ID3D11UnorderedAccessView **out_uav) 1008 { 1009 SYNCHRONIZED; 1010 1011 return E_NOTIMPL; 1012 1013 // remember to return S_FALSE and not crash if out_u_a_view == 0 and parameters are valid 1014 } 1015#endif 1016 1017 virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView( 1018 ID3D11Resource *iresource, 1019 const D3D11_RENDER_TARGET_VIEW_DESC *desc, 1020 ID3D11RenderTargetView **out_rtv) 1021 { 1022 SYNCHRONIZED; 1023 1024 D3D11_RENDER_TARGET_VIEW_DESC def_desc; 1025 if(!desc) 1026 { 1027 struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource; 1028 init_pipe_to_dxgi_format(); 1029 memset(&def_desc, 0, sizeof(def_desc)); 1030 def_desc.Format = pipe_to_dxgi_format[resource->format]; 1031 switch(resource->target) 1032 { 1033 case PIPE_BUFFER: 1034 def_desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER; 1035 def_desc.Buffer.ElementWidth = resource->width0; 1036 break; 1037 case PIPE_TEXTURE_1D: 1038 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D; 1039 break; 1040 case PIPE_TEXTURE_2D: 1041 case PIPE_TEXTURE_RECT: 1042 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; 1043 break; 1044 case PIPE_TEXTURE_3D: 1045 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; 1046 def_desc.Texture3D.WSize = resource->depth0; 1047 break; 1048 case PIPE_TEXTURE_CUBE: 1049 def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; 1050 def_desc.Texture2DArray.ArraySize = 6; 1051 break; 1052 default: 1053 return E_INVALIDARG; 1054 } 1055 desc = &def_desc; 1056 } 1057 1058 struct pipe_surface templat; 1059 memset(&templat, 0, sizeof(templat)); 1060 if(invalid(desc->format >= DXGI_FORMAT_COUNT)) 1061 return E_INVALIDARG; 1062 templat.format = dxgi_to_pipe_format[desc->Format]; 1063 if(!templat.format) 1064 return E_NOTIMPL; 1065 templat.usage = PIPE_BIND_RENDER_TARGET; 1066 templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource; 1067 1068 switch(desc->ViewDimension) 1069 { 1070 case D3D11_RTV_DIMENSION_TEXTURE1D: 1071 case D3D11_RTV_DIMENSION_TEXTURE2D: 1072 templat.u.tex.level = desc->Texture1D.MipSlice; 1073 break; 1074 case D3D11_RTV_DIMENSION_TEXTURE3D: 1075 templat.u.tex.level = desc->Texture3D.MipSlice; 1076 templat.u.tex.first_layer = desc->Texture3D.FirstWSlice; 1077 /* XXX FIXME */ 1078 templat.u.tex.last_layer = desc->Texture3D.FirstWSlice; 1079 break; 1080 case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: 1081 case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: 1082 templat.u.tex.level = desc->Texture1DArray.MipSlice; 1083 templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice; 1084 /* XXX FIXME */ 1085 templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice; 1086 break; 1087 case D3D11_RTV_DIMENSION_BUFFER: 1088 case D3D11_RTV_DIMENSION_TEXTURE2DMS: 1089 case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: 1090 return E_NOTIMPL; 1091 default: 1092 return E_INVALIDARG; 1093 } 1094 1095 if(!out_rtv) 1096 return S_FALSE; 1097 1098 struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat); 1099 if(!surface) 1100 return E_FAIL; 1101 *out_rtv = new GalliumD3D11RenderTargetView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc); 1102 return S_OK; 1103 } 1104 1105 virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilView( 1106 ID3D11Resource *iresource, 1107 const D3D11_DEPTH_STENCIL_VIEW_DESC *desc, 1108 ID3D11DepthStencilView **out_depth_stencil_view) 1109 { 1110 SYNCHRONIZED; 1111 1112 D3D11_DEPTH_STENCIL_VIEW_DESC def_desc; 1113 if(!desc) 1114 { 1115 struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource; 1116 init_pipe_to_dxgi_format(); 1117 memset(&def_desc, 0, sizeof(def_desc)); 1118 def_desc.Format = pipe_to_dxgi_format[resource->format]; 1119 switch(resource->target) 1120 { 1121 case PIPE_TEXTURE_1D: 1122 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D; 1123 break; 1124 case PIPE_TEXTURE_2D: 1125 case PIPE_TEXTURE_RECT: 1126 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; 1127 break; 1128 case PIPE_TEXTURE_CUBE: 1129 def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; 1130 def_desc.Texture2DArray.ArraySize = 6; 1131 break; 1132 default: 1133 return E_INVALIDARG; 1134 } 1135 desc = &def_desc; 1136 } 1137 1138 struct pipe_surface templat; 1139 memset(&templat, 0, sizeof(templat)); 1140 if(invalid(desc->format >= DXGI_FORMAT_COUNT)) 1141 return E_INVALIDARG; 1142 templat.format = dxgi_to_pipe_format[desc->Format]; 1143 if(!templat.format) 1144 return E_NOTIMPL; 1145 templat.usage = PIPE_BIND_DEPTH_STENCIL; 1146 templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource; 1147 1148 switch(desc->ViewDimension) 1149 { 1150 case D3D11_DSV_DIMENSION_TEXTURE1D: 1151 case D3D11_DSV_DIMENSION_TEXTURE2D: 1152 templat.u.tex.level = desc->Texture1D.MipSlice; 1153 break; 1154 case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: 1155 case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: 1156 templat.u.tex.level = desc->Texture1DArray.MipSlice; 1157 templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice; 1158 /* XXX FIXME */ 1159 templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice; 1160 break; 1161 case D3D11_DSV_DIMENSION_TEXTURE2DMS: 1162 case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: 1163 return E_NOTIMPL; 1164 default: 1165 return E_INVALIDARG; 1166 } 1167 1168 if(!out_depth_stencil_view) 1169 return S_FALSE; 1170 1171 struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat); 1172 if(!surface) 1173 return E_FAIL; 1174 *out_depth_stencil_view = new GalliumD3D11DepthStencilView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc); 1175 return S_OK; 1176 } 1177 1178 GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void* shader_bytecode, SIZE_T bytecode_length 1179#if API >= 11 1180 , ID3D11ClassLinkage *class_linkage 1181#endif 1182 ) 1183 { 1184 bool dump = debug_get_option_dump_shaders(); 1185 1186 dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(shader_bytecode, bytecode_length); 1187 if(!sm4_chunk) 1188 return 0; 1189 1190 std::auto_ptr<sm4_program> sm4(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size))); 1191 if(!sm4.get()) 1192 return 0; 1193 1194 if(dump) 1195 sm4->dump(); 1196 1197 struct pipe_shader_state tgsi_shader; 1198 memset(&tgsi_shader, 0, sizeof(tgsi_shader)); 1199 tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4); 1200 if(!tgsi_shader.tokens) 1201 return 0; 1202 1203 if(dump) 1204 tgsi_dump(tgsi_shader.tokens, 0); 1205 1206 void* shader_cso; 1207 GalliumD3D11Shader<>* shader; 1208 1209 switch(type) 1210 { 1211 case PIPE_SHADER_VERTEX: 1212 shader_cso = immediate_pipe->create_vs_state(immediate_pipe, &tgsi_shader); 1213 shader = (GalliumD3D11Shader<>*)new GalliumD3D11VertexShader(this, shader_cso); 1214 break; 1215 case PIPE_SHADER_FRAGMENT: 1216 shader_cso = immediate_pipe->create_fs_state(immediate_pipe, &tgsi_shader); 1217 shader = (GalliumD3D11Shader<>*)new GalliumD3D11PixelShader(this, shader_cso); 1218 break; 1219 case PIPE_SHADER_GEOMETRY: 1220 shader_cso = immediate_pipe->create_gs_state(immediate_pipe, &tgsi_shader); 1221 shader = (GalliumD3D11Shader<>*)new GalliumD3D11GeometryShader(this, shader_cso); 1222 break; 1223 default: 1224 shader_cso = 0; 1225 shader = 0; 1226 break; 1227 } 1228 1229 if(shader) 1230 { 1231 shader->slot_to_resource = sm4->slot_to_resource; 1232 shader->slot_to_sampler = sm4->slot_to_sampler; 1233 } 1234 1235 free((void*)tgsi_shader.tokens); 1236 return shader; 1237 } 1238 1239#if API >= 11 1240#define CREATE_SHADER_ARGS \ 1241 const void *shader_bytecode, \ 1242 SIZE_T bytecode_length, \ 1243 ID3D11ClassLinkage *class_linkage 1244#define PASS_SHADER_ARGS shader_bytecode, bytecode_length, class_linkage 1245#else 1246#define CREATE_SHADER_ARGS \ 1247 const void *shader_bytecode, \ 1248 SIZE_T bytecode_length 1249#define PASS_SHADER_ARGS shader_bytecode, bytecode_length 1250#endif 1251 1252#define IMPLEMENT_CREATE_SHADER(Stage, GALLIUM) \ 1253 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \ 1254 CREATE_SHADER_ARGS, \ 1255 ID3D11##Stage##Shader **out_shader) \ 1256 { \ 1257 SYNCHRONIZED; \ 1258 GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS); \ 1259 if(!shader) \ 1260 return E_FAIL; \ 1261 if(out_shader) \ 1262 { \ 1263 *out_shader = shader; \ 1264 return S_OK; \ 1265 } \ 1266 else \ 1267 { \ 1268 shader->Release(); \ 1269 return S_FALSE; \ 1270 } \ 1271 } 1272 1273#define IMPLEMENT_NOTIMPL_CREATE_SHADER(Stage) \ 1274 virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \ 1275 CREATE_SHADER_ARGS, \ 1276 ID3D11##Stage##Shader **out_shader) \ 1277 { \ 1278 return E_NOTIMPL; \ 1279 } 1280 1281 IMPLEMENT_CREATE_SHADER(Vertex, VERTEX) 1282 IMPLEMENT_CREATE_SHADER(Pixel, FRAGMENT) 1283 IMPLEMENT_CREATE_SHADER(Geometry, GEOMETRY) 1284#if API >= 11 1285 IMPLEMENT_NOTIMPL_CREATE_SHADER(Hull) 1286 IMPLEMENT_NOTIMPL_CREATE_SHADER(Domain) 1287 IMPLEMENT_NOTIMPL_CREATE_SHADER(Compute) 1288#endif 1289 1290 virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput( 1291 const void *shader_bytecode, 1292 SIZE_T bytecode_length, 1293 const D3D11_SO_DECLARATION_ENTRY *so_declaration, 1294 unsigned num_entries, 1295#if API >= 11 1296 const unsigned *buffer_strides, 1297 unsigned num_strides, 1298 unsigned rasterized_stream, 1299 ID3D11ClassLinkage *class_linkage, 1300#else 1301 UINT output_stream_stride, 1302#endif 1303 ID3D11GeometryShader **out_geometry_shader) 1304 { 1305 SYNCHRONIZED; 1306 1307 return E_NOTIMPL; 1308 1309 // remember to return S_FALSE if ppGeometyShader == NULL and the shader is OK 1310 } 1311 1312#if API >= 11 1313 virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage( 1314 ID3D11ClassLinkage **out_linkage) 1315 { 1316 SYNCHRONIZED; 1317 1318 return E_NOTIMPL; 1319 } 1320#endif 1321 1322 virtual HRESULT STDMETHODCALLTYPE CreateQuery( 1323 const D3D11_QUERY_DESC *query_desc, 1324 ID3D11Query **out_query) 1325 { 1326 SYNCHRONIZED; 1327 1328 if(invalid(query_desc->Query >= D3D11_QUERY_COUNT)) 1329 return E_INVALIDARG; 1330 unsigned query_type = d3d11_to_pipe_query[query_desc->Query]; 1331 if(!query_type) 1332 return E_NOTIMPL; 1333 1334 if(out_query) 1335 return S_FALSE; 1336 1337 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type); 1338 if(!query) 1339 return E_FAIL; 1340 1341 *out_query = new GalliumD3D11Query(this, query, d3d11_query_size[query_desc->Query], *query_desc); 1342 return S_OK; 1343 } 1344 1345 virtual HRESULT STDMETHODCALLTYPE CreatePredicate( 1346 const D3D11_QUERY_DESC *predicate_desc, 1347 ID3D11Predicate **out_predicate) 1348 { 1349 SYNCHRONIZED; 1350 1351 unsigned query_type; 1352 switch(predicate_desc->Query) 1353 { 1354 case D3D11_QUERY_SO_OVERFLOW_PREDICATE: 1355 return E_NOTIMPL; 1356 case D3D11_QUERY_OCCLUSION_PREDICATE: 1357 query_type = PIPE_QUERY_OCCLUSION_COUNTER; 1358 break; 1359 default: 1360 return E_INVALIDARG; 1361 } 1362 1363 if(out_predicate) 1364 return S_FALSE; 1365 1366 struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type); 1367 if(!query) 1368 return E_FAIL; 1369 1370 *out_predicate = new GalliumD3D11Predicate(this, query, sizeof(BOOL), *predicate_desc); 1371 return S_OK; 1372 } 1373 1374 1375 virtual HRESULT STDMETHODCALLTYPE CreateCounter( 1376 const D3D11_COUNTER_DESC *counter_desc, 1377 ID3D11Counter **out_counter) 1378 { 1379 SYNCHRONIZED; 1380 1381 return E_NOTIMPL; 1382 1383 // remember to return S_FALSE if out_counter == NULL and everything is OK 1384 } 1385 1386#if API >= 11 1387 virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext( 1388 unsigned context_flags, 1389 ID3D11DeviceContext **out_deferred_context) 1390 { 1391 SYNCHRONIZED; 1392 1393 // TODO: this will have to be implemented using a new Gallium util module 1394 return E_NOTIMPL; 1395 1396 // remember to return S_FALSE if out_counter == NULL and everything is OK 1397 } 1398#endif 1399 1400 virtual HRESULT STDMETHODCALLTYPE OpenSharedResource( 1401 HANDLE resource, 1402 REFIID iid, 1403 void **out_resource) 1404 { 1405 SYNCHRONIZED; 1406 1407 // TODO: the problem here is that we need to communicate dimensions somehow 1408 return E_NOTIMPL; 1409 1410 // remember to return S_FALSE if out_counter == NULL and everything is OK 1411#if 0 1412 struct pipe_resou rce templat; 1413 struct winsys_handle handle; 1414 handle.stride = 0; 1415 handle.handle = resource; 1416 handle.type = DRM_API_HANDLE_TYPE_SHARED; 1417 screen->resource_from_handle(screen, &templat, &handle); 1418#endif 1419 } 1420 1421#if API < 11 1422 /* these are documented as "Not implemented". 1423 * According to the UMDDI documentation, they apparently turn on a 1424 * (width + 1) x (height + 1) convolution filter for 1-bit textures. 1425 * Probably nothing uses these, assuming it has ever been implemented anywhere. 1426 */ 1427 void STDMETHODCALLTYPE SetTextFilterSize( 1428 UINT width, 1429 UINT height 1430 ) 1431 {} 1432 1433 virtual void STDMETHODCALLTYPE GetTextFilterSize( 1434 UINT *width, 1435 UINT *height 1436 ) 1437 {} 1438#endif 1439 1440#if API >= 11 1441 virtual void STDMETHODCALLTYPE RestoreGalliumState() 1442 { 1443 GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(immediate_context); 1444 } 1445 1446 virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly() 1447 { 1448 GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(immediate_context); 1449 } 1450#endif 1451 1452 virtual struct pipe_context* STDMETHODCALLTYPE GetGalliumContext(void) 1453 { 1454 return immediate_pipe; 1455 } 1456 1457#undef SYNCHRONIZED 1458}; 1459