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 &copyArea)
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 &region)
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