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