1 //
2 // Copyright (c) 2012-2014 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 // TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
8 // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11
9 // texture.
10
11 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
12
13 #include <tuple>
14
15 #include "common/MemoryBuffer.h"
16 #include "common/utilities.h"
17 #include "libANGLE/formatutils.h"
18 #include "libANGLE/ImageIndex.h"
19 #include "libANGLE/renderer/d3d/d3d11/Blit11.h"
20 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
21 #include "libANGLE/renderer/d3d/d3d11/Image11.h"
22 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
23 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
24 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
25 #include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
26 #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
27 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
28 #include "libANGLE/renderer/d3d/EGLImageD3D.h"
29 #include "libANGLE/renderer/d3d/TextureD3D.h"
30
31 namespace rx
32 {
33
34 namespace
35 {
36
InvalidateRenderTarget(const gl::Context * context,RenderTarget11 * renderTarget)37 void InvalidateRenderTarget(const gl::Context *context, RenderTarget11 *renderTarget)
38 {
39 if (renderTarget)
40 {
41 renderTarget->signalDirty(context);
42 }
43 }
44
GetRenderTarget(std::unique_ptr<RenderTarget11> * pointer)45 RenderTarget11 *GetRenderTarget(std::unique_ptr<RenderTarget11> *pointer)
46 {
47 return pointer->get();
48 }
49
50 template <typename KeyT>
GetRenderTarget(std::pair<KeyT,std::unique_ptr<RenderTarget11>> * pair)51 RenderTarget11 *GetRenderTarget(std::pair<KeyT, std::unique_ptr<RenderTarget11>> *pair)
52 {
53 return pair->second.get();
54 }
55
56 template <typename T>
InvalidateRenderTargetContainer(const gl::Context * context,T * renderTargetContainer)57 void InvalidateRenderTargetContainer(const gl::Context *context, T *renderTargetContainer)
58 {
59 for (auto &rt : *renderTargetContainer)
60 {
61 InvalidateRenderTarget(context, GetRenderTarget(&rt));
62 }
63 }
64
65 } // anonymous namespace
66
SRVKey(int baseLevel,int mipLevels,bool swizzle,bool dropStencil)67 TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil)
68 : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil)
69 {
70 }
71
operator <(const SRVKey & rhs) const72 bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const
73 {
74 return std::tie(baseLevel, mipLevels, swizzle, dropStencil) <
75 std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil);
76 }
77
TextureStorage11(Renderer11 * renderer,UINT bindFlags,UINT miscFlags,GLenum internalFormat)78 TextureStorage11::TextureStorage11(Renderer11 *renderer,
79 UINT bindFlags,
80 UINT miscFlags,
81 GLenum internalFormat)
82 : mRenderer(renderer),
83 mTopLevel(0),
84 mMipLevels(0),
85 mFormatInfo(d3d11::Format::Get(internalFormat, mRenderer->getRenderer11DeviceCaps())),
86 mTextureWidth(0),
87 mTextureHeight(0),
88 mTextureDepth(0),
89 mDropStencilTexture(),
90 mBindFlags(bindFlags),
91 mMiscFlags(miscFlags)
92 {
93 }
94
~TextureStorage11()95 TextureStorage11::~TextureStorage11()
96 {
97 mSrvCache.clear();
98 }
99
GetTextureBindFlags(GLenum internalFormat,const Renderer11DeviceCaps & renderer11DeviceCaps,bool renderTarget)100 DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat,
101 const Renderer11DeviceCaps &renderer11DeviceCaps,
102 bool renderTarget)
103 {
104 UINT bindFlags = 0;
105
106 const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
107 if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
108 {
109 bindFlags |= D3D11_BIND_SHADER_RESOURCE;
110 }
111 if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
112 {
113 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
114 }
115 if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget)
116 {
117 bindFlags |= D3D11_BIND_RENDER_TARGET;
118 }
119
120 return bindFlags;
121 }
122
GetTextureMiscFlags(GLenum internalFormat,const Renderer11DeviceCaps & renderer11DeviceCaps,bool renderTarget,int levels)123 DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat,
124 const Renderer11DeviceCaps &renderer11DeviceCaps,
125 bool renderTarget,
126 int levels)
127 {
128 UINT miscFlags = 0;
129
130 const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
131 if (renderTarget && levels > 1)
132 {
133 if (d3d11::SupportsMipGen(formatInfo.texFormat, renderer11DeviceCaps.featureLevel))
134 {
135 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
136 }
137 }
138
139 return miscFlags;
140 }
141
getBindFlags() const142 UINT TextureStorage11::getBindFlags() const
143 {
144 return mBindFlags;
145 }
146
getMiscFlags() const147 UINT TextureStorage11::getMiscFlags() const
148 {
149 return mMiscFlags;
150 }
151
getTopLevel() const152 int TextureStorage11::getTopLevel() const
153 {
154 // Applying top level is meant to be encapsulated inside TextureStorage11.
155 UNREACHABLE();
156 return mTopLevel;
157 }
158
isRenderTarget() const159 bool TextureStorage11::isRenderTarget() const
160 {
161 return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
162 }
163
isManaged() const164 bool TextureStorage11::isManaged() const
165 {
166 return false;
167 }
168
supportsNativeMipmapFunction() const169 bool TextureStorage11::supportsNativeMipmapFunction() const
170 {
171 return (mMiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) != 0;
172 }
173
getLevelCount() const174 int TextureStorage11::getLevelCount() const
175 {
176 return mMipLevels - mTopLevel;
177 }
178
getLevelWidth(int mipLevel) const179 int TextureStorage11::getLevelWidth(int mipLevel) const
180 {
181 return std::max(static_cast<int>(mTextureWidth) >> mipLevel, 1);
182 }
183
getLevelHeight(int mipLevel) const184 int TextureStorage11::getLevelHeight(int mipLevel) const
185 {
186 return std::max(static_cast<int>(mTextureHeight) >> mipLevel, 1);
187 }
188
getLevelDepth(int mipLevel) const189 int TextureStorage11::getLevelDepth(int mipLevel) const
190 {
191 return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1);
192 }
193
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)194 gl::Error TextureStorage11::getMippedResource(const gl::Context *context,
195 const TextureHelper11 **outResource)
196 {
197 return getResource(context, outResource);
198 }
199
getSubresourceIndex(const gl::ImageIndex & index) const200 UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const
201 {
202 UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
203 UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
204 UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
205 ASSERT(subresource != std::numeric_limits<UINT>::max());
206 return subresource;
207 }
208
getSRV(const gl::Context * context,const gl::TextureState & textureState,const d3d11::SharedSRV ** outSRV)209 gl::Error TextureStorage11::getSRV(const gl::Context *context,
210 const gl::TextureState &textureState,
211 const d3d11::SharedSRV **outSRV)
212 {
213 // Make sure to add the level offset for our tiny compressed texture workaround
214 const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel();
215 bool swizzleRequired = textureState.swizzleRequired();
216 bool mipmapping = gl::IsMipmapFiltered(textureState.getSamplerState());
217 unsigned int mipLevels =
218 mipmapping ? (textureState.getEffectiveMaxLevel() - effectiveBaseLevel + 1) : 1;
219
220 // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
221 // which corresponds to GL level 0)
222 mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - effectiveBaseLevel);
223
224 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
225 {
226 ASSERT(!swizzleRequired);
227 ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
228 }
229
230 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
231 {
232 // We must ensure that the level zero texture is in sync with mipped texture.
233 ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1));
234 }
235
236 if (swizzleRequired)
237 {
238 verifySwizzleExists(textureState.getSwizzleState());
239 }
240
241 // We drop the stencil when sampling from the SRV if three conditions hold:
242 // 1. the drop stencil workaround is enabled.
243 bool workaround = mRenderer->getWorkarounds().emulateTinyStencilTextures;
244 // 2. this is a stencil texture.
245 bool hasStencil = (mFormatInfo.format().stencilBits > 0);
246 // 3. the texture has a 1x1 or 2x2 mip.
247 int effectiveTopLevel = effectiveBaseLevel + mipLevels - 1;
248 bool hasSmallMips =
249 (getLevelWidth(effectiveTopLevel) <= 2 || getLevelHeight(effectiveTopLevel) <= 2);
250
251 bool useDropStencil = (workaround && hasStencil && hasSmallMips);
252 SRVKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil);
253 if (useDropStencil)
254 {
255 // Ensure drop texture gets created.
256 DropStencil result = DropStencil::CREATED;
257 ANGLE_TRY_RESULT(ensureDropStencilTexture(context), result);
258
259 // Clear the SRV cache if necessary.
260 // TODO(jmadill): Re-use find query result.
261 auto srvEntry = mSrvCache.find(key);
262 if (result == DropStencil::CREATED && srvEntry != mSrvCache.end())
263 {
264 mSrvCache.erase(key);
265 }
266 }
267
268 ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV));
269
270 return gl::NoError();
271 }
272
getCachedOrCreateSRV(const gl::Context * context,const SRVKey & key,const d3d11::SharedSRV ** outSRV)273 gl::Error TextureStorage11::getCachedOrCreateSRV(const gl::Context *context,
274 const SRVKey &key,
275 const d3d11::SharedSRV **outSRV)
276 {
277 auto iter = mSrvCache.find(key);
278 if (iter != mSrvCache.end())
279 {
280 *outSRV = &iter->second;
281 return gl::NoError();
282 }
283
284 const TextureHelper11 *texture = nullptr;
285 DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
286
287 if (key.swizzle)
288 {
289 const auto &swizzleFormat =
290 mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
291 ASSERT(!key.dropStencil || swizzleFormat.format().stencilBits == 0);
292 ANGLE_TRY(getSwizzleTexture(&texture));
293 format = swizzleFormat.srvFormat;
294 }
295 else if (key.dropStencil)
296 {
297 ASSERT(mDropStencilTexture.valid());
298 texture = &mDropStencilTexture;
299 format = DXGI_FORMAT_R32_FLOAT;
300 }
301 else
302 {
303 ANGLE_TRY(getResource(context, &texture));
304 format = mFormatInfo.srvFormat;
305 }
306
307 d3d11::SharedSRV srv;
308
309 ANGLE_TRY(createSRV(context, key.baseLevel, key.mipLevels, format, *texture, &srv));
310
311 const auto &insertIt = mSrvCache.insert(std::make_pair(key, std::move(srv)));
312 *outSRV = &insertIt.first->second;
313
314 return gl::NoError();
315 }
316
getSRVLevel(const gl::Context * context,int mipLevel,bool blitSRV,const d3d11::SharedSRV ** outSRV)317 gl::Error TextureStorage11::getSRVLevel(const gl::Context *context,
318 int mipLevel,
319 bool blitSRV,
320 const d3d11::SharedSRV **outSRV)
321 {
322 ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
323
324 auto &levelSRVs = (blitSRV) ? mLevelBlitSRVs : mLevelSRVs;
325 auto &otherLevelSRVs = (blitSRV) ? mLevelSRVs : mLevelBlitSRVs;
326
327 if (!levelSRVs[mipLevel].valid())
328 {
329 // Only create a different SRV for blit if blit format is different from regular srv format
330 if (otherLevelSRVs[mipLevel].valid() && mFormatInfo.srvFormat == mFormatInfo.blitSRVFormat)
331 {
332 levelSRVs[mipLevel] = otherLevelSRVs[mipLevel].makeCopy();
333 }
334 else
335 {
336 const TextureHelper11 *resource = nullptr;
337 ANGLE_TRY(getResource(context, &resource));
338
339 DXGI_FORMAT resourceFormat =
340 blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat;
341 ANGLE_TRY(
342 createSRV(context, mipLevel, 1, resourceFormat, *resource, &levelSRVs[mipLevel]));
343 }
344 }
345
346 *outSRV = &levelSRVs[mipLevel];
347
348 return gl::NoError();
349 }
350
getSRVLevels(const gl::Context * context,GLint baseLevel,GLint maxLevel,const d3d11::SharedSRV ** outSRV)351 gl::Error TextureStorage11::getSRVLevels(const gl::Context *context,
352 GLint baseLevel,
353 GLint maxLevel,
354 const d3d11::SharedSRV **outSRV)
355 {
356 unsigned int mipLevels = maxLevel - baseLevel + 1;
357
358 // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
359 // which corresponds to GL level 0)
360 mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - baseLevel);
361
362 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
363 {
364 ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
365 }
366
367 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
368 {
369 // We must ensure that the level zero texture is in sync with mipped texture.
370 ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1));
371 }
372
373 // TODO(jmadill): Assert we don't need to drop stencil.
374
375 SRVKey key(baseLevel, mipLevels, false, false);
376 ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV));
377
378 return gl::NoError();
379 }
380
getFormatSet() const381 const d3d11::Format &TextureStorage11::getFormatSet() const
382 {
383 return mFormatInfo;
384 }
385
generateSwizzles(const gl::Context * context,const gl::SwizzleState & swizzleTarget)386 gl::Error TextureStorage11::generateSwizzles(const gl::Context *context,
387 const gl::SwizzleState &swizzleTarget)
388 {
389 for (int level = 0; level < getLevelCount(); level++)
390 {
391 // Check if the swizzle for this level is out of date
392 if (mSwizzleCache[level] != swizzleTarget)
393 {
394 // Need to re-render the swizzle for this level
395 const d3d11::SharedSRV *sourceSRV = nullptr;
396 ANGLE_TRY(getSRVLevel(context, level, true, &sourceSRV));
397
398 const d3d11::RenderTargetView *destRTV;
399 ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV));
400
401 gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
402
403 Blit11 *blitter = mRenderer->getBlitter();
404
405 ANGLE_TRY(blitter->swizzleTexture(context, *sourceSRV, *destRTV, size, swizzleTarget));
406
407 mSwizzleCache[level] = swizzleTarget;
408 }
409 }
410
411 return gl::NoError();
412 }
413
markLevelDirty(int mipLevel)414 void TextureStorage11::markLevelDirty(int mipLevel)
415 {
416 if (mipLevel >= 0 && static_cast<size_t>(mipLevel) < mSwizzleCache.size())
417 {
418 // The default constructor of SwizzleState has GL_INVALID_INDEX for all channels which is
419 // not a valid swizzle combination
420 if (mSwizzleCache[mipLevel] != gl::SwizzleState())
421 {
422 // TODO(jmadill): Invalidate specific swizzle.
423 mRenderer->getStateManager()->invalidateSwizzles();
424 mSwizzleCache[mipLevel] = gl::SwizzleState();
425 }
426 }
427
428 if (mDropStencilTexture.valid())
429 {
430 mDropStencilTexture.reset();
431 }
432 }
433
markDirty()434 void TextureStorage11::markDirty()
435 {
436 for (size_t mipLevel = 0; mipLevel < mSwizzleCache.size(); ++mipLevel)
437 {
438 markLevelDirty(static_cast<int>(mipLevel));
439 }
440 }
441
updateSubresourceLevel(const gl::Context * context,const TextureHelper11 & srcTexture,unsigned int sourceSubresource,const gl::ImageIndex & index,const gl::Box & copyArea)442 gl::Error TextureStorage11::updateSubresourceLevel(const gl::Context *context,
443 const TextureHelper11 &srcTexture,
444 unsigned int sourceSubresource,
445 const gl::ImageIndex &index,
446 const gl::Box ©Area)
447 {
448 ASSERT(srcTexture.valid());
449
450 const GLint level = index.mipIndex;
451
452 markLevelDirty(level);
453
454 gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
455
456 bool fullCopy = copyArea.x == 0 && copyArea.y == 0 && copyArea.z == 0 &&
457 copyArea.width == texSize.width && copyArea.height == texSize.height &&
458 copyArea.depth == texSize.depth;
459
460 const TextureHelper11 *dstTexture = nullptr;
461
462 // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
463 // should update the mipmapped texture, even if mapmaps are currently disabled.
464 if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
465 {
466 ANGLE_TRY(getMippedResource(context, &dstTexture));
467 }
468 else
469 {
470 ANGLE_TRY(getResource(context, &dstTexture));
471 }
472
473 unsigned int dstSubresource = getSubresourceIndex(index);
474
475 ASSERT(dstTexture->valid());
476
477 const d3d11::DXGIFormatSize &dxgiFormatSizeInfo =
478 d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat);
479 if (!fullCopy && mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
480 {
481 // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
482 Blit11 *blitter = mRenderer->getBlitter();
483 return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize,
484 *dstTexture, dstSubresource, copyArea, texSize, nullptr);
485 }
486
487 D3D11_BOX srcBox;
488 srcBox.left = copyArea.x;
489 srcBox.top = copyArea.y;
490 srcBox.right =
491 copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatSizeInfo.blockWidth);
492 srcBox.bottom =
493 copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatSizeInfo.blockHeight);
494 srcBox.front = copyArea.z;
495 srcBox.back = copyArea.z + copyArea.depth;
496
497 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
498
499 deviceContext->CopySubresourceRegion(dstTexture->get(), dstSubresource, copyArea.x, copyArea.y,
500 copyArea.z, srcTexture.get(), sourceSubresource,
501 fullCopy ? nullptr : &srcBox);
502 return gl::NoError();
503 }
504
copySubresourceLevel(const gl::Context * context,const TextureHelper11 & dstTexture,unsigned int dstSubresource,const gl::ImageIndex & index,const gl::Box & region)505 gl::Error TextureStorage11::copySubresourceLevel(const gl::Context *context,
506 const TextureHelper11 &dstTexture,
507 unsigned int dstSubresource,
508 const gl::ImageIndex &index,
509 const gl::Box ®ion)
510 {
511 ASSERT(dstTexture.valid());
512
513 const TextureHelper11 *srcTexture = nullptr;
514
515 // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
516 // should update the mipmapped texture, even if mapmaps are currently disabled.
517 if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
518 {
519 ANGLE_TRY(getMippedResource(context, &srcTexture));
520 }
521 else
522 {
523 ANGLE_TRY(getResource(context, &srcTexture));
524 }
525
526 ASSERT(srcTexture->valid());
527
528 unsigned int srcSubresource = getSubresourceIndex(index);
529
530 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
531
532 // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox
533 // should be nullptr.
534 D3D11_BOX srcBox;
535 D3D11_BOX *pSrcBox = nullptr;
536 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
537 {
538 GLsizei width = region.width;
539 GLsizei height = region.height;
540 d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, nullptr);
541
542 // Keep srcbox as nullptr if we're dealing with tiny mips of compressed textures.
543 if (width == region.width && height == region.height)
544 {
545 // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless
546 // the source box is specified. This is okay, since we don't perform
547 // CopySubresourceRegion on depth/stencil textures on 9_3.
548 ASSERT(mFormatInfo.dsvFormat == DXGI_FORMAT_UNKNOWN);
549 srcBox.left = region.x;
550 srcBox.right = region.x + region.width;
551 srcBox.top = region.y;
552 srcBox.bottom = region.y + region.height;
553 srcBox.front = region.z;
554 srcBox.back = region.z + region.depth;
555 pSrcBox = &srcBox;
556 }
557 }
558
559 deviceContext->CopySubresourceRegion(dstTexture.get(), dstSubresource, region.x, region.y,
560 region.z, srcTexture->get(), srcSubresource, pSrcBox);
561
562 return gl::NoError();
563 }
564
generateMipmap(const gl::Context * context,const gl::ImageIndex & sourceIndex,const gl::ImageIndex & destIndex)565 gl::Error TextureStorage11::generateMipmap(const gl::Context *context,
566 const gl::ImageIndex &sourceIndex,
567 const gl::ImageIndex &destIndex)
568 {
569 ASSERT(sourceIndex.layerIndex == destIndex.layerIndex);
570
571 markLevelDirty(destIndex.mipIndex);
572
573 RenderTargetD3D *source = nullptr;
574 ANGLE_TRY(getRenderTarget(context, sourceIndex, &source));
575
576 RenderTargetD3D *dest = nullptr;
577 ANGLE_TRY(getRenderTarget(context, destIndex, &dest));
578
579 RenderTarget11 *rt11 = GetAs<RenderTarget11>(source);
580 const d3d11::SharedSRV &sourceSRV = rt11->getBlitShaderResourceView();
581 const d3d11::RenderTargetView &destRTV = rt11->getRenderTargetView();
582
583 gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
584 gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth());
585
586 gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth());
587 gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
588
589 Blit11 *blitter = mRenderer->getBlitter();
590 GLenum format = gl::GetUnsizedFormat(source->getInternalFormat());
591 return blitter->copyTexture(context, sourceSRV, sourceArea, sourceSize, format, destRTV,
592 destArea, destSize, nullptr, format, GL_LINEAR, false, false,
593 false);
594 }
595
verifySwizzleExists(const gl::SwizzleState & swizzleState)596 void TextureStorage11::verifySwizzleExists(const gl::SwizzleState &swizzleState)
597 {
598 for (unsigned int level = 0; level < mMipLevels; level++)
599 {
600 ASSERT(mSwizzleCache[level] == swizzleState);
601 }
602 }
603
clearSRVCache()604 void TextureStorage11::clearSRVCache()
605 {
606 markDirty();
607 mSrvCache.clear();
608
609 for (size_t level = 0; level < mLevelSRVs.size(); level++)
610 {
611 mLevelSRVs[level].reset();
612 mLevelBlitSRVs[level].reset();
613 }
614 }
615
copyToStorage(const gl::Context * context,TextureStorage * destStorage)616 gl::Error TextureStorage11::copyToStorage(const gl::Context *context, TextureStorage *destStorage)
617 {
618 ASSERT(destStorage);
619
620 const TextureHelper11 *sourceResouce = nullptr;
621 ANGLE_TRY(getResource(context, &sourceResouce));
622
623 TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage);
624 const TextureHelper11 *destResource = nullptr;
625 ANGLE_TRY(dest11->getResource(context, &destResource));
626
627 ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
628 immediateContext->CopyResource(destResource->get(), sourceResouce->get());
629
630 dest11->markDirty();
631
632 return gl::NoError();
633 }
634
setData(const gl::Context * context,const gl::ImageIndex & index,ImageD3D * image,const gl::Box * destBox,GLenum type,const gl::PixelUnpackState & unpack,const uint8_t * pixelData)635 gl::Error TextureStorage11::setData(const gl::Context *context,
636 const gl::ImageIndex &index,
637 ImageD3D *image,
638 const gl::Box *destBox,
639 GLenum type,
640 const gl::PixelUnpackState &unpack,
641 const uint8_t *pixelData)
642 {
643 ASSERT(!image->isDirty());
644
645 markLevelDirty(index.mipIndex);
646
647 const TextureHelper11 *resource = nullptr;
648 ANGLE_TRY(getResource(context, &resource));
649 ASSERT(resource && resource->valid());
650
651 UINT destSubresource = getSubresourceIndex(index);
652
653 const gl::InternalFormat &internalFormatInfo =
654 gl::GetInternalFormatInfo(image->getInternalFormat(), type);
655
656 gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
657 getLevelDepth(index.mipIndex));
658 bool fullUpdate = (destBox == nullptr || *destBox == levelBox);
659 ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate);
660
661 // TODO(jmadill): Handle compressed formats
662 // Compressed formats have different load syntax, so we'll have to handle them with slightly
663 // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData
664 // with compressed formats in the calling logic.
665 ASSERT(!internalFormatInfo.compressed);
666
667 const int imageWidth = static_cast<int>(image->getWidth());
668 const int width = destBox ? destBox->width : imageWidth;
669 const int imageHeight = static_cast<int>(image->getHeight());
670 const int height = destBox ? destBox->height : imageHeight;
671 const int imageDepth = static_cast<int>(image->getDepth());
672 const int depth = destBox ? destBox->depth : imageDepth;
673 if (imageWidth < width || imageHeight < height || imageDepth < depth)
674 fullUpdate = true;
675 GLuint srcRowPitch = 0;
676 ANGLE_TRY_RESULT(
677 internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength),
678 srcRowPitch);
679 GLuint srcDepthPitch = 0;
680 ANGLE_TRY_RESULT(internalFormatInfo.computeDepthPitch(height, unpack.imageHeight, srcRowPitch),
681 srcDepthPitch);
682 GLuint srcSkipBytes = 0;
683 ANGLE_TRY_RESULT(
684 internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()),
685 srcSkipBytes);
686
687 const d3d11::Format &d3d11Format =
688 d3d11::Format::Get(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
689 const d3d11::DXGIFormatSize &dxgiFormatInfo =
690 d3d11::GetDXGIFormatSizeInfo(d3d11Format.texFormat);
691
692 const size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
693
694 UINT bufferRowPitch = static_cast<unsigned int>(outputPixelSize) * width;
695 UINT bufferDepthPitch = bufferRowPitch * height;
696
697 const size_t neededSize = bufferDepthPitch * depth;
698 angle::MemoryBuffer *conversionBuffer = nullptr;
699 const uint8_t *data = nullptr;
700
701 LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(type);
702 if (loadFunctionInfo.requiresConversion)
703 {
704 ANGLE_TRY(mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer));
705 loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch,
706 srcDepthPitch, conversionBuffer->data(), bufferRowPitch,
707 bufferDepthPitch);
708 data = conversionBuffer->data();
709 }
710 else
711 {
712 data = pixelData + srcSkipBytes;
713 bufferRowPitch = srcRowPitch;
714 bufferDepthPitch = srcDepthPitch;
715 }
716
717 ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
718
719 if (!fullUpdate)
720 {
721 ASSERT(destBox);
722
723 D3D11_BOX destD3DBox;
724 destD3DBox.left = destBox->x;
725 destD3DBox.right = destBox->x + destBox->width;
726 destD3DBox.top = destBox->y;
727 destD3DBox.bottom = destBox->y + destBox->height;
728 destD3DBox.front = destBox->z;
729 destD3DBox.back = destBox->z + destBox->depth;
730
731 immediateContext->UpdateSubresource(resource->get(), destSubresource, &destD3DBox, data,
732 bufferRowPitch, bufferDepthPitch);
733 }
734 else
735 {
736 immediateContext->UpdateSubresource(resource->get(), destSubresource, nullptr, data,
737 bufferRowPitch, bufferDepthPitch);
738 }
739
740 return gl::NoError();
741 }
742
ensureDropStencilTexture(const gl::Context * context)743 gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11::ensureDropStencilTexture(
744 const gl::Context *context)
745 {
746 UNIMPLEMENTED();
747 return gl::InternalError() << "Drop stencil texture not implemented.";
748 }
749
TextureStorage11_2D(Renderer11 * renderer,SwapChain11 * swapchain)750 TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
751 : TextureStorage11(renderer,
752 D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
753 0,
754 swapchain->getRenderTargetInternalFormat()),
755 mTexture(swapchain->getOffscreenTexture()),
756 mLevelZeroTexture(),
757 mLevelZeroRenderTarget(nullptr),
758 mUseLevelZeroTexture(false),
759 mSwizzleTexture()
760 {
761 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
762 {
763 mAssociatedImages[i] = nullptr;
764 mRenderTarget[i] = nullptr;
765 }
766
767 D3D11_TEXTURE2D_DESC texDesc;
768 mTexture.getDesc(&texDesc);
769 mMipLevels = texDesc.MipLevels;
770 mTextureWidth = texDesc.Width;
771 mTextureHeight = texDesc.Height;
772 mTextureDepth = 1;
773 mHasKeyedMutex = (texDesc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
774 }
775
TextureStorage11_2D(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,int levels,bool hintLevelZeroOnly)776 TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer,
777 GLenum internalformat,
778 bool renderTarget,
779 GLsizei width,
780 GLsizei height,
781 int levels,
782 bool hintLevelZeroOnly)
783 : TextureStorage11(
784 renderer,
785 GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
786 GetTextureMiscFlags(internalformat,
787 renderer->getRenderer11DeviceCaps(),
788 renderTarget,
789 levels),
790 internalformat),
791 mTexture(),
792 mHasKeyedMutex(false),
793 mLevelZeroTexture(),
794 mLevelZeroRenderTarget(nullptr),
795 mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
796 mSwizzleTexture()
797 {
798 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
799 {
800 mAssociatedImages[i] = nullptr;
801 mRenderTarget[i] = nullptr;
802 }
803
804 d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
805 mMipLevels = mTopLevel + levels;
806 mTextureWidth = width;
807 mTextureHeight = height;
808 mTextureDepth = 1;
809
810 // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
811 ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround);
812 }
813
onDestroy(const gl::Context * context)814 gl::Error TextureStorage11_2D::onDestroy(const gl::Context *context)
815 {
816 for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
817 {
818 if (mAssociatedImages[i] != nullptr)
819 {
820 mAssociatedImages[i]->verifyAssociatedStorageValid(this);
821
822 // We must let the Images recover their data before we delete it from the
823 // TextureStorage.
824 ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
825 }
826 }
827
828 if (mHasKeyedMutex)
829 {
830 // If the keyed mutex is released that will unbind it and cause the state cache to become
831 // desynchronized.
832 mRenderer->getStateManager()->invalidateBoundViews();
833 }
834
835 // Invalidate RenderTargets.
836 InvalidateRenderTargetContainer(context, &mRenderTarget);
837 InvalidateRenderTarget(context, mLevelZeroRenderTarget.get());
838
839 return gl::NoError();
840 }
841
~TextureStorage11_2D()842 TextureStorage11_2D::~TextureStorage11_2D()
843 {
844 }
845
copyToStorage(const gl::Context * context,TextureStorage * destStorage)846 gl::Error TextureStorage11_2D::copyToStorage(const gl::Context *context,
847 TextureStorage *destStorage)
848 {
849 ASSERT(destStorage);
850
851 TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage);
852 ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
853
854 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
855 {
856 // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
857 // corresponding textures in destStorage.
858 if (mTexture.valid())
859 {
860 ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
861
862 const TextureHelper11 *destResource = nullptr;
863 ANGLE_TRY(dest11->getResource(context, &destResource));
864
865 immediateContext->CopyResource(destResource->get(), mTexture.get());
866 }
867
868 if (mLevelZeroTexture.valid())
869 {
870 ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
871
872 const TextureHelper11 *destResource = nullptr;
873 ANGLE_TRY(dest11->getResource(context, &destResource));
874
875 immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
876 }
877
878 return gl::NoError();
879 }
880
881 const TextureHelper11 *sourceResouce = nullptr;
882 ANGLE_TRY(getResource(context, &sourceResouce));
883
884 const TextureHelper11 *destResource = nullptr;
885 ANGLE_TRY(dest11->getResource(context, &destResource));
886
887 immediateContext->CopyResource(destResource->get(), sourceResouce->get());
888 dest11->markDirty();
889
890 return gl::NoError();
891 }
892
useLevelZeroWorkaroundTexture(const gl::Context * context,bool useLevelZeroTexture)893 gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(const gl::Context *context,
894 bool useLevelZeroTexture)
895 {
896 bool lastSetting = mUseLevelZeroTexture;
897
898 if (useLevelZeroTexture && mMipLevels > 1)
899 {
900 if (!mUseLevelZeroTexture && mTexture.valid())
901 {
902 ANGLE_TRY(ensureTextureExists(1));
903
904 // Pull data back from the mipped texture if necessary.
905 ASSERT(mLevelZeroTexture.valid());
906 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
907 deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(), 0, 0, 0, 0,
908 mTexture.get(), 0, nullptr);
909 }
910
911 mUseLevelZeroTexture = true;
912 }
913 else
914 {
915 if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
916 {
917 ANGLE_TRY(ensureTextureExists(mMipLevels));
918
919 // Pull data back from the level zero texture if necessary.
920 ASSERT(mTexture.valid());
921 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
922 deviceContext->CopySubresourceRegion(mTexture.get(), 0, 0, 0, 0,
923 mLevelZeroTexture.get(), 0, nullptr);
924 }
925
926 mUseLevelZeroTexture = false;
927 }
928
929 if (lastSetting != mUseLevelZeroTexture)
930 {
931 // Mark everything as dirty to be conservative.
932 if (mLevelZeroRenderTarget)
933 {
934 mLevelZeroRenderTarget->signalDirty(context);
935 }
936 for (auto &renderTarget : mRenderTarget)
937 {
938 if (renderTarget)
939 {
940 renderTarget->signalDirty(context);
941 }
942 }
943 }
944
945 return gl::NoError();
946 }
947
associateImage(Image11 * image,const gl::ImageIndex & index)948 void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
949 {
950 const GLint level = index.mipIndex;
951
952 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
953
954 if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
955 {
956 mAssociatedImages[level] = image;
957 }
958 }
959
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)960 void TextureStorage11_2D::verifyAssociatedImageValid(const gl::ImageIndex &index,
961 Image11 *expectedImage)
962 {
963 const GLint level = index.mipIndex;
964
965 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
966 // This validation check should never return false. It means the Image/TextureStorage
967 // association is broken.
968 ASSERT(mAssociatedImages[level] == expectedImage);
969 }
970
971 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)972 void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
973 {
974 const GLint level = index.mipIndex;
975
976 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
977 ASSERT(mAssociatedImages[level] == expectedImage);
978 mAssociatedImages[level] = nullptr;
979 }
980
981 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
982 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)983 gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::Context *context,
984 const gl::ImageIndex &index,
985 Image11 *incomingImage)
986 {
987 const GLint level = index.mipIndex;
988
989 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
990
991 if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
992 {
993 // No need to let the old Image recover its data, if it is also the incoming Image.
994 if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
995 {
996 // Ensure that the Image is still associated with this TextureStorage.
997 mAssociatedImages[level]->verifyAssociatedStorageValid(this);
998
999 // Force the image to recover from storage before its data is overwritten.
1000 // This will reset mAssociatedImages[level] to nullptr too.
1001 ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
1002 }
1003 }
1004
1005 return gl::NoError();
1006 }
1007
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1008 gl::Error TextureStorage11_2D::getResource(const gl::Context *context,
1009 const TextureHelper11 **outResource)
1010 {
1011 if (mUseLevelZeroTexture && mMipLevels > 1)
1012 {
1013 ANGLE_TRY(ensureTextureExists(1));
1014
1015 *outResource = &mLevelZeroTexture;
1016 return gl::NoError();
1017 }
1018
1019 ANGLE_TRY(ensureTextureExists(mMipLevels));
1020
1021 *outResource = &mTexture;
1022 return gl::NoError();
1023 }
1024
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)1025 gl::Error TextureStorage11_2D::getMippedResource(const gl::Context *context,
1026 const TextureHelper11 **outResource)
1027 {
1028 // This shouldn't be called unless the zero max LOD workaround is active.
1029 ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
1030
1031 ANGLE_TRY(ensureTextureExists(mMipLevels));
1032
1033 *outResource = &mTexture;
1034 return gl::NoError();
1035 }
1036
ensureTextureExists(int mipLevels)1037 gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels)
1038 {
1039 // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
1040 bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround
1041 ? (mipLevels == 1) && (mMipLevels > 1)
1042 : false;
1043 TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
1044
1045 // if the width or height is not positive this should be treated as an incomplete texture
1046 // we handle that here by skipping the d3d texture creation
1047 if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
1048 {
1049 ASSERT(mipLevels > 0);
1050
1051 D3D11_TEXTURE2D_DESC desc;
1052 desc.Width = mTextureWidth; // Compressed texture size constraints?
1053 desc.Height = mTextureHeight;
1054 desc.MipLevels = mipLevels;
1055 desc.ArraySize = 1;
1056 desc.Format = mFormatInfo.texFormat;
1057 desc.SampleDesc.Count = 1;
1058 desc.SampleDesc.Quality = 0;
1059 desc.Usage = D3D11_USAGE_DEFAULT;
1060 desc.BindFlags = getBindFlags();
1061 desc.CPUAccessFlags = 0;
1062 desc.MiscFlags = getMiscFlags();
1063
1064 ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, outputTexture));
1065 outputTexture->setDebugName("TexStorage2D.Texture");
1066 }
1067
1068 return gl::NoError();
1069 }
1070
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)1071 gl::Error TextureStorage11_2D::getRenderTarget(const gl::Context *context,
1072 const gl::ImageIndex &index,
1073 RenderTargetD3D **outRT)
1074 {
1075 ASSERT(!index.hasLayer());
1076
1077 const int level = index.mipIndex;
1078 ASSERT(level >= 0 && level < getLevelCount());
1079
1080 // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of
1081 // the GLES 2.0 spec, page 113 of version 2.0.25). Other parts of TextureStorage11_2D could
1082 // create RTVs on non-zero levels of the texture (e.g. generateMipmap).
1083 // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the
1084 // individual levels of the texture, so methods like generateMipmap can't do anything useful
1085 // with non-zero-level RTVs. Therefore if level > 0 on 9_3 then there's almost certainly
1086 // something wrong.
1087 ASSERT(
1088 !(mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0));
1089 ASSERT(outRT);
1090 if (mRenderTarget[level])
1091 {
1092 *outRT = mRenderTarget[level].get();
1093 return gl::NoError();
1094 }
1095
1096 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
1097 {
1098 ASSERT(index.mipIndex == 0);
1099 ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
1100 }
1101
1102 const TextureHelper11 *texture = nullptr;
1103 ANGLE_TRY(getResource(context, &texture));
1104
1105 const d3d11::SharedSRV *srv = nullptr;
1106 ANGLE_TRY(getSRVLevel(context, level, false, &srv));
1107
1108 const d3d11::SharedSRV *blitSRV = nullptr;
1109 ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
1110
1111 if (mUseLevelZeroTexture)
1112 {
1113 if (!mLevelZeroRenderTarget)
1114 {
1115 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1116 rtvDesc.Format = mFormatInfo.rtvFormat;
1117 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1118 rtvDesc.Texture2D.MipSlice = mTopLevel + level;
1119
1120 d3d11::RenderTargetView rtv;
1121 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture.get(), &rtv));
1122
1123 mLevelZeroRenderTarget.reset(new TextureRenderTarget11(
1124 std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
1125 mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
1126 getLevelHeight(level), 1, 0));
1127 }
1128
1129 *outRT = mLevelZeroRenderTarget.get();
1130 return gl::NoError();
1131 }
1132
1133 if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
1134 {
1135 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1136 rtvDesc.Format = mFormatInfo.rtvFormat;
1137 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1138 rtvDesc.Texture2D.MipSlice = mTopLevel + level;
1139
1140 d3d11::RenderTargetView rtv;
1141 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
1142
1143 mRenderTarget[level].reset(new TextureRenderTarget11(
1144 std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
1145 getLevelWidth(level), getLevelHeight(level), 1, 0));
1146
1147 *outRT = mRenderTarget[level].get();
1148 return gl::NoError();
1149 }
1150
1151 ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
1152
1153 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
1154 dsvDesc.Format = mFormatInfo.dsvFormat;
1155 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
1156 dsvDesc.Texture2D.MipSlice = mTopLevel + level;
1157 dsvDesc.Flags = 0;
1158
1159 d3d11::DepthStencilView dsv;
1160 ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv));
1161
1162 mRenderTarget[level].reset(new TextureRenderTarget11(
1163 std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
1164 getLevelWidth(level), getLevelHeight(level), 1, 0));
1165
1166 *outRT = mRenderTarget[level].get();
1167 return gl::NoError();
1168 }
1169
createSRV(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1170 gl::Error TextureStorage11_2D::createSRV(const gl::Context *context,
1171 int baseLevel,
1172 int mipLevels,
1173 DXGI_FORMAT format,
1174 const TextureHelper11 &texture,
1175 d3d11::SharedSRV *outSRV)
1176 {
1177 ASSERT(outSRV);
1178
1179 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1180 srvDesc.Format = format;
1181 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
1182 srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
1183 srvDesc.Texture2D.MipLevels = mipLevels;
1184
1185 const TextureHelper11 *srvTexture = &texture;
1186
1187 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
1188 {
1189 ASSERT(mTopLevel == 0);
1190 ASSERT(baseLevel == 0);
1191 // This code also assumes that the incoming texture equals either mLevelZeroTexture or
1192 // mTexture.
1193
1194 if (mipLevels == 1 && mMipLevels > 1)
1195 {
1196 // We must use a SRV on the level-zero-only texture.
1197 ANGLE_TRY(ensureTextureExists(1));
1198 srvTexture = &mLevelZeroTexture;
1199 }
1200 else
1201 {
1202 ASSERT(mipLevels == static_cast<int>(mMipLevels));
1203 ASSERT(mTexture.valid() && texture == mTexture);
1204 srvTexture = &mTexture;
1205 }
1206 }
1207
1208 ANGLE_TRY(mRenderer->allocateResource(srvDesc, srvTexture->get(), outSRV));
1209 outSRV->setDebugName("TexStorage2D.SRV");
1210
1211 return gl::NoError();
1212 }
1213
getSwizzleTexture(const TextureHelper11 ** outTexture)1214 gl::Error TextureStorage11_2D::getSwizzleTexture(const TextureHelper11 **outTexture)
1215 {
1216 ASSERT(outTexture);
1217
1218 if (!mSwizzleTexture.valid())
1219 {
1220 const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
1221
1222 D3D11_TEXTURE2D_DESC desc;
1223 desc.Width = mTextureWidth;
1224 desc.Height = mTextureHeight;
1225 desc.MipLevels = mMipLevels;
1226 desc.ArraySize = 1;
1227 desc.Format = format.texFormat;
1228 desc.SampleDesc.Count = 1;
1229 desc.SampleDesc.Quality = 0;
1230 desc.Usage = D3D11_USAGE_DEFAULT;
1231 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1232 desc.CPUAccessFlags = 0;
1233 desc.MiscFlags = 0;
1234
1235 ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
1236 mSwizzleTexture.setDebugName("TexStorage2D.SwizzleTexture");
1237 }
1238
1239 *outTexture = &mSwizzleTexture;
1240 return gl::NoError();
1241 }
1242
getSwizzleRenderTarget(int mipLevel,const d3d11::RenderTargetView ** outRTV)1243 gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel,
1244 const d3d11::RenderTargetView **outRTV)
1245 {
1246 ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
1247 ASSERT(outRTV);
1248
1249 if (!mSwizzleRenderTargets[mipLevel].valid())
1250 {
1251 const TextureHelper11 *swizzleTexture = nullptr;
1252 ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
1253
1254 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1255 rtvDesc.Format =
1256 mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
1257 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1258 rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
1259
1260 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
1261 &mSwizzleRenderTargets[mipLevel]));
1262 }
1263
1264 *outRTV = &mSwizzleRenderTargets[mipLevel];
1265 return gl::NoError();
1266 }
1267
ensureDropStencilTexture(const gl::Context * context)1268 gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2D::ensureDropStencilTexture(
1269 const gl::Context *context)
1270 {
1271 if (mDropStencilTexture.valid())
1272 {
1273 return DropStencil::ALREADY_EXISTS;
1274 }
1275
1276 D3D11_TEXTURE2D_DESC dropDesc = {};
1277 dropDesc.ArraySize = 1;
1278 dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
1279 dropDesc.CPUAccessFlags = 0;
1280 dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
1281 dropDesc.Height = mTextureHeight;
1282 dropDesc.MipLevels = mMipLevels;
1283 dropDesc.MiscFlags = 0;
1284 dropDesc.SampleDesc.Count = 1;
1285 dropDesc.SampleDesc.Quality = 0;
1286 dropDesc.Usage = D3D11_USAGE_DEFAULT;
1287 dropDesc.Width = mTextureWidth;
1288
1289 const auto &format =
1290 d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
1291 ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture));
1292 mDropStencilTexture.setDebugName("TexStorage2D.DropStencil");
1293
1294 ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::Make2D(0, mMipLevels)));
1295
1296 return DropStencil::CREATED;
1297 }
1298
TextureStorage11_External(Renderer11 * renderer,egl::Stream * stream,const egl::Stream::GLTextureDescription & glDesc)1299 TextureStorage11_External::TextureStorage11_External(
1300 Renderer11 *renderer,
1301 egl::Stream *stream,
1302 const egl::Stream::GLTextureDescription &glDesc)
1303 : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat)
1304 {
1305 ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11TextureNV12);
1306 StreamProducerNV12 *producer = static_cast<StreamProducerNV12 *>(stream->getImplementation());
1307 mTexture.set(producer->getD3DTexture(), mFormatInfo);
1308 mSubresourceIndex = producer->getArraySlice();
1309 mTexture.get()->AddRef();
1310 mMipLevels = 1;
1311
1312 D3D11_TEXTURE2D_DESC desc;
1313 mTexture.getDesc(&desc);
1314 mTextureWidth = desc.Width;
1315 mTextureHeight = desc.Height;
1316 mTextureDepth = 1;
1317 mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
1318 }
1319
onDestroy(const gl::Context * context)1320 gl::Error TextureStorage11_External::onDestroy(const gl::Context *context)
1321 {
1322 if (mHasKeyedMutex)
1323 {
1324 // If the keyed mutex is released that will unbind it and cause the state cache to become
1325 // desynchronized.
1326 mRenderer->getStateManager()->invalidateBoundViews();
1327 }
1328
1329 return gl::NoError();
1330 }
1331
~TextureStorage11_External()1332 TextureStorage11_External::~TextureStorage11_External()
1333 {
1334 }
1335
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1336 gl::Error TextureStorage11_External::copyToStorage(const gl::Context *context,
1337 TextureStorage *destStorage)
1338 {
1339 UNIMPLEMENTED();
1340 return gl::NoError();
1341 }
1342
associateImage(Image11 * image,const gl::ImageIndex & index)1343 void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index)
1344 {
1345 ASSERT(index.mipIndex == 0);
1346 mAssociatedImage = image;
1347 }
1348
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)1349 void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index,
1350 Image11 *expectedImage)
1351 {
1352 ASSERT(index.mipIndex == 0 && mAssociatedImage == expectedImage);
1353 }
1354
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)1355 void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index,
1356 Image11 *expectedImage)
1357 {
1358 ASSERT(index.mipIndex == 0);
1359 ASSERT(mAssociatedImage == expectedImage);
1360 mAssociatedImage = nullptr;
1361 }
1362
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)1363 gl::Error TextureStorage11_External::releaseAssociatedImage(const gl::Context *context,
1364 const gl::ImageIndex &index,
1365 Image11 *incomingImage)
1366 {
1367 ASSERT(index.mipIndex == 0);
1368
1369 if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
1370 {
1371 mAssociatedImage->verifyAssociatedStorageValid(this);
1372
1373 ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
1374 }
1375
1376 return gl::NoError();
1377 }
1378
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1379 gl::Error TextureStorage11_External::getResource(const gl::Context *context,
1380 const TextureHelper11 **outResource)
1381 {
1382 *outResource = &mTexture;
1383 return gl::NoError();
1384 }
1385
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)1386 gl::Error TextureStorage11_External::getMippedResource(const gl::Context *context,
1387 const TextureHelper11 **outResource)
1388 {
1389 *outResource = &mTexture;
1390 return gl::NoError();
1391 }
1392
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)1393 gl::Error TextureStorage11_External::getRenderTarget(const gl::Context *context,
1394 const gl::ImageIndex &index,
1395 RenderTargetD3D **outRT)
1396 {
1397 // Render targets are not supported for external textures
1398 UNREACHABLE();
1399 return gl::InternalError();
1400 }
1401
createSRV(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1402 gl::Error TextureStorage11_External::createSRV(const gl::Context *context,
1403 int baseLevel,
1404 int mipLevels,
1405 DXGI_FORMAT format,
1406 const TextureHelper11 &texture,
1407 d3d11::SharedSRV *outSRV)
1408 {
1409 // Since external textures are treates as non-mipmapped textures, we ignore mipmap levels and
1410 // use the specified subresource ID the storage was created with.
1411 ASSERT(mipLevels == 1);
1412 ASSERT(outSRV);
1413
1414 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1415 srvDesc.Format = format;
1416 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1417 // subresource index is equal to the mip level for 2D textures
1418 srvDesc.Texture2DArray.MostDetailedMip = 0;
1419 srvDesc.Texture2DArray.MipLevels = 1;
1420 srvDesc.Texture2DArray.FirstArraySlice = mSubresourceIndex;
1421 srvDesc.Texture2DArray.ArraySize = 1;
1422
1423 ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
1424 outSRV->setDebugName("TexStorage2D.SRV");
1425
1426 return gl::NoError();
1427 }
1428
getSwizzleTexture(const TextureHelper11 ** outTexture)1429 gl::Error TextureStorage11_External::getSwizzleTexture(const TextureHelper11 **outTexture)
1430 {
1431 UNIMPLEMENTED();
1432 return gl::InternalError();
1433 }
1434
getSwizzleRenderTarget(int mipLevel,const d3d11::RenderTargetView ** outRTV)1435 gl::Error TextureStorage11_External::getSwizzleRenderTarget(int mipLevel,
1436 const d3d11::RenderTargetView **outRTV)
1437 {
1438 UNIMPLEMENTED();
1439 return gl::InternalError();
1440 }
1441
TextureStorage11_EGLImage(Renderer11 * renderer,EGLImageD3D * eglImage,RenderTarget11 * renderTarget11)1442 TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
1443 EGLImageD3D *eglImage,
1444 RenderTarget11 *renderTarget11)
1445 : TextureStorage11(renderer,
1446 D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
1447 0,
1448 renderTarget11->getInternalFormat()),
1449 mImage(eglImage),
1450 mCurrentRenderTarget(0),
1451 mSwizzleTexture(),
1452 mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1453 {
1454 mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
1455
1456 mMipLevels = 1;
1457 mTextureWidth = renderTarget11->getWidth();
1458 mTextureHeight = renderTarget11->getHeight();
1459 mTextureDepth = 1;
1460 }
1461
~TextureStorage11_EGLImage()1462 TextureStorage11_EGLImage::~TextureStorage11_EGLImage()
1463 {
1464 }
1465
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1466 gl::Error TextureStorage11_EGLImage::getResource(const gl::Context *context,
1467 const TextureHelper11 **outResource)
1468 {
1469 ANGLE_TRY(checkForUpdatedRenderTarget(context));
1470
1471 RenderTarget11 *renderTarget11 = nullptr;
1472 ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
1473 *outResource = &renderTarget11->getTexture();
1474 return gl::NoError();
1475 }
1476
getSRV(const gl::Context * context,const gl::TextureState & textureState,const d3d11::SharedSRV ** outSRV)1477 gl::Error TextureStorage11_EGLImage::getSRV(const gl::Context *context,
1478 const gl::TextureState &textureState,
1479 const d3d11::SharedSRV **outSRV)
1480 {
1481 ANGLE_TRY(checkForUpdatedRenderTarget(context));
1482 return TextureStorage11::getSRV(context, textureState, outSRV);
1483 }
1484
getMippedResource(const gl::Context * context,const TextureHelper11 **)1485 gl::Error TextureStorage11_EGLImage::getMippedResource(const gl::Context *context,
1486 const TextureHelper11 **)
1487 {
1488 // This shouldn't be called unless the zero max LOD workaround is active.
1489 // EGL images are unavailable in this configuration.
1490 UNREACHABLE();
1491 return gl::InternalError();
1492 }
1493
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)1494 gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context,
1495 const gl::ImageIndex &index,
1496 RenderTargetD3D **outRT)
1497 {
1498 ASSERT(!index.hasLayer());
1499 ASSERT(index.mipIndex == 0);
1500
1501 ANGLE_TRY(checkForUpdatedRenderTarget(context));
1502
1503 return mImage->getRenderTarget(context, outRT);
1504 }
1505
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1506 gl::Error TextureStorage11_EGLImage::copyToStorage(const gl::Context *context,
1507 TextureStorage *destStorage)
1508 {
1509 const TextureHelper11 *sourceResouce = nullptr;
1510 ANGLE_TRY(getResource(context, &sourceResouce));
1511
1512 ASSERT(destStorage);
1513 TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage);
1514 const TextureHelper11 *destResource = nullptr;
1515 ANGLE_TRY(dest11->getResource(context, &destResource));
1516
1517 ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
1518 immediateContext->CopyResource(destResource->get(), sourceResouce->get());
1519
1520 dest11->markDirty();
1521
1522 return gl::NoError();
1523 }
1524
associateImage(Image11 *,const gl::ImageIndex &)1525 void TextureStorage11_EGLImage::associateImage(Image11 *, const gl::ImageIndex &)
1526 {
1527 }
1528
disassociateImage(const gl::ImageIndex &,Image11 *)1529 void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &, Image11 *)
1530 {
1531 }
1532
verifyAssociatedImageValid(const gl::ImageIndex &,Image11 *)1533 void TextureStorage11_EGLImage::verifyAssociatedImageValid(const gl::ImageIndex &, Image11 *)
1534 {
1535 }
1536
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex &,Image11 *)1537 gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::Context *context,
1538 const gl::ImageIndex &,
1539 Image11 *)
1540 {
1541 return gl::NoError();
1542 }
1543
useLevelZeroWorkaroundTexture(const gl::Context * context,bool)1544 gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(const gl::Context *context, bool)
1545 {
1546 UNREACHABLE();
1547 return gl::InternalError();
1548 }
1549
getSwizzleTexture(const TextureHelper11 ** outTexture)1550 gl::Error TextureStorage11_EGLImage::getSwizzleTexture(const TextureHelper11 **outTexture)
1551 {
1552 ASSERT(outTexture);
1553
1554 if (!mSwizzleTexture.valid())
1555 {
1556 const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
1557
1558 D3D11_TEXTURE2D_DESC desc;
1559 desc.Width = mTextureWidth;
1560 desc.Height = mTextureHeight;
1561 desc.MipLevels = mMipLevels;
1562 desc.ArraySize = 1;
1563 desc.Format = format.texFormat;
1564 desc.SampleDesc.Count = 1;
1565 desc.SampleDesc.Quality = 0;
1566 desc.Usage = D3D11_USAGE_DEFAULT;
1567 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1568 desc.CPUAccessFlags = 0;
1569 desc.MiscFlags = 0;
1570
1571 ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
1572 mSwizzleTexture.setDebugName("TexStorageEGLImage.SwizzleTexture");
1573 }
1574
1575 *outTexture = &mSwizzleTexture;
1576 return gl::NoError();
1577 }
1578
getSwizzleRenderTarget(int mipLevel,const d3d11::RenderTargetView ** outRTV)1579 gl::Error TextureStorage11_EGLImage::getSwizzleRenderTarget(int mipLevel,
1580 const d3d11::RenderTargetView **outRTV)
1581 {
1582 ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
1583 ASSERT(outRTV);
1584
1585 if (!mSwizzleRenderTargets[mipLevel].valid())
1586 {
1587 const TextureHelper11 *swizzleTexture = nullptr;
1588 ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
1589
1590 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1591 rtvDesc.Format =
1592 mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
1593 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1594 rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
1595
1596 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
1597 &mSwizzleRenderTargets[mipLevel]));
1598 }
1599
1600 *outRTV = &mSwizzleRenderTargets[mipLevel];
1601 return gl::NoError();
1602 }
1603
checkForUpdatedRenderTarget(const gl::Context * context)1604 gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget(const gl::Context *context)
1605 {
1606 RenderTarget11 *renderTarget11 = nullptr;
1607 ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
1608
1609 if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11))
1610 {
1611 clearSRVCache();
1612 mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
1613 }
1614
1615 return gl::NoError();
1616 }
1617
createSRV(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1618 gl::Error TextureStorage11_EGLImage::createSRV(const gl::Context *context,
1619 int baseLevel,
1620 int mipLevels,
1621 DXGI_FORMAT format,
1622 const TextureHelper11 &texture,
1623 d3d11::SharedSRV *outSRV)
1624 {
1625 ASSERT(baseLevel == 0);
1626 ASSERT(mipLevels == 1);
1627 ASSERT(outSRV);
1628
1629 // Create a new SRV only for the swizzle texture. Otherwise just return the Image's
1630 // RenderTarget's SRV.
1631 if (texture == mSwizzleTexture)
1632 {
1633 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1634 srvDesc.Format = format;
1635 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
1636 srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
1637 srvDesc.Texture2D.MipLevels = mipLevels;
1638
1639 ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
1640 outSRV->setDebugName("TexStorageEGLImage.SRV");
1641 }
1642 else
1643 {
1644 RenderTarget11 *renderTarget = nullptr;
1645 ANGLE_TRY(getImageRenderTarget(context, &renderTarget));
1646
1647 ASSERT(texture == renderTarget->getTexture());
1648
1649 *outSRV = renderTarget->getShaderResourceView().makeCopy();
1650 }
1651
1652 return gl::NoError();
1653 }
1654
getImageRenderTarget(const gl::Context * context,RenderTarget11 ** outRT) const1655 gl::Error TextureStorage11_EGLImage::getImageRenderTarget(const gl::Context *context,
1656 RenderTarget11 **outRT) const
1657 {
1658 RenderTargetD3D *renderTargetD3D = nullptr;
1659 ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
1660 *outRT = GetAs<RenderTarget11>(renderTargetD3D);
1661 return gl::NoError();
1662 }
1663
TextureStorage11_Cube(Renderer11 * renderer,GLenum internalformat,bool renderTarget,int size,int levels,bool hintLevelZeroOnly)1664 TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer,
1665 GLenum internalformat,
1666 bool renderTarget,
1667 int size,
1668 int levels,
1669 bool hintLevelZeroOnly)
1670 : TextureStorage11(
1671 renderer,
1672 GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
1673 GetTextureMiscFlags(internalformat,
1674 renderer->getRenderer11DeviceCaps(),
1675 renderTarget,
1676 levels),
1677 internalformat),
1678 mTexture(),
1679 mLevelZeroTexture(),
1680 mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
1681 mSwizzleTexture()
1682 {
1683 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
1684 {
1685 for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++)
1686 {
1687 mAssociatedImages[face][level] = nullptr;
1688 mRenderTarget[face][level] = nullptr;
1689 }
1690 }
1691
1692 for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++)
1693 {
1694 mLevelZeroRenderTarget[face] = nullptr;
1695 }
1696
1697 // adjust size if needed for compressed textures
1698 int height = size;
1699 d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel);
1700
1701 mMipLevels = mTopLevel + levels;
1702 mTextureWidth = size;
1703 mTextureHeight = size;
1704 mTextureDepth = 1;
1705
1706 // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
1707 ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround);
1708 }
1709
onDestroy(const gl::Context * context)1710 gl::Error TextureStorage11_Cube::onDestroy(const gl::Context *context)
1711 {
1712 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
1713 {
1714 for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++)
1715 {
1716 if (mAssociatedImages[face][level] != nullptr)
1717 {
1718 mAssociatedImages[face][level]->verifyAssociatedStorageValid(this);
1719
1720 // We must let the Images recover their data before we delete it from the
1721 // TextureStorage.
1722 ANGLE_TRY(mAssociatedImages[face][level]->recoverFromAssociatedStorage(context));
1723 }
1724 }
1725 }
1726
1727 for (auto &faceRenderTargets : mRenderTarget)
1728 {
1729 InvalidateRenderTargetContainer(context, &faceRenderTargets);
1730 }
1731 InvalidateRenderTargetContainer(context, &mLevelZeroRenderTarget);
1732
1733 return gl::NoError();
1734 }
1735
~TextureStorage11_Cube()1736 TextureStorage11_Cube::~TextureStorage11_Cube()
1737 {
1738 }
1739
getSubresourceIndex(const gl::ImageIndex & index) const1740 UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const
1741 {
1742 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture &&
1743 index.mipIndex == 0)
1744 {
1745 UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
1746 UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
1747 ASSERT(subresource != std::numeric_limits<UINT>::max());
1748 return subresource;
1749 }
1750 else
1751 {
1752 UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
1753 UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
1754 UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
1755 ASSERT(subresource != std::numeric_limits<UINT>::max());
1756 return subresource;
1757 }
1758 }
1759
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1760 gl::Error TextureStorage11_Cube::copyToStorage(const gl::Context *context,
1761 TextureStorage *destStorage)
1762 {
1763 ASSERT(destStorage);
1764
1765 TextureStorage11_Cube *dest11 = GetAs<TextureStorage11_Cube>(destStorage);
1766
1767 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
1768 {
1769 ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
1770
1771 // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
1772 // corresponding textures in destStorage.
1773 if (mTexture.valid())
1774 {
1775 ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
1776
1777 const TextureHelper11 *destResource = nullptr;
1778 ANGLE_TRY(dest11->getResource(context, &destResource));
1779
1780 immediateContext->CopyResource(destResource->get(), mTexture.get());
1781 }
1782
1783 if (mLevelZeroTexture.valid())
1784 {
1785 ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
1786
1787 const TextureHelper11 *destResource = nullptr;
1788 ANGLE_TRY(dest11->getResource(context, &destResource));
1789
1790 immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
1791 }
1792 }
1793 else
1794 {
1795 const TextureHelper11 *sourceResouce = nullptr;
1796 ANGLE_TRY(getResource(context, &sourceResouce));
1797
1798 const TextureHelper11 *destResource = nullptr;
1799 ANGLE_TRY(dest11->getResource(context, &destResource));
1800
1801 ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
1802 immediateContext->CopyResource(destResource->get(), sourceResouce->get());
1803 }
1804
1805 dest11->markDirty();
1806
1807 return gl::NoError();
1808 }
1809
useLevelZeroWorkaroundTexture(const gl::Context * context,bool useLevelZeroTexture)1810 gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(const gl::Context *context,
1811 bool useLevelZeroTexture)
1812 {
1813 if (useLevelZeroTexture && mMipLevels > 1)
1814 {
1815 if (!mUseLevelZeroTexture && mTexture.valid())
1816 {
1817 ANGLE_TRY(ensureTextureExists(1));
1818
1819 // Pull data back from the mipped texture if necessary.
1820 ASSERT(mLevelZeroTexture.valid());
1821 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1822
1823 for (int face = 0; face < 6; face++)
1824 {
1825 deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(),
1826 D3D11CalcSubresource(0, face, 1), 0, 0, 0,
1827 mTexture.get(), face * mMipLevels, nullptr);
1828 }
1829 }
1830
1831 mUseLevelZeroTexture = true;
1832 }
1833 else
1834 {
1835 if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
1836 {
1837 ANGLE_TRY(ensureTextureExists(mMipLevels));
1838
1839 // Pull data back from the level zero texture if necessary.
1840 ASSERT(mTexture.valid());
1841 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1842
1843 for (int face = 0; face < 6; face++)
1844 {
1845 deviceContext->CopySubresourceRegion(mTexture.get(),
1846 D3D11CalcSubresource(0, face, mMipLevels), 0,
1847 0, 0, mLevelZeroTexture.get(), face, nullptr);
1848 }
1849 }
1850
1851 mUseLevelZeroTexture = false;
1852 }
1853
1854 return gl::NoError();
1855 }
1856
associateImage(Image11 * image,const gl::ImageIndex & index)1857 void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index)
1858 {
1859 const GLint level = index.mipIndex;
1860 const GLint layerTarget = index.layerIndex;
1861
1862 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1863 ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT));
1864
1865 if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1866 {
1867 if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT))
1868 {
1869 mAssociatedImages[layerTarget][level] = image;
1870 }
1871 }
1872 }
1873
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)1874 void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index,
1875 Image11 *expectedImage)
1876 {
1877 const GLint level = index.mipIndex;
1878 const GLint layerTarget = index.layerIndex;
1879
1880 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1881 ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT));
1882 // This validation check should never return false. It means the Image/TextureStorage
1883 // association is broken.
1884 ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
1885 }
1886
1887 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)1888 void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
1889 {
1890 const GLint level = index.mipIndex;
1891 const GLint layerTarget = index.layerIndex;
1892
1893 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1894 ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT));
1895 ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
1896 mAssociatedImages[layerTarget][level] = nullptr;
1897 }
1898
1899 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
1900 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)1901 gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::Context *context,
1902 const gl::ImageIndex &index,
1903 Image11 *incomingImage)
1904 {
1905 const GLint level = index.mipIndex;
1906 const GLint layerTarget = index.layerIndex;
1907
1908 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1909 ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT));
1910
1911 if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1912 {
1913 if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT))
1914 {
1915 // No need to let the old Image recover its data, if it is also the incoming Image.
1916 if (mAssociatedImages[layerTarget][level] != nullptr &&
1917 mAssociatedImages[layerTarget][level] != incomingImage)
1918 {
1919 // Ensure that the Image is still associated with this TextureStorage.
1920 mAssociatedImages[layerTarget][level]->verifyAssociatedStorageValid(this);
1921
1922 // Force the image to recover from storage before its data is overwritten.
1923 // This will reset mAssociatedImages[level] to nullptr too.
1924 ANGLE_TRY(
1925 mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(context));
1926 }
1927 }
1928 }
1929
1930 return gl::NoError();
1931 }
1932
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1933 gl::Error TextureStorage11_Cube::getResource(const gl::Context *context,
1934 const TextureHelper11 **outResource)
1935 {
1936 if (mUseLevelZeroTexture && mMipLevels > 1)
1937 {
1938 ANGLE_TRY(ensureTextureExists(1));
1939 *outResource = &mLevelZeroTexture;
1940 return gl::NoError();
1941 }
1942 else
1943 {
1944 ANGLE_TRY(ensureTextureExists(mMipLevels));
1945 *outResource = &mTexture;
1946 return gl::NoError();
1947 }
1948 }
1949
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)1950 gl::Error TextureStorage11_Cube::getMippedResource(const gl::Context *context,
1951 const TextureHelper11 **outResource)
1952 {
1953 // This shouldn't be called unless the zero max LOD workaround is active.
1954 ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
1955
1956 ANGLE_TRY(ensureTextureExists(mMipLevels));
1957 *outResource = &mTexture;
1958 return gl::NoError();
1959 }
1960
ensureTextureExists(int mipLevels)1961 gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels)
1962 {
1963 // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
1964 bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround
1965 ? (mipLevels == 1) && (mMipLevels > 1)
1966 : false;
1967 TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
1968
1969 // if the size is not positive this should be treated as an incomplete texture
1970 // we handle that here by skipping the d3d texture creation
1971 if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
1972 {
1973 ASSERT(mMipLevels > 0);
1974
1975 D3D11_TEXTURE2D_DESC desc;
1976 desc.Width = mTextureWidth;
1977 desc.Height = mTextureHeight;
1978 desc.MipLevels = mipLevels;
1979 desc.ArraySize = gl::CUBE_FACE_COUNT;
1980 desc.Format = mFormatInfo.texFormat;
1981 desc.SampleDesc.Count = 1;
1982 desc.SampleDesc.Quality = 0;
1983 desc.Usage = D3D11_USAGE_DEFAULT;
1984 desc.BindFlags = getBindFlags();
1985 desc.CPUAccessFlags = 0;
1986 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags();
1987
1988 ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, outputTexture));
1989 outputTexture->setDebugName("TexStorageCube.Texture");
1990 }
1991
1992 return gl::NoError();
1993 }
1994
createRenderTargetSRV(const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const1995 gl::Error TextureStorage11_Cube::createRenderTargetSRV(const TextureHelper11 &texture,
1996 const gl::ImageIndex &index,
1997 DXGI_FORMAT resourceFormat,
1998 d3d11::SharedSRV *srv) const
1999 {
2000 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2001 srvDesc.Format = resourceFormat;
2002 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
2003 srvDesc.Texture2DArray.MipLevels = 1;
2004 srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex;
2005 srvDesc.Texture2DArray.ArraySize = 1;
2006
2007 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
2008 {
2009 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
2010 }
2011 else
2012 {
2013 // Will be used with Texture2D sampler, not TextureCube
2014 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2015 }
2016
2017 ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), srv));
2018 return gl::NoError();
2019 }
2020
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)2021 gl::Error TextureStorage11_Cube::getRenderTarget(const gl::Context *context,
2022 const gl::ImageIndex &index,
2023 RenderTargetD3D **outRT)
2024 {
2025 const int faceIndex = index.layerIndex;
2026 const int level = index.mipIndex;
2027
2028 ASSERT(level >= 0 && level < getLevelCount());
2029 ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::CUBE_FACE_COUNT));
2030
2031 if (!mRenderTarget[faceIndex][level])
2032 {
2033 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
2034 {
2035 ASSERT(index.mipIndex == 0);
2036 ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
2037 }
2038
2039 const TextureHelper11 *texture = nullptr;
2040 ANGLE_TRY(getResource(context, &texture));
2041
2042 if (mUseLevelZeroTexture)
2043 {
2044 if (!mLevelZeroRenderTarget[faceIndex])
2045 {
2046 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2047 rtvDesc.Format = mFormatInfo.rtvFormat;
2048 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2049 rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
2050 rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2051 rtvDesc.Texture2DArray.ArraySize = 1;
2052
2053 d3d11::RenderTargetView rtv;
2054 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture.get(), &rtv));
2055
2056 mLevelZeroRenderTarget[faceIndex].reset(new TextureRenderTarget11(
2057 std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
2058 mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
2059 getLevelHeight(level), 1, 0));
2060 }
2061
2062 ASSERT(outRT);
2063 *outRT = mLevelZeroRenderTarget[faceIndex].get();
2064 return gl::NoError();
2065 }
2066
2067 d3d11::SharedSRV srv;
2068 ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.srvFormat, &srv));
2069 d3d11::SharedSRV blitSRV;
2070 if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
2071 {
2072 ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.blitSRVFormat, &blitSRV));
2073 }
2074 else
2075 {
2076 blitSRV = srv.makeCopy();
2077 }
2078
2079 srv.setDebugName("TexStorageCube.RenderTargetSRV");
2080
2081 if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
2082 {
2083 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2084 rtvDesc.Format = mFormatInfo.rtvFormat;
2085 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2086 rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
2087 rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2088 rtvDesc.Texture2DArray.ArraySize = 1;
2089
2090 d3d11::RenderTargetView rtv;
2091 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
2092 rtv.setDebugName("TexStorageCube.RenderTargetRTV");
2093
2094 mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
2095 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
2096 getLevelWidth(level), getLevelHeight(level), 1, 0));
2097 }
2098 else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
2099 {
2100 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
2101 dsvDesc.Format = mFormatInfo.dsvFormat;
2102 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
2103 dsvDesc.Flags = 0;
2104 dsvDesc.Texture2DArray.MipSlice = mTopLevel + level;
2105 dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2106 dsvDesc.Texture2DArray.ArraySize = 1;
2107
2108 d3d11::DepthStencilView dsv;
2109 ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv));
2110 dsv.setDebugName("TexStorageCube.RenderTargetDSV");
2111
2112 mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
2113 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
2114 getLevelWidth(level), getLevelHeight(level), 1, 0));
2115 }
2116 else
2117 {
2118 UNREACHABLE();
2119 }
2120 }
2121
2122 ASSERT(outRT);
2123 *outRT = mRenderTarget[faceIndex][level].get();
2124 return gl::NoError();
2125 }
2126
createSRV(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2127 gl::Error TextureStorage11_Cube::createSRV(const gl::Context *context,
2128 int baseLevel,
2129 int mipLevels,
2130 DXGI_FORMAT format,
2131 const TextureHelper11 &texture,
2132 d3d11::SharedSRV *outSRV)
2133 {
2134 ASSERT(outSRV);
2135
2136 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2137 srvDesc.Format = format;
2138
2139 // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six
2140 // 2D textures
2141 const GLenum componentType = d3d11::GetComponentType(format);
2142 if (componentType == GL_INT || componentType == GL_UNSIGNED_INT)
2143 {
2144 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2145 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
2146 srvDesc.Texture2DArray.MipLevels = mipLevels;
2147 srvDesc.Texture2DArray.FirstArraySlice = 0;
2148 srvDesc.Texture2DArray.ArraySize = gl::CUBE_FACE_COUNT;
2149 }
2150 else
2151 {
2152 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
2153 srvDesc.TextureCube.MipLevels = mipLevels;
2154 srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
2155 }
2156
2157 const TextureHelper11 *srvTexture = &texture;
2158
2159 if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
2160 {
2161 ASSERT(mTopLevel == 0);
2162 ASSERT(baseLevel == 0);
2163 // This code also assumes that the incoming texture equals either mLevelZeroTexture or
2164 // mTexture.
2165
2166 if (mipLevels == 1 && mMipLevels > 1)
2167 {
2168 // We must use a SRV on the level-zero-only texture.
2169 ANGLE_TRY(ensureTextureExists(1));
2170 srvTexture = &mLevelZeroTexture;
2171 }
2172 else
2173 {
2174 ASSERT(mipLevels == static_cast<int>(mMipLevels));
2175 ASSERT(mTexture.valid() && texture == mTexture);
2176 srvTexture = &mTexture;
2177 }
2178 }
2179
2180 ANGLE_TRY(mRenderer->allocateResource(srvDesc, srvTexture->get(), outSRV));
2181 outSRV->setDebugName("TexStorageCube.SRV");
2182
2183 return gl::NoError();
2184 }
2185
getSwizzleTexture(const TextureHelper11 ** outTexture)2186 gl::Error TextureStorage11_Cube::getSwizzleTexture(const TextureHelper11 **outTexture)
2187 {
2188 ASSERT(outTexture);
2189
2190 if (!mSwizzleTexture.valid())
2191 {
2192 const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
2193
2194 D3D11_TEXTURE2D_DESC desc;
2195 desc.Width = mTextureWidth;
2196 desc.Height = mTextureHeight;
2197 desc.MipLevels = mMipLevels;
2198 desc.ArraySize = gl::CUBE_FACE_COUNT;
2199 desc.Format = format.texFormat;
2200 desc.SampleDesc.Count = 1;
2201 desc.SampleDesc.Quality = 0;
2202 desc.Usage = D3D11_USAGE_DEFAULT;
2203 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
2204 desc.CPUAccessFlags = 0;
2205 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
2206
2207 ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
2208 mSwizzleTexture.setDebugName("TexStorageCube.SwizzleTexture");
2209 }
2210
2211 *outTexture = &mSwizzleTexture;
2212 return gl::NoError();
2213 }
2214
getSwizzleRenderTarget(int mipLevel,const d3d11::RenderTargetView ** outRTV)2215 gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel,
2216 const d3d11::RenderTargetView **outRTV)
2217 {
2218 ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2219 ASSERT(outRTV);
2220
2221 if (!mSwizzleRenderTargets[mipLevel].valid())
2222 {
2223 const TextureHelper11 *swizzleTexture = nullptr;
2224 ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
2225
2226 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2227 rtvDesc.Format =
2228 mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
2229 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2230 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
2231 rtvDesc.Texture2DArray.FirstArraySlice = 0;
2232 rtvDesc.Texture2DArray.ArraySize = gl::CUBE_FACE_COUNT;
2233
2234 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
2235 &mSwizzleRenderTargets[mipLevel]));
2236 }
2237
2238 *outRTV = &mSwizzleRenderTargets[mipLevel];
2239 return gl::NoError();
2240 }
2241
initDropStencilTexture(const gl::Context * context,const gl::ImageIndexIterator & it)2242 gl::Error TextureStorage11::initDropStencilTexture(const gl::Context *context,
2243 const gl::ImageIndexIterator &it)
2244 {
2245 const TextureHelper11 *sourceTexture = nullptr;
2246 ANGLE_TRY(getResource(context, &sourceTexture));
2247
2248 gl::ImageIndexIterator itCopy = it;
2249
2250 while (itCopy.hasNext())
2251 {
2252 gl::ImageIndex index = itCopy.next();
2253 gl::Box wholeArea(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
2254 1);
2255 gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
2256 UINT subresource = getSubresourceIndex(index);
2257 ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(
2258 *sourceTexture, subresource, wholeArea, wholeSize, mDropStencilTexture, subresource,
2259 wholeArea, wholeSize, nullptr));
2260 }
2261
2262 return gl::NoError();
2263 }
2264
ensureDropStencilTexture(const gl::Context * context)2265 gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_Cube::ensureDropStencilTexture(
2266 const gl::Context *context)
2267 {
2268 if (mDropStencilTexture.valid())
2269 {
2270 return DropStencil::ALREADY_EXISTS;
2271 }
2272
2273 D3D11_TEXTURE2D_DESC dropDesc = {};
2274 dropDesc.ArraySize = 6;
2275 dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
2276 dropDesc.CPUAccessFlags = 0;
2277 dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
2278 dropDesc.Height = mTextureHeight;
2279 dropDesc.MipLevels = mMipLevels;
2280 dropDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
2281 dropDesc.SampleDesc.Count = 1;
2282 dropDesc.SampleDesc.Quality = 0;
2283 dropDesc.Usage = D3D11_USAGE_DEFAULT;
2284 dropDesc.Width = mTextureWidth;
2285
2286 const auto &format =
2287 d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
2288 ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture));
2289 mDropStencilTexture.setDebugName("TexStorageCube.DropStencil");
2290
2291 ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
2292
2293 return DropStencil::CREATED;
2294 }
2295
TextureStorage11_3D(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels)2296 TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
2297 GLenum internalformat,
2298 bool renderTarget,
2299 GLsizei width,
2300 GLsizei height,
2301 GLsizei depth,
2302 int levels)
2303 : TextureStorage11(
2304 renderer,
2305 GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
2306 GetTextureMiscFlags(internalformat,
2307 renderer->getRenderer11DeviceCaps(),
2308 renderTarget,
2309 levels),
2310 internalformat)
2311 {
2312 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2313 {
2314 mAssociatedImages[i] = nullptr;
2315 mLevelRenderTargets[i] = nullptr;
2316 }
2317
2318 // adjust size if needed for compressed textures
2319 d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
2320
2321 mMipLevels = mTopLevel + levels;
2322 mTextureWidth = width;
2323 mTextureHeight = height;
2324 mTextureDepth = depth;
2325 }
2326
onDestroy(const gl::Context * context)2327 gl::Error TextureStorage11_3D::onDestroy(const gl::Context *context)
2328 {
2329 for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2330 {
2331 if (mAssociatedImages[i] != nullptr)
2332 {
2333 mAssociatedImages[i]->verifyAssociatedStorageValid(this);
2334
2335 // We must let the Images recover their data before we delete it from the
2336 // TextureStorage.
2337 ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
2338 }
2339 }
2340
2341 InvalidateRenderTargetContainer(context, &mLevelRenderTargets);
2342 InvalidateRenderTargetContainer(context, &mLevelLayerRenderTargets);
2343
2344 return gl::NoError();
2345 }
2346
~TextureStorage11_3D()2347 TextureStorage11_3D::~TextureStorage11_3D()
2348 {
2349 }
2350
associateImage(Image11 * image,const gl::ImageIndex & index)2351 void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
2352 {
2353 const GLint level = index.mipIndex;
2354
2355 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2356
2357 if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2358 {
2359 mAssociatedImages[level] = image;
2360 }
2361 }
2362
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2363 void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index,
2364 Image11 *expectedImage)
2365 {
2366 const GLint level = index.mipIndex;
2367
2368 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2369 // This validation check should never return false. It means the Image/TextureStorage
2370 // association is broken.
2371 ASSERT(mAssociatedImages[level] == expectedImage);
2372 }
2373
2374 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)2375 void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
2376 {
2377 const GLint level = index.mipIndex;
2378
2379 ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2380 ASSERT(mAssociatedImages[level] == expectedImage);
2381 mAssociatedImages[level] = nullptr;
2382 }
2383
2384 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
2385 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)2386 gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::Context *context,
2387 const gl::ImageIndex &index,
2388 Image11 *incomingImage)
2389 {
2390 const GLint level = index.mipIndex;
2391
2392 ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
2393
2394 if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2395 {
2396 // No need to let the old Image recover its data, if it is also the incoming Image.
2397 if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
2398 {
2399 // Ensure that the Image is still associated with this TextureStorage.
2400 mAssociatedImages[level]->verifyAssociatedStorageValid(this);
2401
2402 // Force the image to recover from storage before its data is overwritten.
2403 // This will reset mAssociatedImages[level] to nullptr too.
2404 ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
2405 }
2406 }
2407
2408 return gl::NoError();
2409 }
2410
getResource(const gl::Context * context,const TextureHelper11 ** outResource)2411 gl::Error TextureStorage11_3D::getResource(const gl::Context *context,
2412 const TextureHelper11 **outResource)
2413 {
2414 // If the width, height or depth are not positive this should be treated as an incomplete
2415 // texture. We handle that here by skipping the d3d texture creation.
2416 if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
2417 {
2418 ASSERT(mMipLevels > 0);
2419
2420 D3D11_TEXTURE3D_DESC desc;
2421 desc.Width = mTextureWidth;
2422 desc.Height = mTextureHeight;
2423 desc.Depth = mTextureDepth;
2424 desc.MipLevels = mMipLevels;
2425 desc.Format = mFormatInfo.texFormat;
2426 desc.Usage = D3D11_USAGE_DEFAULT;
2427 desc.BindFlags = getBindFlags();
2428 desc.CPUAccessFlags = 0;
2429 desc.MiscFlags = getMiscFlags();
2430
2431 ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture));
2432 mTexture.setDebugName("TexStorage3D.Texture");
2433 }
2434
2435 *outResource = &mTexture;
2436 return gl::NoError();
2437 }
2438
createSRV(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2439 gl::Error TextureStorage11_3D::createSRV(const gl::Context *context,
2440 int baseLevel,
2441 int mipLevels,
2442 DXGI_FORMAT format,
2443 const TextureHelper11 &texture,
2444 d3d11::SharedSRV *outSRV)
2445 {
2446 ASSERT(outSRV);
2447
2448 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2449 srvDesc.Format = format;
2450 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
2451 srvDesc.Texture3D.MostDetailedMip = baseLevel;
2452 srvDesc.Texture3D.MipLevels = mipLevels;
2453
2454 ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
2455 outSRV->setDebugName("TexStorage3D.SRV");
2456
2457 return gl::NoError();
2458 }
2459
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)2460 gl::Error TextureStorage11_3D::getRenderTarget(const gl::Context *context,
2461 const gl::ImageIndex &index,
2462 RenderTargetD3D **outRT)
2463 {
2464 const int mipLevel = index.mipIndex;
2465 ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2466
2467 ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
2468
2469 if (!index.hasLayer())
2470 {
2471 if (!mLevelRenderTargets[mipLevel])
2472 {
2473 const TextureHelper11 *texture = nullptr;
2474 ANGLE_TRY(getResource(context, &texture));
2475
2476 const d3d11::SharedSRV *srv = nullptr;
2477 ANGLE_TRY(getSRVLevel(context, mipLevel, false, &srv));
2478
2479 const d3d11::SharedSRV *blitSRV = nullptr;
2480 ANGLE_TRY(getSRVLevel(context, mipLevel, true, &blitSRV));
2481
2482 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2483 rtvDesc.Format = mFormatInfo.rtvFormat;
2484 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
2485 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
2486 rtvDesc.Texture3D.FirstWSlice = 0;
2487 rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
2488
2489 d3d11::RenderTargetView rtv;
2490 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
2491 rtv.setDebugName("TexStorage3D.RTV");
2492
2493 mLevelRenderTargets[mipLevel].reset(new TextureRenderTarget11(
2494 std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat,
2495 getFormatSet(), getLevelWidth(mipLevel), getLevelHeight(mipLevel),
2496 getLevelDepth(mipLevel), 0));
2497 }
2498
2499 ASSERT(outRT);
2500 *outRT = mLevelRenderTargets[mipLevel].get();
2501 return gl::NoError();
2502 }
2503
2504 const int layer = index.layerIndex;
2505
2506 LevelLayerKey key(mipLevel, layer);
2507 if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
2508 {
2509 const TextureHelper11 *texture = nullptr;
2510 ANGLE_TRY(getResource(context, &texture));
2511
2512 // TODO, what kind of SRV is expected here?
2513 const d3d11::SharedSRV srv;
2514 const d3d11::SharedSRV blitSRV;
2515
2516 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2517 rtvDesc.Format = mFormatInfo.rtvFormat;
2518 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
2519 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
2520 rtvDesc.Texture3D.FirstWSlice = layer;
2521 rtvDesc.Texture3D.WSize = 1;
2522
2523 d3d11::RenderTargetView rtv;
2524 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
2525 rtv.setDebugName("TexStorage3D.LayerRTV");
2526
2527 mLevelLayerRenderTargets[key].reset(new TextureRenderTarget11(
2528 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
2529 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
2530 }
2531
2532 ASSERT(outRT);
2533 *outRT = mLevelLayerRenderTargets[key].get();
2534 return gl::NoError();
2535 }
2536
getSwizzleTexture(const TextureHelper11 ** outTexture)2537 gl::Error TextureStorage11_3D::getSwizzleTexture(const TextureHelper11 **outTexture)
2538 {
2539 ASSERT(outTexture);
2540
2541 if (!mSwizzleTexture.valid())
2542 {
2543 const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
2544
2545 D3D11_TEXTURE3D_DESC desc;
2546 desc.Width = mTextureWidth;
2547 desc.Height = mTextureHeight;
2548 desc.Depth = mTextureDepth;
2549 desc.MipLevels = mMipLevels;
2550 desc.Format = format.texFormat;
2551 desc.Usage = D3D11_USAGE_DEFAULT;
2552 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
2553 desc.CPUAccessFlags = 0;
2554 desc.MiscFlags = 0;
2555
2556 ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
2557 mSwizzleTexture.setDebugName("TexStorage3D.SwizzleTexture");
2558 }
2559
2560 *outTexture = &mSwizzleTexture;
2561 return gl::NoError();
2562 }
2563
getSwizzleRenderTarget(int mipLevel,const d3d11::RenderTargetView ** outRTV)2564 gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel,
2565 const d3d11::RenderTargetView **outRTV)
2566 {
2567 ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2568 ASSERT(outRTV);
2569
2570 if (!mSwizzleRenderTargets[mipLevel].valid())
2571 {
2572 const TextureHelper11 *swizzleTexture = nullptr;
2573 ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
2574
2575 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2576 rtvDesc.Format =
2577 mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
2578 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
2579 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
2580 rtvDesc.Texture3D.FirstWSlice = 0;
2581 rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
2582
2583 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
2584 &mSwizzleRenderTargets[mipLevel]));
2585 mSwizzleRenderTargets[mipLevel].setDebugName("TexStorage3D.SwizzleRTV");
2586 }
2587
2588 *outRTV = &mSwizzleRenderTargets[mipLevel];
2589 return gl::NoError();
2590 }
2591
TextureStorage11_2DArray(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels)2592 TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer,
2593 GLenum internalformat,
2594 bool renderTarget,
2595 GLsizei width,
2596 GLsizei height,
2597 GLsizei depth,
2598 int levels)
2599 : TextureStorage11(
2600 renderer,
2601 GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
2602 GetTextureMiscFlags(internalformat,
2603 renderer->getRenderer11DeviceCaps(),
2604 renderTarget,
2605 levels),
2606 internalformat)
2607 {
2608 // adjust size if needed for compressed textures
2609 d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
2610
2611 mMipLevels = mTopLevel + levels;
2612 mTextureWidth = width;
2613 mTextureHeight = height;
2614 mTextureDepth = depth;
2615 }
2616
onDestroy(const gl::Context * context)2617 gl::Error TextureStorage11_2DArray::onDestroy(const gl::Context *context)
2618 {
2619 for (auto iter : mAssociatedImages)
2620 {
2621 if (iter.second)
2622 {
2623 iter.second->verifyAssociatedStorageValid(this);
2624
2625 // We must let the Images recover their data before we delete it from the
2626 // TextureStorage.
2627 ANGLE_TRY(iter.second->recoverFromAssociatedStorage(context));
2628 }
2629 }
2630 mAssociatedImages.clear();
2631
2632 InvalidateRenderTargetContainer(context, &mRenderTargets);
2633
2634 return gl::NoError();
2635 }
2636
~TextureStorage11_2DArray()2637 TextureStorage11_2DArray::~TextureStorage11_2DArray()
2638 {
2639 }
2640
associateImage(Image11 * image,const gl::ImageIndex & index)2641 void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
2642 {
2643 const GLint level = index.mipIndex;
2644 const GLint layerTarget = index.layerIndex;
2645 const GLint numLayers = index.numLayers;
2646
2647 ASSERT(0 <= level && level < getLevelCount());
2648
2649 if (0 <= level && level < getLevelCount())
2650 {
2651 LevelLayerRangeKey key(level, layerTarget, numLayers);
2652 mAssociatedImages[key] = image;
2653 }
2654 }
2655
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2656 void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index,
2657 Image11 *expectedImage)
2658 {
2659 const GLint level = index.mipIndex;
2660 const GLint layerTarget = index.layerIndex;
2661 const GLint numLayers = index.numLayers;
2662
2663 LevelLayerRangeKey key(level, layerTarget, numLayers);
2664
2665 // This validation check should never return false. It means the Image/TextureStorage
2666 // association is broken.
2667 bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
2668 (mAssociatedImages[key] == expectedImage));
2669 ASSERT(retValue);
2670 }
2671
2672 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)2673 void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index,
2674 Image11 *expectedImage)
2675 {
2676 const GLint level = index.mipIndex;
2677 const GLint layerTarget = index.layerIndex;
2678 const GLint numLayers = index.numLayers;
2679
2680 LevelLayerRangeKey key(level, layerTarget, numLayers);
2681
2682 bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
2683 (mAssociatedImages[key] == expectedImage));
2684 ASSERT(imageAssociationCorrect);
2685 mAssociatedImages[key] = nullptr;
2686 }
2687
2688 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
2689 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)2690 gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::Context *context,
2691 const gl::ImageIndex &index,
2692 Image11 *incomingImage)
2693 {
2694 const GLint level = index.mipIndex;
2695 const GLint layerTarget = index.layerIndex;
2696 const GLint numLayers = index.numLayers;
2697
2698 LevelLayerRangeKey key(level, layerTarget, numLayers);
2699
2700 if (mAssociatedImages.find(key) != mAssociatedImages.end())
2701 {
2702 if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage)
2703 {
2704 // Ensure that the Image is still associated with this TextureStorage.
2705 mAssociatedImages[key]->verifyAssociatedStorageValid(this);
2706
2707 // Force the image to recover from storage before its data is overwritten.
2708 // This will reset mAssociatedImages[level] to nullptr too.
2709 ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage(context));
2710 }
2711 }
2712
2713 return gl::NoError();
2714 }
2715
getResource(const gl::Context * context,const TextureHelper11 ** outResource)2716 gl::Error TextureStorage11_2DArray::getResource(const gl::Context *context,
2717 const TextureHelper11 **outResource)
2718 {
2719 // if the width, height or depth is not positive this should be treated as an incomplete texture
2720 // we handle that here by skipping the d3d texture creation
2721 if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
2722 {
2723 ASSERT(mMipLevels > 0);
2724
2725 D3D11_TEXTURE2D_DESC desc;
2726 desc.Width = mTextureWidth;
2727 desc.Height = mTextureHeight;
2728 desc.MipLevels = mMipLevels;
2729 desc.ArraySize = mTextureDepth;
2730 desc.Format = mFormatInfo.texFormat;
2731 desc.SampleDesc.Count = 1;
2732 desc.SampleDesc.Quality = 0;
2733 desc.Usage = D3D11_USAGE_DEFAULT;
2734 desc.BindFlags = getBindFlags();
2735 desc.CPUAccessFlags = 0;
2736 desc.MiscFlags = getMiscFlags();
2737
2738 ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture));
2739 mTexture.setDebugName("TexStorage2DArray.Texture");
2740 }
2741
2742 *outResource = &mTexture;
2743 return gl::NoError();
2744 }
2745
createSRV(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2746 gl::Error TextureStorage11_2DArray::createSRV(const gl::Context *context,
2747 int baseLevel,
2748 int mipLevels,
2749 DXGI_FORMAT format,
2750 const TextureHelper11 &texture,
2751 d3d11::SharedSRV *outSRV)
2752 {
2753 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2754 srvDesc.Format = format;
2755 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2756 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
2757 srvDesc.Texture2DArray.MipLevels = mipLevels;
2758 srvDesc.Texture2DArray.FirstArraySlice = 0;
2759 srvDesc.Texture2DArray.ArraySize = mTextureDepth;
2760
2761 ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
2762 outSRV->setDebugName("TexStorage2DArray.SRV");
2763
2764 return gl::NoError();
2765 }
2766
createRenderTargetSRV(const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const2767 gl::Error TextureStorage11_2DArray::createRenderTargetSRV(const TextureHelper11 &texture,
2768 const gl::ImageIndex &index,
2769 DXGI_FORMAT resourceFormat,
2770 d3d11::SharedSRV *srv) const
2771 {
2772 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2773 srvDesc.Format = resourceFormat;
2774 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2775 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
2776 srvDesc.Texture2DArray.MipLevels = 1;
2777 srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex;
2778 srvDesc.Texture2DArray.ArraySize = index.numLayers;
2779
2780 ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), srv));
2781
2782 return gl::NoError();
2783 }
2784
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)2785 gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::Context *context,
2786 const gl::ImageIndex &index,
2787 RenderTargetD3D **outRT)
2788 {
2789 ASSERT(index.hasLayer());
2790
2791 const int mipLevel = index.mipIndex;
2792 const int layer = index.layerIndex;
2793 const int numLayers = index.numLayers;
2794
2795 ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2796
2797 LevelLayerRangeKey key(mipLevel, layer, numLayers);
2798 if (mRenderTargets.find(key) == mRenderTargets.end())
2799 {
2800 const TextureHelper11 *texture = nullptr;
2801 ANGLE_TRY(getResource(context, &texture));
2802 d3d11::SharedSRV srv;
2803 ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.srvFormat, &srv));
2804 d3d11::SharedSRV blitSRV;
2805 if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
2806 {
2807 ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.blitSRVFormat, &blitSRV));
2808 }
2809 else
2810 {
2811 blitSRV = srv.makeCopy();
2812 }
2813
2814 srv.setDebugName("TexStorage2DArray.RenderTargetSRV");
2815
2816 if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
2817 {
2818 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2819 rtvDesc.Format = mFormatInfo.rtvFormat;
2820 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2821 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
2822 rtvDesc.Texture2DArray.FirstArraySlice = layer;
2823 rtvDesc.Texture2DArray.ArraySize = numLayers;
2824
2825 d3d11::RenderTargetView rtv;
2826 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
2827 rtv.setDebugName("TexStorage2DArray.RenderTargetRTV");
2828
2829 mRenderTargets[key].reset(new TextureRenderTarget11(
2830 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
2831 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
2832 }
2833 else
2834 {
2835 ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
2836
2837 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
2838 dsvDesc.Format = mFormatInfo.dsvFormat;
2839 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
2840 dsvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
2841 dsvDesc.Texture2DArray.FirstArraySlice = layer;
2842 dsvDesc.Texture2DArray.ArraySize = numLayers;
2843 dsvDesc.Flags = 0;
2844
2845 d3d11::DepthStencilView dsv;
2846 ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv));
2847 dsv.setDebugName("TexStorage2DArray.RenderTargetDSV");
2848
2849 mRenderTargets[key].reset(new TextureRenderTarget11(
2850 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
2851 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
2852 }
2853 }
2854
2855 ASSERT(outRT);
2856 *outRT = mRenderTargets[key].get();
2857 return gl::NoError();
2858 }
2859
getSwizzleTexture(const TextureHelper11 ** outTexture)2860 gl::Error TextureStorage11_2DArray::getSwizzleTexture(const TextureHelper11 **outTexture)
2861 {
2862 if (!mSwizzleTexture.valid())
2863 {
2864 const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
2865
2866 D3D11_TEXTURE2D_DESC desc;
2867 desc.Width = mTextureWidth;
2868 desc.Height = mTextureHeight;
2869 desc.MipLevels = mMipLevels;
2870 desc.ArraySize = mTextureDepth;
2871 desc.Format = format.texFormat;
2872 desc.SampleDesc.Count = 1;
2873 desc.SampleDesc.Quality = 0;
2874 desc.Usage = D3D11_USAGE_DEFAULT;
2875 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
2876 desc.CPUAccessFlags = 0;
2877 desc.MiscFlags = 0;
2878
2879 ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
2880 mSwizzleTexture.setDebugName("TexStorage2DArray.SwizzleTexture");
2881 }
2882
2883 *outTexture = &mSwizzleTexture;
2884 return gl::NoError();
2885 }
2886
getSwizzleRenderTarget(int mipLevel,const d3d11::RenderTargetView ** outRTV)2887 gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel,
2888 const d3d11::RenderTargetView **outRTV)
2889 {
2890 ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2891 ASSERT(outRTV);
2892
2893 if (!mSwizzleRenderTargets[mipLevel].valid())
2894 {
2895 const TextureHelper11 *swizzleTexture = nullptr;
2896 ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
2897
2898 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2899 rtvDesc.Format =
2900 mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
2901 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2902 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
2903 rtvDesc.Texture2DArray.FirstArraySlice = 0;
2904 rtvDesc.Texture2DArray.ArraySize = mTextureDepth;
2905
2906 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
2907 &mSwizzleRenderTargets[mipLevel]));
2908 }
2909
2910 *outRTV = &mSwizzleRenderTargets[mipLevel];
2911 return gl::NoError();
2912 }
2913
ensureDropStencilTexture(const gl::Context * context)2914 gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2DArray::ensureDropStencilTexture(
2915 const gl::Context *context)
2916 {
2917 if (mDropStencilTexture.valid())
2918 {
2919 return DropStencil::ALREADY_EXISTS;
2920 }
2921
2922 D3D11_TEXTURE2D_DESC dropDesc = {};
2923 dropDesc.ArraySize = mTextureDepth;
2924 dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
2925 dropDesc.CPUAccessFlags = 0;
2926 dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
2927 dropDesc.Height = mTextureHeight;
2928 dropDesc.MipLevels = mMipLevels;
2929 dropDesc.MiscFlags = 0;
2930 dropDesc.SampleDesc.Count = 1;
2931 dropDesc.SampleDesc.Quality = 0;
2932 dropDesc.Usage = D3D11_USAGE_DEFAULT;
2933 dropDesc.Width = mTextureWidth;
2934
2935 const auto &format =
2936 d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
2937 ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture));
2938 mDropStencilTexture.setDebugName("TexStorage2DArray.DropStencil");
2939
2940 std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
2941
2942 ANGLE_TRY(initDropStencilTexture(
2943 context, gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
2944
2945 return DropStencil::CREATED;
2946 }
2947
TextureStorage11_2DMultisample(Renderer11 * renderer,GLenum internalformat,GLsizei width,GLsizei height,int levels,int samples,bool fixedSampleLocations)2948 TextureStorage11_2DMultisample::TextureStorage11_2DMultisample(Renderer11 *renderer,
2949 GLenum internalformat,
2950 GLsizei width,
2951 GLsizei height,
2952 int levels,
2953 int samples,
2954 bool fixedSampleLocations)
2955 : TextureStorage11(
2956 renderer,
2957 GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true),
2958 GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels),
2959 internalformat),
2960 mTexture(),
2961 mRenderTarget(nullptr)
2962 {
2963 // adjust size if needed for compressed textures
2964 d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
2965
2966 mMipLevels = 1;
2967 mTextureWidth = width;
2968 mTextureHeight = height;
2969 mTextureDepth = 1;
2970 mSamples = samples;
2971 mFixedSampleLocations = fixedSampleLocations;
2972 }
2973
onDestroy(const gl::Context * context)2974 gl::Error TextureStorage11_2DMultisample::onDestroy(const gl::Context *context)
2975 {
2976 InvalidateRenderTarget(context, mRenderTarget.get());
2977 mRenderTarget.reset();
2978 return gl::NoError();
2979 }
2980
~TextureStorage11_2DMultisample()2981 TextureStorage11_2DMultisample::~TextureStorage11_2DMultisample()
2982 {
2983 }
2984
copyToStorage(const gl::Context * context,TextureStorage * destStorage)2985 gl::Error TextureStorage11_2DMultisample::copyToStorage(const gl::Context *context,
2986 TextureStorage *destStorage)
2987 {
2988 UNIMPLEMENTED();
2989 return gl::InternalError() << "copyToStorage is unimplemented";
2990 }
2991
associateImage(Image11 * image,const gl::ImageIndex & index)2992 void TextureStorage11_2DMultisample::associateImage(Image11 *image, const gl::ImageIndex &index)
2993 {
2994 }
2995
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2996 void TextureStorage11_2DMultisample::verifyAssociatedImageValid(const gl::ImageIndex &index,
2997 Image11 *expectedImage)
2998 {
2999 }
3000
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)3001 void TextureStorage11_2DMultisample::disassociateImage(const gl::ImageIndex &index,
3002 Image11 *expectedImage)
3003 {
3004 }
3005
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)3006 gl::Error TextureStorage11_2DMultisample::releaseAssociatedImage(const gl::Context *context,
3007 const gl::ImageIndex &index,
3008 Image11 *incomingImage)
3009 {
3010 return gl::NoError();
3011 }
3012
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3013 gl::Error TextureStorage11_2DMultisample::getResource(const gl::Context *context,
3014 const TextureHelper11 **outResource)
3015 {
3016 ANGLE_TRY(ensureTextureExists(1));
3017
3018 *outResource = &mTexture;
3019 return gl::NoError();
3020 }
3021
ensureTextureExists(int mipLevels)3022 gl::Error TextureStorage11_2DMultisample::ensureTextureExists(int mipLevels)
3023 {
3024 // For Multisampled textures, mipLevels always equals 1.
3025 ASSERT(mipLevels == 1);
3026
3027 // if the width or height is not positive this should be treated as an incomplete texture
3028 // we handle that here by skipping the d3d texture creation
3029 if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
3030 {
3031 D3D11_TEXTURE2D_DESC desc;
3032 ZeroMemory(&desc, sizeof(desc));
3033 desc.Width = mTextureWidth; // Compressed texture size constraints?
3034 desc.Height = mTextureHeight;
3035 desc.MipLevels = mipLevels;
3036 desc.ArraySize = 1;
3037 desc.Format = mFormatInfo.texFormat;
3038 desc.Usage = D3D11_USAGE_DEFAULT;
3039 desc.BindFlags = getBindFlags();
3040 desc.CPUAccessFlags = 0;
3041 desc.MiscFlags = getMiscFlags();
3042
3043 const gl::TextureCaps &textureCaps =
3044 mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
3045 GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
3046 desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
3047 desc.SampleDesc.Quality = static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN);
3048
3049 ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture));
3050 mTexture.setDebugName("TexStorage2DMS.Texture");
3051 }
3052
3053 return gl::NoError();
3054 }
3055
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,RenderTargetD3D ** outRT)3056 gl::Error TextureStorage11_2DMultisample::getRenderTarget(const gl::Context *context,
3057 const gl::ImageIndex &index,
3058 RenderTargetD3D **outRT)
3059 {
3060 ASSERT(!index.hasLayer());
3061
3062 const int level = index.mipIndex;
3063 ASSERT(level == 0);
3064
3065 ASSERT(outRT);
3066 if (mRenderTarget)
3067 {
3068 *outRT = mRenderTarget.get();
3069 return gl::NoError();
3070 }
3071
3072 const TextureHelper11 *texture = nullptr;
3073 ANGLE_TRY(getResource(context, &texture));
3074
3075 const d3d11::SharedSRV *srv = nullptr;
3076 ANGLE_TRY(getSRVLevel(context, level, false, &srv));
3077
3078 const d3d11::SharedSRV *blitSRV = nullptr;
3079 ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
3080
3081 if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
3082 {
3083 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3084 rtvDesc.Format = mFormatInfo.rtvFormat;
3085 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
3086
3087 d3d11::RenderTargetView rtv;
3088 ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
3089
3090 mRenderTarget.reset(new TextureRenderTarget11(
3091 std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3092 getLevelWidth(level), getLevelHeight(level), 1, mSamples));
3093
3094 *outRT = mRenderTarget.get();
3095 return gl::NoError();
3096 }
3097
3098 ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
3099
3100 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
3101 dsvDesc.Format = mFormatInfo.dsvFormat;
3102 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
3103 dsvDesc.Flags = 0;
3104
3105 d3d11::DepthStencilView dsv;
3106 ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv));
3107
3108 mRenderTarget.reset(new TextureRenderTarget11(
3109 std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
3110 getLevelWidth(level), getLevelHeight(level), 1, mSamples));
3111
3112 *outRT = mRenderTarget.get();
3113 return gl::NoError();
3114 }
3115
createSRV(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3116 gl::Error TextureStorage11_2DMultisample::createSRV(const gl::Context *context,
3117 int baseLevel,
3118 int mipLevels,
3119 DXGI_FORMAT format,
3120 const TextureHelper11 &texture,
3121 d3d11::SharedSRV *outSRV)
3122 {
3123 ASSERT(outSRV);
3124
3125 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3126 srvDesc.Format = format;
3127 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3128
3129 ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
3130 outSRV->setDebugName("TexStorage2DMS.SRV");
3131 return gl::NoError();
3132 }
3133
getSwizzleTexture(const TextureHelper11 ** outTexture)3134 gl::Error TextureStorage11_2DMultisample::getSwizzleTexture(const TextureHelper11 **outTexture)
3135 {
3136 UNIMPLEMENTED();
3137 return gl::InternalError() << "getSwizzleTexture is unimplemented.";
3138 }
3139
getSwizzleRenderTarget(int mipLevel,const d3d11::RenderTargetView ** outRTV)3140 gl::Error TextureStorage11_2DMultisample::getSwizzleRenderTarget(
3141 int mipLevel,
3142 const d3d11::RenderTargetView **outRTV)
3143 {
3144 UNIMPLEMENTED();
3145 return gl::InternalError() << "getSwizzleRenderTarget is unimplemented.";
3146 }
3147
3148 gl::ErrorOrResult<TextureStorage11::DropStencil>
ensureDropStencilTexture(const gl::Context * context)3149 TextureStorage11_2DMultisample::ensureDropStencilTexture(const gl::Context *context)
3150 {
3151 UNIMPLEMENTED();
3152 return gl::InternalError() << "Drop stencil texture not implemented.";
3153 }
3154
3155 } // namespace rx
3156