Image11.cpp (27636B)
1 // 2 // Copyright 2012 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Image11.h: Implements the rx::Image11 class, which acts as the interface to 8 // the actual underlying resources of a Texture 9 10 #include "libANGLE/renderer/d3d/d3d11/Image11.h" 11 12 #include "common/utilities.h" 13 #include "libANGLE/Context.h" 14 #include "libANGLE/Framebuffer.h" 15 #include "libANGLE/FramebufferAttachment.h" 16 #include "libANGLE/formatutils.h" 17 #include "libANGLE/renderer/d3d/d3d11/Context11.h" 18 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" 19 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" 20 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" 21 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" 22 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" 23 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" 24 25 namespace rx 26 { 27 28 Image11::Image11(Renderer11 *renderer) 29 : mRenderer(renderer), 30 mDXGIFormat(DXGI_FORMAT_UNKNOWN), 31 mStagingTexture(), 32 mStagingSubresource(0), 33 mRecoverFromStorage(false), 34 mAssociatedStorage(nullptr), 35 mAssociatedImageIndex(), 36 mRecoveredFromStorageCount(0) 37 {} 38 39 Image11::~Image11() 40 { 41 disassociateStorage(); 42 releaseStagingTexture(); 43 } 44 45 // static 46 angle::Result Image11::GenerateMipmap(const gl::Context *context, 47 Image11 *dest, 48 Image11 *src, 49 const Renderer11DeviceCaps &rendererCaps) 50 { 51 ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); 52 ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); 53 ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); 54 55 D3D11_MAPPED_SUBRESOURCE destMapped; 56 ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped)); 57 d3d11::ScopedUnmapper<Image11> destRAII(dest); 58 59 D3D11_MAPPED_SUBRESOURCE srcMapped; 60 ANGLE_TRY(src->map(context, D3D11_MAP_READ, &srcMapped)); 61 d3d11::ScopedUnmapper<Image11> srcRAII(src); 62 63 const uint8_t *sourceData = static_cast<const uint8_t *>(srcMapped.pData); 64 uint8_t *destData = static_cast<uint8_t *>(destMapped.pData); 65 66 auto mipGenerationFunction = 67 d3d11::Format::Get(src->getInternalFormat(), rendererCaps).format().mipGenerationFunction; 68 mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), sourceData, 69 srcMapped.RowPitch, srcMapped.DepthPitch, destData, destMapped.RowPitch, 70 destMapped.DepthPitch); 71 72 dest->markDirty(); 73 74 return angle::Result::Continue; 75 } 76 77 // static 78 angle::Result Image11::CopyImage(const gl::Context *context, 79 Image11 *dest, 80 Image11 *source, 81 const gl::Box &sourceBox, 82 const gl::Offset &destOffset, 83 bool unpackFlipY, 84 bool unpackPremultiplyAlpha, 85 bool unpackUnmultiplyAlpha, 86 const Renderer11DeviceCaps &rendererCaps) 87 { 88 D3D11_MAPPED_SUBRESOURCE destMapped; 89 ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped)); 90 d3d11::ScopedUnmapper<Image11> destRAII(dest); 91 92 D3D11_MAPPED_SUBRESOURCE srcMapped; 93 ANGLE_TRY(source->map(context, D3D11_MAP_READ, &srcMapped)); 94 d3d11::ScopedUnmapper<Image11> sourceRAII(source); 95 96 const auto &sourceFormat = 97 d3d11::Format::Get(source->getInternalFormat(), rendererCaps).format(); 98 GLuint sourcePixelBytes = 99 gl::GetSizedInternalFormatInfo(sourceFormat.fboImplementationInternalFormat).pixelBytes; 100 101 GLenum destUnsizedFormat = gl::GetUnsizedFormat(dest->getInternalFormat()); 102 const auto &destFormat = d3d11::Format::Get(dest->getInternalFormat(), rendererCaps).format(); 103 const auto &destFormatInfo = 104 gl::GetSizedInternalFormatInfo(destFormat.fboImplementationInternalFormat); 105 GLuint destPixelBytes = destFormatInfo.pixelBytes; 106 107 const uint8_t *sourceData = static_cast<const uint8_t *>(srcMapped.pData) + 108 sourceBox.x * sourcePixelBytes + sourceBox.y * srcMapped.RowPitch + 109 sourceBox.z * srcMapped.DepthPitch; 110 uint8_t *destData = static_cast<uint8_t *>(destMapped.pData) + destOffset.x * destPixelBytes + 111 destOffset.y * destMapped.RowPitch + destOffset.z * destMapped.DepthPitch; 112 113 CopyImageCHROMIUM(sourceData, srcMapped.RowPitch, sourcePixelBytes, srcMapped.DepthPitch, 114 sourceFormat.pixelReadFunction, destData, destMapped.RowPitch, destPixelBytes, 115 destMapped.DepthPitch, destFormat.pixelWriteFunction, destUnsizedFormat, 116 destFormatInfo.componentType, sourceBox.width, sourceBox.height, 117 sourceBox.depth, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha); 118 119 dest->markDirty(); 120 121 return angle::Result::Continue; 122 } 123 124 bool Image11::isDirty() const 125 { 126 // If mDirty is true AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be 127 // recovered from TextureStorage AND the texture doesn't require init data (i.e. a blank new 128 // texture will suffice) AND robust resource initialization is not enabled then isDirty should 129 // still return false. 130 if (mDirty && !mStagingTexture.valid() && !mRecoverFromStorage) 131 { 132 const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps(); 133 const auto &formatInfo = d3d11::Format::Get(mInternalFormat, deviceCaps); 134 if (formatInfo.dataInitializerFunction == nullptr) 135 { 136 return false; 137 } 138 } 139 140 return mDirty; 141 } 142 143 angle::Result Image11::copyToStorage(const gl::Context *context, 144 TextureStorage *storage, 145 const gl::ImageIndex &index, 146 const gl::Box ®ion) 147 { 148 TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage); 149 150 // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage 151 // multiple times, then we should just keep the staging texture around to prevent the copying 152 // from impacting perf. We allow the Image11 to copy its data to/from TextureStorage once. This 153 // accounts for an app making a late call to glGenerateMipmap. 154 bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2); 155 156 if (attemptToReleaseStagingTexture) 157 { 158 // If another image is relying on this Storage for its data, then we must let it recover its 159 // data before we overwrite it. 160 ANGLE_TRY(storage11->releaseAssociatedImage(context, index, this)); 161 } 162 163 const TextureHelper11 *stagingTexture = nullptr; 164 unsigned int stagingSubresourceIndex = 0; 165 ANGLE_TRY(getStagingTexture(context, &stagingTexture, &stagingSubresourceIndex)); 166 ANGLE_TRY(storage11->updateSubresourceLevel(context, *stagingTexture, stagingSubresourceIndex, 167 index, region)); 168 169 // Once the image data has been copied into the Storage, we can release it locally. 170 if (attemptToReleaseStagingTexture) 171 { 172 storage11->associateImage(this, index); 173 releaseStagingTexture(); 174 mRecoverFromStorage = true; 175 mAssociatedStorage = storage11; 176 mAssociatedImageIndex = index; 177 } 178 179 return angle::Result::Continue; 180 } 181 182 void Image11::verifyAssociatedStorageValid(TextureStorage11 *textureStorageEXT) const 183 { 184 ASSERT(mAssociatedStorage == textureStorageEXT); 185 } 186 187 angle::Result Image11::recoverFromAssociatedStorage(const gl::Context *context) 188 { 189 if (mRecoverFromStorage) 190 { 191 ANGLE_TRY(createStagingTexture(context)); 192 193 mAssociatedStorage->verifyAssociatedImageValid(mAssociatedImageIndex, this); 194 195 // CopySubResource from the Storage to the Staging texture 196 gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); 197 ANGLE_TRY(mAssociatedStorage->copySubresourceLevel( 198 context, mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region)); 199 mRecoveredFromStorageCount += 1; 200 201 // Reset all the recovery parameters, even if the texture storage association is broken. 202 disassociateStorage(); 203 204 markDirty(); 205 } 206 207 return angle::Result::Continue; 208 } 209 210 void Image11::disassociateStorage() 211 { 212 if (mRecoverFromStorage) 213 { 214 // Make the texturestorage release the Image11 too 215 mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this); 216 217 mRecoverFromStorage = false; 218 mAssociatedStorage = nullptr; 219 mAssociatedImageIndex = gl::ImageIndex(); 220 } 221 } 222 223 bool Image11::redefine(gl::TextureType type, 224 GLenum internalformat, 225 const gl::Extents &size, 226 bool forceRelease) 227 { 228 if (mWidth != size.width || mHeight != size.height || mDepth != size.depth || 229 mInternalFormat != internalformat || forceRelease) 230 { 231 // End the association with the TextureStorage, since that data will be out of date. 232 // Also reset mRecoveredFromStorageCount since this Image is getting completely redefined. 233 disassociateStorage(); 234 mRecoveredFromStorageCount = 0; 235 236 mWidth = size.width; 237 mHeight = size.height; 238 mDepth = size.depth; 239 mInternalFormat = internalformat; 240 mType = type; 241 242 // compute the d3d format that will be used 243 const d3d11::Format &formatInfo = 244 d3d11::Format::Get(internalformat, mRenderer->getRenderer11DeviceCaps()); 245 mDXGIFormat = formatInfo.texFormat; 246 mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); 247 248 releaseStagingTexture(); 249 mDirty = (formatInfo.dataInitializerFunction != nullptr); 250 251 return true; 252 } 253 254 return false; 255 } 256 257 DXGI_FORMAT Image11::getDXGIFormat() const 258 { 259 // this should only happen if the image hasn't been redefined first 260 // which would be a bug by the caller 261 ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); 262 263 return mDXGIFormat; 264 } 265 266 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as 267 // format/type at input 268 // into the target pixel rectangle. 269 angle::Result Image11::loadData(const gl::Context *context, 270 const gl::Box &area, 271 const gl::PixelUnpackState &unpack, 272 GLenum type, 273 const void *input, 274 bool applySkipImages) 275 { 276 Context11 *context11 = GetImplAs<Context11>(context); 277 278 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); 279 GLuint inputRowPitch = 0; 280 ANGLE_CHECK_GL_MATH(context11, formatInfo.computeRowPitch(type, area.width, unpack.alignment, 281 unpack.rowLength, &inputRowPitch)); 282 GLuint inputDepthPitch = 0; 283 ANGLE_CHECK_GL_MATH(context11, formatInfo.computeDepthPitch(area.height, unpack.imageHeight, 284 inputRowPitch, &inputDepthPitch)); 285 GLuint inputSkipBytes = 0; 286 ANGLE_CHECK_GL_MATH(context11, 287 formatInfo.computeSkipBytes(type, inputRowPitch, inputDepthPitch, unpack, 288 applySkipImages, &inputSkipBytes)); 289 290 const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); 291 GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; 292 293 const d3d11::Format &d3dFormatInfo = 294 d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); 295 LoadImageFunction loadFunction = d3dFormatInfo.getLoadFunctions()(type).loadFunction; 296 297 D3D11_MAPPED_SUBRESOURCE mappedImage; 298 ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage)); 299 300 uint8_t *offsetMappedData = (static_cast<uint8_t *>(mappedImage.pData) + 301 (area.y * mappedImage.RowPitch + area.x * outputPixelSize + 302 area.z * mappedImage.DepthPitch)); 303 loadFunction(area.width, area.height, area.depth, 304 static_cast<const uint8_t *>(input) + inputSkipBytes, inputRowPitch, 305 inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); 306 307 unmap(); 308 309 return angle::Result::Continue; 310 } 311 312 angle::Result Image11::loadCompressedData(const gl::Context *context, 313 const gl::Box &area, 314 const void *input) 315 { 316 Context11 *context11 = GetImplAs<Context11>(context); 317 318 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); 319 GLuint inputRowPitch = 0; 320 ANGLE_CHECK_GL_MATH( 321 context11, formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0, &inputRowPitch)); 322 GLuint inputDepthPitch = 0; 323 ANGLE_CHECK_GL_MATH( 324 context11, formatInfo.computeDepthPitch(area.height, 0, inputRowPitch, &inputDepthPitch)); 325 326 const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); 327 GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; 328 GLuint outputBlockWidth = dxgiFormatInfo.blockWidth; 329 GLuint outputBlockHeight = dxgiFormatInfo.blockHeight; 330 331 ASSERT(area.x % outputBlockWidth == 0); 332 ASSERT(area.y % outputBlockHeight == 0); 333 334 const d3d11::Format &d3dFormatInfo = 335 d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); 336 LoadImageFunction loadFunction = 337 d3dFormatInfo.getLoadFunctions()(GL_UNSIGNED_BYTE).loadFunction; 338 339 D3D11_MAPPED_SUBRESOURCE mappedImage; 340 ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage)); 341 342 uint8_t *offsetMappedData = 343 static_cast<uint8_t *>(mappedImage.pData) + 344 ((area.y / outputBlockHeight) * mappedImage.RowPitch + 345 (area.x / outputBlockWidth) * outputPixelSize + area.z * mappedImage.DepthPitch); 346 347 loadFunction(area.width, area.height, area.depth, static_cast<const uint8_t *>(input), 348 inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch, 349 mappedImage.DepthPitch); 350 351 unmap(); 352 353 return angle::Result::Continue; 354 } 355 356 angle::Result Image11::copyFromTexStorage(const gl::Context *context, 357 const gl::ImageIndex &imageIndex, 358 TextureStorage *source) 359 { 360 TextureStorage11 *storage11 = GetAs<TextureStorage11>(source); 361 362 const TextureHelper11 *textureHelper = nullptr; 363 ANGLE_TRY(storage11->getResource(context, &textureHelper)); 364 365 UINT subresourceIndex = 0; 366 ANGLE_TRY(storage11->getSubresourceIndex(context, imageIndex, &subresourceIndex)); 367 368 gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth); 369 return copyWithoutConversion(context, gl::Offset(), sourceBox, *textureHelper, 370 subresourceIndex); 371 } 372 373 angle::Result Image11::copyFromFramebuffer(const gl::Context *context, 374 const gl::Offset &destOffset, 375 const gl::Rectangle &sourceArea, 376 const gl::Framebuffer *sourceFBO) 377 { 378 const gl::FramebufferAttachment *srcAttachment = sourceFBO->getReadColorAttachment(); 379 ASSERT(srcAttachment); 380 381 GLenum sourceInternalFormat = srcAttachment->getFormat().info->sizedInternalFormat; 382 const auto &d3d11Format = 383 d3d11::Format::Get(sourceInternalFormat, mRenderer->getRenderer11DeviceCaps()); 384 385 if (d3d11Format.texFormat == mDXGIFormat && sourceInternalFormat == mInternalFormat) 386 { 387 RenderTarget11 *rt11 = nullptr; 388 ANGLE_TRY(srcAttachment->getRenderTarget(context, 0, &rt11)); 389 ASSERT(rt11->getTexture().get()); 390 391 TextureHelper11 textureHelper = rt11->getTexture(); 392 unsigned int sourceSubResource = rt11->getSubresourceIndex(); 393 394 gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1); 395 return copyWithoutConversion(context, destOffset, sourceBox, textureHelper, 396 sourceSubResource); 397 } 398 399 // This format requires conversion, so we must copy the texture to staging and manually convert 400 // via readPixels 401 D3D11_MAPPED_SUBRESOURCE mappedImage; 402 ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage)); 403 404 // determine the offset coordinate into the destination buffer 405 const auto &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); 406 GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x; 407 408 uint8_t *dataOffset = static_cast<uint8_t *>(mappedImage.pData) + 409 mappedImage.RowPitch * destOffset.y + rowOffset + 410 destOffset.z * mappedImage.DepthPitch; 411 412 const gl::InternalFormat &destFormatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); 413 const auto &destD3D11Format = 414 d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); 415 416 auto loadFunction = destD3D11Format.getLoadFunctions()(destFormatInfo.type); 417 angle::Result result = angle::Result::Continue; 418 if (loadFunction.requiresConversion) 419 { 420 size_t bufferSize = destFormatInfo.pixelBytes * sourceArea.width * sourceArea.height; 421 angle::MemoryBuffer *memoryBuffer = nullptr; 422 result = mRenderer->getScratchMemoryBuffer(GetImplAs<Context11>(context), bufferSize, 423 &memoryBuffer); 424 425 if (result == angle::Result::Continue) 426 { 427 GLuint memoryBufferRowPitch = destFormatInfo.pixelBytes * sourceArea.width; 428 429 result = mRenderer->readFromAttachment( 430 context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type, 431 memoryBufferRowPitch, gl::PixelPackState(), memoryBuffer->data()); 432 433 loadFunction.loadFunction(sourceArea.width, sourceArea.height, 1, memoryBuffer->data(), 434 memoryBufferRowPitch, 0, dataOffset, mappedImage.RowPitch, 435 mappedImage.DepthPitch); 436 } 437 } 438 else 439 { 440 result = mRenderer->readFromAttachment( 441 context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type, 442 mappedImage.RowPitch, gl::PixelPackState(), dataOffset); 443 } 444 445 unmap(); 446 mDirty = true; 447 448 return result; 449 } 450 451 angle::Result Image11::copyWithoutConversion(const gl::Context *context, 452 const gl::Offset &destOffset, 453 const gl::Box &sourceArea, 454 const TextureHelper11 &textureHelper, 455 UINT sourceSubResource) 456 { 457 // No conversion needed-- use copyback fastpath 458 const TextureHelper11 *stagingTexture = nullptr; 459 unsigned int stagingSubresourceIndex = 0; 460 ANGLE_TRY(getStagingTexture(context, &stagingTexture, &stagingSubresourceIndex)); 461 462 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 463 464 const gl::Extents &extents = textureHelper.getExtents(); 465 466 D3D11_BOX srcBox; 467 srcBox.left = sourceArea.x; 468 srcBox.right = sourceArea.x + sourceArea.width; 469 srcBox.top = sourceArea.y; 470 srcBox.bottom = sourceArea.y + sourceArea.height; 471 srcBox.front = sourceArea.z; 472 srcBox.back = sourceArea.z + sourceArea.depth; 473 474 if (textureHelper.is2D() && textureHelper.getSampleCount() > 1) 475 { 476 D3D11_TEXTURE2D_DESC resolveDesc; 477 resolveDesc.Width = extents.width; 478 resolveDesc.Height = extents.height; 479 resolveDesc.MipLevels = 1; 480 resolveDesc.ArraySize = 1; 481 resolveDesc.Format = textureHelper.getFormat(); 482 resolveDesc.SampleDesc.Count = 1; 483 resolveDesc.SampleDesc.Quality = 0; 484 resolveDesc.Usage = D3D11_USAGE_DEFAULT; 485 resolveDesc.BindFlags = 0; 486 resolveDesc.CPUAccessFlags = 0; 487 resolveDesc.MiscFlags = 0; 488 489 d3d11::Texture2D resolveTex; 490 ANGLE_TRY( 491 mRenderer->allocateResource(GetImplAs<Context11>(context), resolveDesc, &resolveTex)); 492 493 deviceContext->ResolveSubresource(resolveTex.get(), 0, textureHelper.get(), 494 sourceSubResource, textureHelper.getFormat()); 495 496 deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex, 497 destOffset.x, destOffset.y, destOffset.z, 498 resolveTex.get(), 0, &srcBox); 499 } 500 else 501 { 502 deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex, 503 destOffset.x, destOffset.y, destOffset.z, 504 textureHelper.get(), sourceSubResource, &srcBox); 505 } 506 507 mDirty = true; 508 return angle::Result::Continue; 509 } 510 511 angle::Result Image11::getStagingTexture(const gl::Context *context, 512 const TextureHelper11 **outStagingTexture, 513 unsigned int *outSubresourceIndex) 514 { 515 ANGLE_TRY(createStagingTexture(context)); 516 517 *outStagingTexture = &mStagingTexture; 518 *outSubresourceIndex = mStagingSubresource; 519 return angle::Result::Continue; 520 } 521 522 void Image11::releaseStagingTexture() 523 { 524 mStagingTexture.reset(); 525 mStagingTextureSubresourceVerifier.reset(); 526 } 527 528 angle::Result Image11::createStagingTexture(const gl::Context *context) 529 { 530 if (mStagingTexture.valid()) 531 { 532 return angle::Result::Continue; 533 } 534 535 ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0); 536 537 const DXGI_FORMAT dxgiFormat = getDXGIFormat(); 538 const auto &formatInfo = 539 d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); 540 541 int lodOffset = 1; 542 GLsizei width = mWidth; 543 GLsizei height = mHeight; 544 545 // adjust size if needed for compressed textures 546 d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset); 547 548 Context11 *context11 = GetImplAs<Context11>(context); 549 550 switch (mType) 551 { 552 case gl::TextureType::_3D: 553 { 554 D3D11_TEXTURE3D_DESC desc; 555 desc.Width = width; 556 desc.Height = height; 557 desc.Depth = mDepth; 558 desc.MipLevels = lodOffset + 1; 559 desc.Format = dxgiFormat; 560 desc.Usage = D3D11_USAGE_STAGING; 561 desc.BindFlags = 0; 562 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 563 desc.MiscFlags = 0; 564 565 if (formatInfo.dataInitializerFunction != nullptr) 566 { 567 gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> initialData; 568 ANGLE_TRY(d3d11::GenerateInitialTextureData( 569 context, mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, 570 mDepth, lodOffset + 1, &initialData)); 571 572 ANGLE_TRY(mRenderer->allocateTexture(context11, desc, formatInfo, 573 initialData.data(), &mStagingTexture)); 574 } 575 else 576 { 577 ANGLE_TRY( 578 mRenderer->allocateTexture(context11, desc, formatInfo, &mStagingTexture)); 579 } 580 581 mStagingTexture.setInternalName("Image11::StagingTexture3D"); 582 mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); 583 mStagingTextureSubresourceVerifier.setDesc(desc); 584 } 585 break; 586 587 case gl::TextureType::_2D: 588 case gl::TextureType::_2DArray: 589 case gl::TextureType::CubeMap: 590 { 591 D3D11_TEXTURE2D_DESC desc; 592 desc.Width = width; 593 desc.Height = height; 594 desc.MipLevels = lodOffset + 1; 595 desc.ArraySize = 1; 596 desc.Format = dxgiFormat; 597 desc.SampleDesc.Count = 1; 598 desc.SampleDesc.Quality = 0; 599 desc.Usage = D3D11_USAGE_STAGING; 600 desc.BindFlags = 0; 601 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 602 desc.MiscFlags = 0; 603 604 if (formatInfo.dataInitializerFunction != nullptr) 605 { 606 gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> initialData; 607 ANGLE_TRY(d3d11::GenerateInitialTextureData( 608 context, mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, 609 1, lodOffset + 1, &initialData)); 610 611 ANGLE_TRY(mRenderer->allocateTexture(context11, desc, formatInfo, 612 initialData.data(), &mStagingTexture)); 613 } 614 else 615 { 616 ANGLE_TRY( 617 mRenderer->allocateTexture(context11, desc, formatInfo, &mStagingTexture)); 618 } 619 620 mStagingTexture.setInternalName("Image11::StagingTexture2D"); 621 mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); 622 mStagingTextureSubresourceVerifier.setDesc(desc); 623 } 624 break; 625 626 default: 627 UNREACHABLE(); 628 } 629 630 mDirty = false; 631 return angle::Result::Continue; 632 } 633 634 angle::Result Image11::map(const gl::Context *context, 635 D3D11_MAP mapType, 636 D3D11_MAPPED_SUBRESOURCE *map) 637 { 638 // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. 639 ANGLE_TRY(recoverFromAssociatedStorage(context)); 640 641 const TextureHelper11 *stagingTexture = nullptr; 642 unsigned int subresourceIndex = 0; 643 ANGLE_TRY(getStagingTexture(context, &stagingTexture, &subresourceIndex)); 644 645 ASSERT(stagingTexture && stagingTexture->valid()); 646 647 ANGLE_TRY( 648 mRenderer->mapResource(context, stagingTexture->get(), subresourceIndex, mapType, 0, map)); 649 650 if (!mStagingTextureSubresourceVerifier.wrap(mapType, map)) 651 { 652 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 653 deviceContext->Unmap(mStagingTexture.get(), mStagingSubresource); 654 Context11 *context11 = GetImplAs<Context11>(context); 655 context11->handleError(GL_OUT_OF_MEMORY, 656 "Failed to allocate staging texture mapping verifier buffer.", 657 __FILE__, ANGLE_FUNCTION, __LINE__); 658 return angle::Result::Stop; 659 } 660 661 mDirty = true; 662 663 return angle::Result::Continue; 664 } 665 666 void Image11::unmap() 667 { 668 if (mStagingTexture.valid()) 669 { 670 mStagingTextureSubresourceVerifier.unwrap(); 671 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 672 deviceContext->Unmap(mStagingTexture.get(), mStagingSubresource); 673 } 674 } 675 676 } // namespace rx