1 #include "precompiled.h" 2 // 3 // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 // 7 8 // TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived 9 // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. 10 11 #include "libGLESv2/renderer/d3d11/TextureStorage11.h" 12 13 #include "libGLESv2/renderer/d3d11/Renderer11.h" 14 #include "libGLESv2/renderer/d3d11/RenderTarget11.h" 15 #include "libGLESv2/renderer/d3d11/SwapChain11.h" 16 #include "libGLESv2/renderer/d3d11/renderer11_utils.h" 17 #include "libGLESv2/renderer/d3d11/Blit11.h" 18 #include "libGLESv2/renderer/d3d11/formatutils11.h" 19 20 #include "common/utilities.h" 21 #include "libGLESv2/main.h" 22 23 namespace rx 24 { 25 26 TextureStorage11::SwizzleCacheValue::SwizzleCacheValue() 27 : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE) 28 { 29 } 30 31 TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha) 32 : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha) 33 { 34 } 35 36 bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const 37 { 38 return swizzleRed == other.swizzleRed && 39 swizzleGreen == other.swizzleGreen && 40 swizzleBlue == other.swizzleBlue && 41 swizzleAlpha == other.swizzleAlpha; 42 } 43 44 bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const 45 { 46 return !(*this == other); 47 } 48 49 TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle) 50 : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle) 51 { 52 } 53 54 bool TextureStorage11::SRVKey::operator==(const SRVKey &rhs) const 55 { 56 return baseLevel == rhs.baseLevel && 57 mipLevels == rhs.mipLevels && 58 swizzle == rhs.swizzle; 59 } 60 61 TextureStorage11::SRVCache::~SRVCache() 62 { 63 for (size_t i = 0; i < cache.size(); i++) 64 { 65 SafeRelease(cache[i].srv); 66 } 67 } 68 69 ID3D11ShaderResourceView *TextureStorage11::SRVCache::find(const SRVKey &key) const 70 { 71 for (size_t i = 0; i < cache.size(); i++) 72 { 73 if (cache[i].key == key) 74 { 75 return cache[i].srv; 76 } 77 } 78 79 return NULL; 80 } 81 82 ID3D11ShaderResourceView *TextureStorage11::SRVCache::add(const SRVKey &key, ID3D11ShaderResourceView *srv) 83 { 84 SRVPair pair = {key, srv}; 85 cache.push_back(pair); 86 87 return srv; 88 } 89 90 TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) 91 : mBindFlags(bindFlags), 92 mTopLevel(0), 93 mMipLevels(0), 94 mTextureFormat(DXGI_FORMAT_UNKNOWN), 95 mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), 96 mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), 97 mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), 98 mTextureWidth(0), 99 mTextureHeight(0), 100 mTextureDepth(0) 101 { 102 mRenderer = Renderer11::makeRenderer11(renderer); 103 104 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 105 { 106 mLevelSRVs[i] = NULL; 107 } 108 } 109 110 TextureStorage11::~TextureStorage11() 111 { 112 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) 113 { 114 SafeRelease(mLevelSRVs[level]); 115 } 116 } 117 118 TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) 119 { 120 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); 121 return static_cast<TextureStorage11*>(storage); 122 } 123 124 DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, GLuint clientVersion, bool renderTarget) 125 { 126 UINT bindFlags = 0; 127 128 if (gl_d3d11::GetSRVFormat(internalFormat, clientVersion) != DXGI_FORMAT_UNKNOWN) 129 { 130 bindFlags |= D3D11_BIND_SHADER_RESOURCE; 131 } 132 if (gl_d3d11::GetDSVFormat(internalFormat, clientVersion) != DXGI_FORMAT_UNKNOWN) 133 { 134 bindFlags |= D3D11_BIND_DEPTH_STENCIL; 135 } 136 if (gl_d3d11::GetRTVFormat(internalFormat, clientVersion) != DXGI_FORMAT_UNKNOWN && renderTarget) 137 { 138 bindFlags |= D3D11_BIND_RENDER_TARGET; 139 } 140 141 return bindFlags; 142 } 143 144 UINT TextureStorage11::getBindFlags() const 145 { 146 return mBindFlags; 147 } 148 149 int TextureStorage11::getTopLevel() const 150 { 151 return mTopLevel; 152 } 153 154 bool TextureStorage11::isRenderTarget() const 155 { 156 return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; 157 } 158 159 bool TextureStorage11::isManaged() const 160 { 161 return false; 162 } 163 164 int TextureStorage11::getLevelCount() const 165 { 166 return mMipLevels - mTopLevel; 167 } 168 169 int TextureStorage11::getLevelWidth(int mipLevel) const 170 { 171 return std::max(static_cast<int>(mTextureWidth) >> mipLevel, 1); 172 } 173 174 int TextureStorage11::getLevelHeight(int mipLevel) const 175 { 176 return std::max(static_cast<int>(mTextureHeight) >> mipLevel, 1); 177 } 178 179 int TextureStorage11::getLevelDepth(int mipLevel) const 180 { 181 return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1); 182 } 183 184 UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const 185 { 186 UINT index = 0; 187 if (getResource()) 188 { 189 index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels); 190 } 191 return index; 192 } 193 194 ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState) 195 { 196 bool swizzleRequired = samplerState.swizzleRequired(); 197 bool mipmapping = gl::IsMipmapFiltered(samplerState); 198 unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel) : 1; 199 200 // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) 201 mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel); 202 203 if (swizzleRequired) 204 { 205 verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha); 206 } 207 208 SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired); 209 ID3D11ShaderResourceView *srv = srvCache.find(key); 210 211 if(srv) 212 { 213 return srv; 214 } 215 216 DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); 217 ID3D11Resource *texture = swizzleRequired ? getSwizzleTexture() : getResource(); 218 219 srv = createSRV(samplerState.baseLevel, mipLevels, format, texture); 220 221 return srvCache.add(key, srv); 222 } 223 224 ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel) 225 { 226 if (mipLevel >= 0 && mipLevel < getLevelCount()) 227 { 228 if (!mLevelSRVs[mipLevel]) 229 { 230 mLevelSRVs[mipLevel] = createSRV(mipLevel, 1, mShaderResourceFormat, getResource()); 231 } 232 233 return mLevelSRVs[mipLevel]; 234 } 235 else 236 { 237 return NULL; 238 } 239 } 240 241 void TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) 242 { 243 SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); 244 for (int level = 0; level < getLevelCount(); level++) 245 { 246 // Check if the swizzle for this level is out of date 247 if (mSwizzleCache[level] != swizzleTarget) 248 { 249 // Need to re-render the swizzle for this level 250 ID3D11ShaderResourceView *sourceSRV = getSRVLevel(level); 251 ID3D11RenderTargetView *destRTV = getSwizzleRenderTarget(level); 252 253 gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); 254 255 Blit11 *blitter = mRenderer->getBlitter(); 256 257 if (blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha)) 258 { 259 mSwizzleCache[level] = swizzleTarget; 260 } 261 else 262 { 263 ERR("Failed to swizzle texture."); 264 } 265 } 266 } 267 } 268 269 void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel) 270 { 271 if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache)) 272 { 273 // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a 274 // valid swizzle combination 275 mSwizzleCache[mipLevel] = SwizzleCacheValue(); 276 } 277 } 278 279 void TextureStorage11::invalidateSwizzleCache() 280 { 281 for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++) 282 { 283 invalidateSwizzleCacheLevel(mipLevel); 284 } 285 } 286 287 bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource, 288 int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, 289 GLsizei width, GLsizei height, GLsizei depth) 290 { 291 if (srcTexture) 292 { 293 invalidateSwizzleCacheLevel(level); 294 295 gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); 296 gl::Box copyArea(xoffset, yoffset, zoffset, width, height, depth); 297 298 bool fullCopy = copyArea.x == 0 && 299 copyArea.y == 0 && 300 copyArea.z == 0 && 301 copyArea.width == texSize.width && 302 copyArea.height == texSize.height && 303 copyArea.depth == texSize.depth; 304 305 ID3D11Resource *dstTexture = getResource(); 306 unsigned int dstSubresource = getSubresourceIndex(level + mTopLevel, layerTarget); 307 308 ASSERT(dstTexture); 309 310 if (!fullCopy && (d3d11::GetDepthBits(mTextureFormat) > 0 || d3d11::GetStencilBits(mTextureFormat) > 0)) 311 { 312 // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead 313 Blit11 *blitter = mRenderer->getBlitter(); 314 315 return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, 316 dstTexture, dstSubresource, copyArea, texSize, 317 NULL); 318 } 319 else 320 { 321 D3D11_BOX srcBox; 322 srcBox.left = copyArea.x; 323 srcBox.top = copyArea.y; 324 srcBox.right = copyArea.x + roundUp((unsigned int)width, d3d11::GetBlockWidth(mTextureFormat)); 325 srcBox.bottom = copyArea.y + roundUp((unsigned int)height, d3d11::GetBlockHeight(mTextureFormat)); 326 srcBox.front = copyArea.z; 327 srcBox.back = copyArea.z + copyArea.depth; 328 329 ID3D11DeviceContext *context = mRenderer->getDeviceContext(); 330 331 context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, 332 srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox); 333 return true; 334 } 335 } 336 337 return false; 338 } 339 340 void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) 341 { 342 if (source && dest) 343 { 344 ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); 345 ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); 346 347 if (sourceSRV && destRTV) 348 { 349 gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); 350 gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); 351 352 gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth()); 353 gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); 354 355 Blit11 *blitter = mRenderer->getBlitter(); 356 357 blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, 358 gl::GetFormat(source->getInternalFormat(), mRenderer->getCurrentClientVersion()), 359 GL_LINEAR); 360 } 361 } 362 } 363 364 void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) 365 { 366 SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); 367 for (unsigned int level = 0; level < mMipLevels; level++) 368 { 369 ASSERT(mSwizzleCache[level] == swizzleTarget); 370 } 371 } 372 373 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) 374 : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) 375 { 376 mTexture = swapchain->getOffscreenTexture(); 377 mTexture->AddRef(); 378 mSwizzleTexture = NULL; 379 380 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 381 { 382 mRenderTarget[i] = NULL; 383 mSwizzleRenderTargets[i] = NULL; 384 } 385 386 D3D11_TEXTURE2D_DESC texDesc; 387 mTexture->GetDesc(&texDesc); 388 mMipLevels = texDesc.MipLevels; 389 mTextureFormat = texDesc.Format; 390 mTextureWidth = texDesc.Width; 391 mTextureHeight = texDesc.Height; 392 mTextureDepth = 1; 393 394 ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); 395 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 396 srv->GetDesc(&srvDesc); 397 mShaderResourceFormat = srvDesc.Format; 398 399 ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); 400 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 401 offscreenRTV->GetDesc(&rtvDesc); 402 mRenderTargetFormat = rtvDesc.Format; 403 404 GLint internalFormat = d3d11_gl::GetInternalFormat(mTextureFormat, renderer->getCurrentClientVersion()); 405 mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalFormat, renderer); 406 mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalFormat, renderer); 407 mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalFormat, renderer); 408 409 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; 410 } 411 412 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) 413 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), renderTarget)) 414 { 415 mTexture = NULL; 416 mSwizzleTexture = NULL; 417 418 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 419 { 420 mRenderTarget[i] = NULL; 421 mSwizzleRenderTargets[i] = NULL; 422 } 423 424 GLuint clientVersion = mRenderer->getCurrentClientVersion(); 425 426 mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion); 427 mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion); 428 mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion); 429 mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion); 430 mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat, renderer); 431 mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat, renderer); 432 mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat, renderer); 433 434 // if the width or height is not positive this should be treated as an incomplete texture 435 // we handle that here by skipping the d3d texture creation 436 if (width > 0 && height > 0) 437 { 438 // adjust size if needed for compressed textures 439 d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); 440 441 ID3D11Device *device = mRenderer->getDevice(); 442 443 D3D11_TEXTURE2D_DESC desc; 444 desc.Width = width; // Compressed texture size constraints? 445 desc.Height = height; 446 desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); 447 desc.ArraySize = 1; 448 desc.Format = mTextureFormat; 449 desc.SampleDesc.Count = 1; 450 desc.SampleDesc.Quality = 0; 451 desc.Usage = D3D11_USAGE_DEFAULT; 452 desc.BindFlags = getBindFlags(); 453 desc.CPUAccessFlags = 0; 454 desc.MiscFlags = 0; 455 456 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); 457 458 // this can happen from windows TDR 459 if (d3d11::isDeviceLostError(result)) 460 { 461 mRenderer->notifyDeviceLost(); 462 gl::error(GL_OUT_OF_MEMORY); 463 } 464 else if (FAILED(result)) 465 { 466 ASSERT(result == E_OUTOFMEMORY); 467 ERR("Creating image failed."); 468 gl::error(GL_OUT_OF_MEMORY); 469 } 470 else 471 { 472 mTexture->GetDesc(&desc); 473 mMipLevels = desc.MipLevels; 474 mTextureWidth = desc.Width; 475 mTextureHeight = desc.Height; 476 mTextureDepth = 1; 477 } 478 } 479 } 480 481 TextureStorage11_2D::~TextureStorage11_2D() 482 { 483 SafeRelease(mTexture); 484 SafeRelease(mSwizzleTexture); 485 486 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 487 { 488 SafeDelete(mRenderTarget[i]); 489 SafeRelease(mSwizzleRenderTargets[i]); 490 } 491 } 492 493 TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) 494 { 495 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); 496 return static_cast<TextureStorage11_2D*>(storage); 497 } 498 499 ID3D11Resource *TextureStorage11_2D::getResource() const 500 { 501 return mTexture; 502 } 503 504 RenderTarget *TextureStorage11_2D::getRenderTarget(int level) 505 { 506 if (level >= 0 && level < getLevelCount()) 507 { 508 if (!mRenderTarget[level]) 509 { 510 ID3D11ShaderResourceView *srv = getSRVLevel(level); 511 if (!srv) 512 { 513 return NULL; 514 } 515 516 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) 517 { 518 ID3D11Device *device = mRenderer->getDevice(); 519 520 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 521 rtvDesc.Format = mRenderTargetFormat; 522 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; 523 rtvDesc.Texture2D.MipSlice = mTopLevel + level; 524 525 ID3D11RenderTargetView *rtv; 526 HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); 527 528 if (result == E_OUTOFMEMORY) 529 { 530 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 531 } 532 ASSERT(SUCCEEDED(result)); 533 534 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); 535 536 // RenderTarget will take ownership of these resources 537 SafeRelease(rtv); 538 } 539 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) 540 { 541 ID3D11Device *device = mRenderer->getDevice(); 542 543 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; 544 dsvDesc.Format = mDepthStencilFormat; 545 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; 546 dsvDesc.Texture2D.MipSlice = mTopLevel + level; 547 dsvDesc.Flags = 0; 548 549 ID3D11DepthStencilView *dsv; 550 HRESULT result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); 551 552 if (result == E_OUTOFMEMORY) 553 { 554 SafeRelease(srv); 555 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 556 } 557 ASSERT(SUCCEEDED(result)); 558 559 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); 560 561 // RenderTarget will take ownership of these resources 562 SafeRelease(dsv); 563 } 564 else 565 { 566 UNREACHABLE(); 567 } 568 } 569 570 return mRenderTarget[level]; 571 } 572 else 573 { 574 return NULL; 575 } 576 } 577 578 ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) 579 { 580 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 581 srvDesc.Format = format; 582 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 583 srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; 584 srvDesc.Texture2D.MipLevels = mipLevels; 585 586 ID3D11ShaderResourceView *SRV = NULL; 587 588 ID3D11Device *device = mRenderer->getDevice(); 589 HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); 590 591 if (result == E_OUTOFMEMORY) 592 { 593 gl::error(GL_OUT_OF_MEMORY); 594 } 595 ASSERT(SUCCEEDED(result)); 596 597 return SRV; 598 } 599 600 void TextureStorage11_2D::generateMipmap(int level) 601 { 602 invalidateSwizzleCacheLevel(level); 603 604 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); 605 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); 606 607 generateMipmapLayer(source, dest); 608 } 609 610 ID3D11Resource *TextureStorage11_2D::getSwizzleTexture() 611 { 612 if (!mSwizzleTexture) 613 { 614 ID3D11Device *device = mRenderer->getDevice(); 615 616 D3D11_TEXTURE2D_DESC desc; 617 desc.Width = mTextureWidth; 618 desc.Height = mTextureHeight; 619 desc.MipLevels = mMipLevels; 620 desc.ArraySize = 1; 621 desc.Format = mSwizzleTextureFormat; 622 desc.SampleDesc.Count = 1; 623 desc.SampleDesc.Quality = 0; 624 desc.Usage = D3D11_USAGE_DEFAULT; 625 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; 626 desc.CPUAccessFlags = 0; 627 desc.MiscFlags = 0; 628 629 HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); 630 631 if (result == E_OUTOFMEMORY) 632 { 633 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL)); 634 } 635 ASSERT(SUCCEEDED(result)); 636 } 637 638 return mSwizzleTexture; 639 } 640 641 ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel) 642 { 643 if (mipLevel >= 0 && mipLevel < getLevelCount()) 644 { 645 if (!mSwizzleRenderTargets[mipLevel]) 646 { 647 ID3D11Resource *swizzleTexture = getSwizzleTexture(); 648 if (!swizzleTexture) 649 { 650 return NULL; 651 } 652 653 ID3D11Device *device = mRenderer->getDevice(); 654 655 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 656 rtvDesc.Format = mSwizzleRenderTargetFormat; 657 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; 658 rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; 659 660 HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); 661 if (result == E_OUTOFMEMORY) 662 { 663 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL)); 664 } 665 ASSERT(SUCCEEDED(result)); 666 } 667 668 return mSwizzleRenderTargets[mipLevel]; 669 } 670 else 671 { 672 return NULL; 673 } 674 } 675 676 unsigned int TextureStorage11_2D::getTextureLevelDepth(int mipLevel) const 677 { 678 return 1; 679 } 680 681 TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) 682 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), renderTarget)) 683 { 684 mTexture = NULL; 685 mSwizzleTexture = NULL; 686 687 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) 688 { 689 mSwizzleRenderTargets[level] = NULL; 690 for (unsigned int face = 0; face < 6; face++) 691 { 692 mRenderTarget[face][level] = NULL; 693 } 694 } 695 696 GLuint clientVersion = mRenderer->getCurrentClientVersion(); 697 698 mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion); 699 mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion); 700 mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion); 701 mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion); 702 mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat, renderer); 703 mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat, renderer); 704 mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat, renderer); 705 706 // if the size is not positive this should be treated as an incomplete texture 707 // we handle that here by skipping the d3d texture creation 708 if (size > 0) 709 { 710 // adjust size if needed for compressed textures 711 int height = size; 712 d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel); 713 714 ID3D11Device *device = mRenderer->getDevice(); 715 716 D3D11_TEXTURE2D_DESC desc; 717 desc.Width = size; 718 desc.Height = size; 719 desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); 720 desc.ArraySize = 6; 721 desc.Format = mTextureFormat; 722 desc.SampleDesc.Count = 1; 723 desc.SampleDesc.Quality = 0; 724 desc.Usage = D3D11_USAGE_DEFAULT; 725 desc.BindFlags = getBindFlags(); 726 desc.CPUAccessFlags = 0; 727 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; 728 729 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); 730 731 if (FAILED(result)) 732 { 733 ASSERT(result == E_OUTOFMEMORY); 734 ERR("Creating image failed."); 735 gl::error(GL_OUT_OF_MEMORY); 736 } 737 else 738 { 739 mTexture->GetDesc(&desc); 740 mMipLevels = desc.MipLevels; 741 mTextureWidth = desc.Width; 742 mTextureHeight = desc.Height; 743 mTextureDepth = 1; 744 } 745 } 746 } 747 748 TextureStorage11_Cube::~TextureStorage11_Cube() 749 { 750 SafeRelease(mTexture); 751 SafeRelease(mSwizzleTexture); 752 753 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) 754 { 755 SafeRelease(mSwizzleRenderTargets[level]); 756 for (unsigned int face = 0; face < 6; face++) 757 { 758 SafeDelete(mRenderTarget[face][level]); 759 } 760 } 761 } 762 763 TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) 764 { 765 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); 766 return static_cast<TextureStorage11_Cube*>(storage); 767 } 768 769 ID3D11Resource *TextureStorage11_Cube::getResource() const 770 { 771 return mTexture; 772 } 773 774 RenderTarget *TextureStorage11_Cube::getRenderTargetFace(GLenum faceTarget, int level) 775 { 776 if (level >= 0 && level < getLevelCount()) 777 { 778 int faceIndex = gl::TextureCubeMap::targetToIndex(faceTarget); 779 if (!mRenderTarget[faceIndex][level]) 780 { 781 ID3D11Device *device = mRenderer->getDevice(); 782 HRESULT result; 783 784 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 785 srvDesc.Format = mShaderResourceFormat; 786 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube 787 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; 788 srvDesc.Texture2DArray.MipLevels = 1; 789 srvDesc.Texture2DArray.FirstArraySlice = faceIndex; 790 srvDesc.Texture2DArray.ArraySize = 1; 791 792 ID3D11ShaderResourceView *srv; 793 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); 794 795 if (result == E_OUTOFMEMORY) 796 { 797 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 798 } 799 ASSERT(SUCCEEDED(result)); 800 801 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) 802 { 803 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 804 rtvDesc.Format = mRenderTargetFormat; 805 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; 806 rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; 807 rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; 808 rtvDesc.Texture2DArray.ArraySize = 1; 809 810 ID3D11RenderTargetView *rtv; 811 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); 812 813 if (result == E_OUTOFMEMORY) 814 { 815 SafeRelease(srv); 816 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 817 } 818 ASSERT(SUCCEEDED(result)); 819 820 mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); 821 822 // RenderTarget will take ownership of these resources 823 SafeRelease(rtv); 824 SafeRelease(srv); 825 } 826 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) 827 { 828 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; 829 dsvDesc.Format = mDepthStencilFormat; 830 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; 831 dsvDesc.Flags = 0; 832 dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; 833 dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; 834 dsvDesc.Texture2DArray.ArraySize = 1; 835 836 ID3D11DepthStencilView *dsv; 837 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); 838 839 if (result == E_OUTOFMEMORY) 840 { 841 SafeRelease(srv); 842 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 843 } 844 ASSERT(SUCCEEDED(result)); 845 846 mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); 847 848 // RenderTarget will take ownership of these resources 849 SafeRelease(dsv); 850 SafeRelease(srv); 851 } 852 else 853 { 854 UNREACHABLE(); 855 } 856 } 857 858 return mRenderTarget[faceIndex][level]; 859 } 860 else 861 { 862 return NULL; 863 } 864 } 865 866 ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) 867 { 868 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 869 srvDesc.Format = format; 870 871 // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures 872 bool unnormalizedInteger = (d3d11::GetComponentType(mTextureFormat) == GL_INT || 873 d3d11::GetComponentType(mTextureFormat) == GL_UNSIGNED_INT); 874 875 if(unnormalizedInteger) 876 { 877 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; 878 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; 879 srvDesc.Texture2DArray.MipLevels = 1; 880 srvDesc.Texture2DArray.FirstArraySlice = 0; 881 srvDesc.Texture2DArray.ArraySize = 6; 882 } 883 else 884 { 885 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; 886 srvDesc.TextureCube.MipLevels = mipLevels; 887 srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; 888 } 889 890 ID3D11ShaderResourceView *SRV = NULL; 891 892 ID3D11Device *device = mRenderer->getDevice(); 893 HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); 894 895 if (result == E_OUTOFMEMORY) 896 { 897 gl::error(GL_OUT_OF_MEMORY); 898 } 899 ASSERT(SUCCEEDED(result)); 900 901 return SRV; 902 } 903 904 void TextureStorage11_Cube::generateMipmap(int faceIndex, int level) 905 { 906 invalidateSwizzleCacheLevel(level); 907 908 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1)); 909 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level)); 910 911 generateMipmapLayer(source, dest); 912 } 913 914 ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture() 915 { 916 if (!mSwizzleTexture) 917 { 918 ID3D11Device *device = mRenderer->getDevice(); 919 920 D3D11_TEXTURE2D_DESC desc; 921 desc.Width = mTextureWidth; 922 desc.Height = mTextureHeight; 923 desc.MipLevels = mMipLevels; 924 desc.ArraySize = 6; 925 desc.Format = mSwizzleTextureFormat; 926 desc.SampleDesc.Count = 1; 927 desc.SampleDesc.Quality = 0; 928 desc.Usage = D3D11_USAGE_DEFAULT; 929 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; 930 desc.CPUAccessFlags = 0; 931 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; 932 933 HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); 934 935 if (result == E_OUTOFMEMORY) 936 { 937 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL)); 938 } 939 ASSERT(SUCCEEDED(result)); 940 } 941 942 return mSwizzleTexture; 943 } 944 945 ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel) 946 { 947 if (mipLevel >= 0 && mipLevel < getLevelCount()) 948 { 949 if (!mSwizzleRenderTargets[mipLevel]) 950 { 951 ID3D11Resource *swizzleTexture = getSwizzleTexture(); 952 if (!swizzleTexture) 953 { 954 return NULL; 955 } 956 957 ID3D11Device *device = mRenderer->getDevice(); 958 959 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 960 rtvDesc.Format = mSwizzleRenderTargetFormat; 961 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; 962 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; 963 rtvDesc.Texture2DArray.FirstArraySlice = 0; 964 rtvDesc.Texture2DArray.ArraySize = 6; 965 966 HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); 967 968 if (result == E_OUTOFMEMORY) 969 { 970 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL)); 971 } 972 ASSERT(SUCCEEDED(result)); 973 } 974 975 return mSwizzleRenderTargets[mipLevel]; 976 } 977 else 978 { 979 return NULL; 980 } 981 } 982 983 unsigned int TextureStorage11_Cube::getTextureLevelDepth(int mipLevel) const 984 { 985 return 6; 986 } 987 988 TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget, 989 GLsizei width, GLsizei height, GLsizei depth, int levels) 990 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), renderTarget)) 991 { 992 mTexture = NULL; 993 mSwizzleTexture = NULL; 994 995 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 996 { 997 mLevelRenderTargets[i] = NULL; 998 mSwizzleRenderTargets[i] = NULL; 999 } 1000 1001 GLuint clientVersion = mRenderer->getCurrentClientVersion(); 1002 1003 mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion); 1004 mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion); 1005 mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion); 1006 mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion); 1007 mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat, renderer); 1008 mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat, renderer); 1009 mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat, renderer); 1010 1011 // If the width, height or depth are not positive this should be treated as an incomplete texture 1012 // we handle that here by skipping the d3d texture creation 1013 if (width > 0 && height > 0 && depth > 0) 1014 { 1015 // adjust size if needed for compressed textures 1016 d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); 1017 1018 ID3D11Device *device = mRenderer->getDevice(); 1019 1020 D3D11_TEXTURE3D_DESC desc; 1021 desc.Width = width; 1022 desc.Height = height; 1023 desc.Depth = depth; 1024 desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); 1025 desc.Format = mTextureFormat; 1026 desc.Usage = D3D11_USAGE_DEFAULT; 1027 desc.BindFlags = getBindFlags(); 1028 desc.CPUAccessFlags = 0; 1029 desc.MiscFlags = 0; 1030 1031 HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture); 1032 1033 // this can happen from windows TDR 1034 if (d3d11::isDeviceLostError(result)) 1035 { 1036 mRenderer->notifyDeviceLost(); 1037 gl::error(GL_OUT_OF_MEMORY); 1038 } 1039 else if (FAILED(result)) 1040 { 1041 ASSERT(result == E_OUTOFMEMORY); 1042 ERR("Creating image failed."); 1043 gl::error(GL_OUT_OF_MEMORY); 1044 } 1045 else 1046 { 1047 mTexture->GetDesc(&desc); 1048 mMipLevels = desc.MipLevels; 1049 mTextureWidth = desc.Width; 1050 mTextureHeight = desc.Height; 1051 mTextureDepth = desc.Depth; 1052 } 1053 } 1054 } 1055 1056 TextureStorage11_3D::~TextureStorage11_3D() 1057 { 1058 SafeRelease(mTexture); 1059 SafeRelease(mSwizzleTexture); 1060 1061 for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++) 1062 { 1063 SafeDelete(i->second); 1064 } 1065 mLevelLayerRenderTargets.clear(); 1066 1067 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 1068 { 1069 SafeDelete(mLevelRenderTargets[i]); 1070 SafeRelease(mSwizzleRenderTargets[i]); 1071 } 1072 } 1073 1074 TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage) 1075 { 1076 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage)); 1077 return static_cast<TextureStorage11_3D*>(storage); 1078 } 1079 1080 ID3D11Resource *TextureStorage11_3D::getResource() const 1081 { 1082 return mTexture; 1083 } 1084 1085 ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) 1086 { 1087 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 1088 srvDesc.Format = format; 1089 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; 1090 srvDesc.Texture3D.MostDetailedMip = baseLevel; 1091 srvDesc.Texture3D.MipLevels = mipLevels; 1092 1093 ID3D11ShaderResourceView *SRV = NULL; 1094 1095 ID3D11Device *device = mRenderer->getDevice(); 1096 HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); 1097 1098 if (result == E_OUTOFMEMORY) 1099 { 1100 gl::error(GL_OUT_OF_MEMORY); 1101 } 1102 ASSERT(SUCCEEDED(result)); 1103 1104 return SRV; 1105 } 1106 1107 RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel) 1108 { 1109 if (mipLevel >= 0 && mipLevel < getLevelCount()) 1110 { 1111 if (!mLevelRenderTargets[mipLevel]) 1112 { 1113 ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel); 1114 if (!srv) 1115 { 1116 return NULL; 1117 } 1118 1119 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) 1120 { 1121 ID3D11Device *device = mRenderer->getDevice(); 1122 1123 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 1124 rtvDesc.Format = mRenderTargetFormat; 1125 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; 1126 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; 1127 rtvDesc.Texture3D.FirstWSlice = 0; 1128 rtvDesc.Texture3D.WSize = -1; 1129 1130 ID3D11RenderTargetView *rtv; 1131 HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); 1132 1133 if (result == E_OUTOFMEMORY) 1134 { 1135 SafeRelease(srv); 1136 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 1137 } 1138 ASSERT(SUCCEEDED(result)); 1139 1140 mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel)); 1141 1142 // RenderTarget will take ownership of these resources 1143 SafeRelease(rtv); 1144 } 1145 else 1146 { 1147 UNREACHABLE(); 1148 } 1149 } 1150 1151 return mLevelRenderTargets[mipLevel]; 1152 } 1153 else 1154 { 1155 return NULL; 1156 } 1157 } 1158 1159 RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer) 1160 { 1161 if (mipLevel >= 0 && mipLevel < getLevelCount()) 1162 { 1163 LevelLayerKey key(mipLevel, layer); 1164 if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) 1165 { 1166 ID3D11Device *device = mRenderer->getDevice(); 1167 HRESULT result; 1168 1169 // TODO, what kind of SRV is expected here? 1170 ID3D11ShaderResourceView *srv = NULL; 1171 1172 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) 1173 { 1174 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 1175 rtvDesc.Format = mRenderTargetFormat; 1176 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; 1177 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; 1178 rtvDesc.Texture3D.FirstWSlice = layer; 1179 rtvDesc.Texture3D.WSize = 1; 1180 1181 ID3D11RenderTargetView *rtv; 1182 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); 1183 1184 if (result == E_OUTOFMEMORY) 1185 { 1186 SafeRelease(srv); 1187 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 1188 } 1189 ASSERT(SUCCEEDED(result)); 1190 1191 mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1); 1192 1193 // RenderTarget will take ownership of these resources 1194 SafeRelease(rtv); 1195 SafeRelease(srv); 1196 } 1197 else 1198 { 1199 UNREACHABLE(); 1200 } 1201 } 1202 1203 return mLevelLayerRenderTargets[key]; 1204 } 1205 else 1206 { 1207 return NULL; 1208 } 1209 } 1210 1211 void TextureStorage11_3D::generateMipmap(int level) 1212 { 1213 invalidateSwizzleCacheLevel(level); 1214 1215 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); 1216 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); 1217 1218 generateMipmapLayer(source, dest); 1219 } 1220 1221 ID3D11Resource *TextureStorage11_3D::getSwizzleTexture() 1222 { 1223 if (!mSwizzleTexture) 1224 { 1225 ID3D11Device *device = mRenderer->getDevice(); 1226 1227 D3D11_TEXTURE3D_DESC desc; 1228 desc.Width = mTextureWidth; 1229 desc.Height = mTextureHeight; 1230 desc.Depth = mTextureDepth; 1231 desc.MipLevels = mMipLevels; 1232 desc.Format = mSwizzleTextureFormat; 1233 desc.Usage = D3D11_USAGE_DEFAULT; 1234 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; 1235 desc.CPUAccessFlags = 0; 1236 desc.MiscFlags = 0; 1237 1238 HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture); 1239 1240 if (result == E_OUTOFMEMORY) 1241 { 1242 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture3D*>(NULL)); 1243 } 1244 ASSERT(SUCCEEDED(result)); 1245 } 1246 1247 return mSwizzleTexture; 1248 } 1249 1250 ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel) 1251 { 1252 if (mipLevel >= 0 && mipLevel < getLevelCount()) 1253 { 1254 if (!mSwizzleRenderTargets[mipLevel]) 1255 { 1256 ID3D11Resource *swizzleTexture = getSwizzleTexture(); 1257 if (!swizzleTexture) 1258 { 1259 return NULL; 1260 } 1261 1262 ID3D11Device *device = mRenderer->getDevice(); 1263 1264 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 1265 rtvDesc.Format = mSwizzleRenderTargetFormat; 1266 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; 1267 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; 1268 rtvDesc.Texture3D.FirstWSlice = 0; 1269 rtvDesc.Texture3D.WSize = -1; 1270 1271 HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); 1272 1273 if (result == E_OUTOFMEMORY) 1274 { 1275 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL)); 1276 } 1277 ASSERT(SUCCEEDED(result)); 1278 } 1279 1280 return mSwizzleRenderTargets[mipLevel]; 1281 } 1282 else 1283 { 1284 return NULL; 1285 } 1286 } 1287 1288 unsigned int TextureStorage11_3D::getTextureLevelDepth(int mipLevel) const 1289 { 1290 return std::max(mTextureDepth >> mipLevel, 1U); 1291 } 1292 1293 1294 TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, 1295 GLsizei width, GLsizei height, GLsizei depth, int levels) 1296 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), renderTarget)) 1297 { 1298 mTexture = NULL; 1299 mSwizzleTexture = NULL; 1300 1301 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) 1302 { 1303 mSwizzleRenderTargets[level] = NULL; 1304 } 1305 1306 GLuint clientVersion = mRenderer->getCurrentClientVersion(); 1307 1308 mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion); 1309 mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion); 1310 mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion); 1311 mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion); 1312 mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat, renderer); 1313 mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat, renderer); 1314 mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat, renderer); 1315 1316 // if the width, height or depth is not positive this should be treated as an incomplete texture 1317 // we handle that here by skipping the d3d texture creation 1318 if (width > 0 && height > 0 && depth > 0) 1319 { 1320 // adjust size if needed for compressed textures 1321 d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); 1322 1323 ID3D11Device *device = mRenderer->getDevice(); 1324 1325 D3D11_TEXTURE2D_DESC desc; 1326 desc.Width = width; 1327 desc.Height = height; 1328 desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); 1329 desc.ArraySize = depth; 1330 desc.Format = mTextureFormat; 1331 desc.SampleDesc.Count = 1; 1332 desc.SampleDesc.Quality = 0; 1333 desc.Usage = D3D11_USAGE_DEFAULT; 1334 desc.BindFlags = getBindFlags(); 1335 desc.CPUAccessFlags = 0; 1336 desc.MiscFlags = 0; 1337 1338 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); 1339 1340 // this can happen from windows TDR 1341 if (d3d11::isDeviceLostError(result)) 1342 { 1343 mRenderer->notifyDeviceLost(); 1344 gl::error(GL_OUT_OF_MEMORY); 1345 } 1346 else if (FAILED(result)) 1347 { 1348 ASSERT(result == E_OUTOFMEMORY); 1349 ERR("Creating image failed."); 1350 gl::error(GL_OUT_OF_MEMORY); 1351 } 1352 else 1353 { 1354 mTexture->GetDesc(&desc); 1355 mMipLevels = desc.MipLevels; 1356 mTextureWidth = desc.Width; 1357 mTextureHeight = desc.Height; 1358 mTextureDepth = desc.ArraySize; 1359 } 1360 } 1361 } 1362 1363 TextureStorage11_2DArray::~TextureStorage11_2DArray() 1364 { 1365 SafeRelease(mTexture); 1366 SafeRelease(mSwizzleTexture); 1367 1368 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) 1369 { 1370 SafeRelease(mSwizzleRenderTargets[level]); 1371 } 1372 1373 for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++) 1374 { 1375 SafeDelete(i->second); 1376 } 1377 mRenderTargets.clear(); 1378 } 1379 1380 TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage) 1381 { 1382 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage)); 1383 return static_cast<TextureStorage11_2DArray*>(storage); 1384 } 1385 1386 ID3D11Resource *TextureStorage11_2DArray::getResource() const 1387 { 1388 return mTexture; 1389 } 1390 1391 ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) 1392 { 1393 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 1394 srvDesc.Format = format; 1395 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; 1396 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; 1397 srvDesc.Texture2DArray.MipLevels = mipLevels; 1398 srvDesc.Texture2DArray.FirstArraySlice = 0; 1399 srvDesc.Texture2DArray.ArraySize = mTextureDepth; 1400 1401 ID3D11ShaderResourceView *SRV = NULL; 1402 1403 ID3D11Device *device = mRenderer->getDevice(); 1404 HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); 1405 1406 if (result == E_OUTOFMEMORY) 1407 { 1408 gl::error(GL_OUT_OF_MEMORY); 1409 } 1410 ASSERT(SUCCEEDED(result)); 1411 1412 return SRV; 1413 } 1414 1415 RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer) 1416 { 1417 if (mipLevel >= 0 && mipLevel < getLevelCount()) 1418 { 1419 LevelLayerKey key(mipLevel, layer); 1420 if (mRenderTargets.find(key) == mRenderTargets.end()) 1421 { 1422 ID3D11Device *device = mRenderer->getDevice(); 1423 HRESULT result; 1424 1425 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 1426 srvDesc.Format = mShaderResourceFormat; 1427 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; 1428 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel; 1429 srvDesc.Texture2DArray.MipLevels = 1; 1430 srvDesc.Texture2DArray.FirstArraySlice = layer; 1431 srvDesc.Texture2DArray.ArraySize = 1; 1432 1433 ID3D11ShaderResourceView *srv; 1434 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); 1435 1436 if (result == E_OUTOFMEMORY) 1437 { 1438 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 1439 } 1440 ASSERT(SUCCEEDED(result)); 1441 1442 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) 1443 { 1444 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 1445 rtvDesc.Format = mRenderTargetFormat; 1446 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; 1447 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; 1448 rtvDesc.Texture2DArray.FirstArraySlice = layer; 1449 rtvDesc.Texture2DArray.ArraySize = 1; 1450 1451 ID3D11RenderTargetView *rtv; 1452 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); 1453 1454 if (result == E_OUTOFMEMORY) 1455 { 1456 SafeRelease(srv); 1457 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 1458 } 1459 ASSERT(SUCCEEDED(result)); 1460 1461 mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1); 1462 1463 // RenderTarget will take ownership of these resources 1464 SafeRelease(rtv); 1465 SafeRelease(srv); 1466 } 1467 else 1468 { 1469 UNREACHABLE(); 1470 } 1471 } 1472 1473 return mRenderTargets[key]; 1474 } 1475 else 1476 { 1477 return NULL; 1478 } 1479 } 1480 1481 void TextureStorage11_2DArray::generateMipmap(int level) 1482 { 1483 invalidateSwizzleCacheLevel(level); 1484 for (unsigned int layer = 0; layer < mTextureDepth; layer++) 1485 { 1486 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level - 1, layer)); 1487 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level, layer)); 1488 1489 generateMipmapLayer(source, dest); 1490 } 1491 } 1492 1493 ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture() 1494 { 1495 if (!mSwizzleTexture) 1496 { 1497 ID3D11Device *device = mRenderer->getDevice(); 1498 1499 D3D11_TEXTURE2D_DESC desc; 1500 desc.Width = mTextureWidth; 1501 desc.Height = mTextureHeight; 1502 desc.MipLevels = mMipLevels; 1503 desc.ArraySize = mTextureDepth; 1504 desc.Format = mSwizzleTextureFormat; 1505 desc.SampleDesc.Count = 1; 1506 desc.SampleDesc.Quality = 0; 1507 desc.Usage = D3D11_USAGE_DEFAULT; 1508 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; 1509 desc.CPUAccessFlags = 0; 1510 desc.MiscFlags = 0; 1511 1512 HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); 1513 1514 if (result == E_OUTOFMEMORY) 1515 { 1516 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL)); 1517 } 1518 ASSERT(SUCCEEDED(result)); 1519 } 1520 1521 return mSwizzleTexture; 1522 } 1523 1524 ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel) 1525 { 1526 if (mipLevel >= 0 && mipLevel < getLevelCount()) 1527 { 1528 if (!mSwizzleRenderTargets[mipLevel]) 1529 { 1530 ID3D11Resource *swizzleTexture = getSwizzleTexture(); 1531 if (!swizzleTexture) 1532 { 1533 return NULL; 1534 } 1535 1536 ID3D11Device *device = mRenderer->getDevice(); 1537 1538 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 1539 rtvDesc.Format = mSwizzleRenderTargetFormat; 1540 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; 1541 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; 1542 rtvDesc.Texture2DArray.FirstArraySlice = 0; 1543 rtvDesc.Texture2DArray.ArraySize = mTextureDepth; 1544 1545 HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); 1546 1547 if (result == E_OUTOFMEMORY) 1548 { 1549 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL)); 1550 } 1551 ASSERT(SUCCEEDED(result)); 1552 } 1553 1554 return mSwizzleRenderTargets[mipLevel]; 1555 } 1556 else 1557 { 1558 return NULL; 1559 } 1560 } 1561 1562 unsigned int TextureStorage11_2DArray::getTextureLevelDepth(int mipLevel) const 1563 { 1564 return mTextureDepth; 1565 } 1566 1567 } 1568