1 //
2 // Copyright 2012 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // 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/Context.h"
18 #include "libANGLE/ImageIndex.h"
19 #include "libANGLE/formatutils.h"
20 #include "libANGLE/renderer/d3d/EGLImageD3D.h"
21 #include "libANGLE/renderer/d3d/TextureD3D.h"
22 #include "libANGLE/renderer/d3d/d3d11/Blit11.h"
23 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
24 #include "libANGLE/renderer/d3d/d3d11/Image11.h"
25 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
26 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
27 #include "libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h"
28 #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
29 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
30 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
31 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
32 
33 namespace rx
34 {
SamplerKey()35 TextureStorage11::SamplerKey::SamplerKey()
36     : baseLevel(0), mipLevels(0), swizzle(false), dropStencil(false)
37 {}
38 
SamplerKey(int baseLevel,int mipLevels,bool swizzle,bool dropStencil)39 TextureStorage11::SamplerKey::SamplerKey(int baseLevel,
40                                          int mipLevels,
41                                          bool swizzle,
42                                          bool dropStencil)
43     : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil)
44 {}
45 
operator <(const SamplerKey & rhs) const46 bool TextureStorage11::SamplerKey::operator<(const SamplerKey &rhs) const
47 {
48     return std::tie(baseLevel, mipLevels, swizzle, dropStencil) <
49            std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil);
50 }
51 
ImageKey()52 TextureStorage11::ImageKey::ImageKey()
53     : level(0), layered(false), layer(0), access(GL_READ_ONLY), format(GL_R32UI)
54 {}
55 
ImageKey(int level,bool layered,int layer,GLenum access,GLenum format)56 TextureStorage11::ImageKey::ImageKey(int level,
57                                      bool layered,
58                                      int layer,
59                                      GLenum access,
60                                      GLenum format)
61     : level(level), layered(layered), layer(layer), access(access), format(format)
62 {}
63 
operator <(const ImageKey & rhs) const64 bool TextureStorage11::ImageKey::operator<(const ImageKey &rhs) const
65 {
66     return std::tie(level, layered, layer, access, format) <
67            std::tie(rhs.level, rhs.layered, rhs.layer, rhs.access, rhs.format);
68 }
69 
MultisampledRenderToTextureInfo(const GLsizei samples,const gl::ImageIndex & indexSS,const gl::ImageIndex & indexMS)70 MultisampledRenderToTextureInfo::MultisampledRenderToTextureInfo(const GLsizei samples,
71                                                                  const gl::ImageIndex &indexSS,
72                                                                  const gl::ImageIndex &indexMS)
73     : samples(samples), indexSS(indexSS), indexMS(indexMS), msTextureNeedsResolve(false)
74 {}
75 
~MultisampledRenderToTextureInfo()76 MultisampledRenderToTextureInfo::~MultisampledRenderToTextureInfo() {}
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 
~TextureStorage11()94 TextureStorage11::~TextureStorage11()
95 {
96     mSrvCacheForSampler.clear();
97 }
98 
GetTextureBindFlags(GLenum internalFormat,const Renderer11DeviceCaps & renderer11DeviceCaps,bool renderTarget)99 DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat,
100                                             const Renderer11DeviceCaps &renderer11DeviceCaps,
101                                             bool renderTarget)
102 {
103     UINT bindFlags = 0;
104 
105     const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
106     if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
107     {
108         bindFlags |= D3D11_BIND_SHADER_RESOURCE;
109     }
110     if (formatInfo.uavFormat != DXGI_FORMAT_UNKNOWN &&
111         renderer11DeviceCaps.featureLevel >= d3d11_gl::GetMinimumFeatureLevelForES31())
112     {
113         // If we find performance issues later on some specific GPUs, this may be the cause.
114         bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
115     }
116     if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
117     {
118         bindFlags |= D3D11_BIND_DEPTH_STENCIL;
119     }
120     if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget)
121     {
122         bindFlags |= D3D11_BIND_RENDER_TARGET;
123     }
124 
125     return bindFlags;
126 }
127 
GetTextureMiscFlags(GLenum internalFormat,const Renderer11DeviceCaps & renderer11DeviceCaps,bool renderTarget,int levels)128 DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat,
129                                             const Renderer11DeviceCaps &renderer11DeviceCaps,
130                                             bool renderTarget,
131                                             int levels)
132 {
133     UINT miscFlags = 0;
134 
135     const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
136     if (renderTarget && levels > 1)
137     {
138         if (d3d11::SupportsMipGen(formatInfo.texFormat, renderer11DeviceCaps.featureLevel))
139         {
140             miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
141         }
142     }
143 
144     return miscFlags;
145 }
146 
getBindFlags() const147 UINT TextureStorage11::getBindFlags() const
148 {
149     return mBindFlags;
150 }
151 
getMiscFlags() const152 UINT TextureStorage11::getMiscFlags() const
153 {
154     return mMiscFlags;
155 }
156 
getTopLevel() const157 int TextureStorage11::getTopLevel() const
158 {
159     // Applying top level is meant to be encapsulated inside TextureStorage11.
160     UNREACHABLE();
161     return mTopLevel;
162 }
163 
isRenderTarget() const164 bool TextureStorage11::isRenderTarget() const
165 {
166     return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
167 }
168 
isManaged() const169 bool TextureStorage11::isManaged() const
170 {
171     return false;
172 }
173 
supportsNativeMipmapFunction() const174 bool TextureStorage11::supportsNativeMipmapFunction() const
175 {
176     return (mMiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) != 0;
177 }
178 
getLevelCount() const179 int TextureStorage11::getLevelCount() const
180 {
181     return mMipLevels - mTopLevel;
182 }
183 
getLevelWidth(int mipLevel) const184 int TextureStorage11::getLevelWidth(int mipLevel) const
185 {
186     return std::max(static_cast<int>(mTextureWidth) >> mipLevel, 1);
187 }
188 
getLevelHeight(int mipLevel) const189 int TextureStorage11::getLevelHeight(int mipLevel) const
190 {
191     return std::max(static_cast<int>(mTextureHeight) >> mipLevel, 1);
192 }
193 
getLevelDepth(int mipLevel) const194 int TextureStorage11::getLevelDepth(int mipLevel) const
195 {
196     return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1);
197 }
198 
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)199 angle::Result TextureStorage11::getMippedResource(const gl::Context *context,
200                                                   const TextureHelper11 **outResource)
201 {
202     return getResource(context, outResource);
203 }
204 
getSubresourceIndex(const gl::Context * context,const gl::ImageIndex & index,UINT * outSubresourceIndex) const205 angle::Result TextureStorage11::getSubresourceIndex(const gl::Context *context,
206                                                     const gl::ImageIndex &index,
207                                                     UINT *outSubresourceIndex) const
208 {
209     UINT mipSlice    = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
210     UINT arraySlice  = static_cast<UINT>(index.hasLayer() ? index.getLayerIndex() : 0);
211     UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
212     ASSERT(subresource != std::numeric_limits<UINT>::max());
213     *outSubresourceIndex = subresource;
214     return angle::Result::Continue;
215 }
216 
getSRVForSampler(const gl::Context * context,const gl::TextureState & textureState,const gl::SamplerState & sampler,const d3d11::SharedSRV ** outSRV)217 angle::Result TextureStorage11::getSRVForSampler(const gl::Context *context,
218                                                  const gl::TextureState &textureState,
219                                                  const gl::SamplerState &sampler,
220                                                  const d3d11::SharedSRV **outSRV)
221 {
222     ANGLE_TRY(resolveTexture(context));
223     // Make sure to add the level offset for our tiny compressed texture workaround
224     const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel();
225     const bool swizzleRequired      = textureState.swizzleRequired();
226     const bool mipmapping           = gl::IsMipmapFiltered(sampler.getMinFilter());
227     unsigned int mipLevels =
228         mipmapping ? (textureState.getEffectiveMaxLevel() - effectiveBaseLevel + 1) : 1;
229 
230     // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
231     // which corresponds to GL level 0)
232     mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - effectiveBaseLevel);
233 
234     if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
235     {
236         ASSERT(!swizzleRequired);
237         ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
238     }
239 
240     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
241     {
242         // We must ensure that the level zero texture is in sync with mipped texture.
243         ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1));
244     }
245 
246     if (swizzleRequired)
247     {
248         verifySwizzleExists(textureState.getSwizzleState());
249     }
250 
251     // We drop the stencil when sampling from the SRV if three conditions hold:
252     // 1. the drop stencil workaround is enabled.
253     const bool emulateTinyStencilTextures =
254         mRenderer->getFeatures().emulateTinyStencilTextures.enabled;
255     // 2. this is a stencil texture.
256     const bool hasStencil = (mFormatInfo.format().stencilBits > 0);
257     // 3. the texture has a 1x1 or 2x2 mip.
258     const int effectiveTopLevel = effectiveBaseLevel + mipLevels - 1;
259     const bool hasSmallMips =
260         (getLevelWidth(effectiveTopLevel) <= 2 || getLevelHeight(effectiveTopLevel) <= 2);
261 
262     const bool useDropStencil = (emulateTinyStencilTextures && hasStencil && hasSmallMips);
263     const SamplerKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil);
264     if (useDropStencil)
265     {
266         // Ensure drop texture gets created.
267         DropStencil result = DropStencil::CREATED;
268         ANGLE_TRY(ensureDropStencilTexture(context, &result));
269 
270         // Clear the SRV cache if necessary.
271         // TODO(jmadill): Re-use find query result.
272         const auto srvEntry = mSrvCacheForSampler.find(key);
273         if (result == DropStencil::CREATED && srvEntry != mSrvCacheForSampler.end())
274         {
275             mSrvCacheForSampler.erase(key);
276         }
277     }
278 
279     ANGLE_TRY(getCachedOrCreateSRVForSampler(context, key, outSRV));
280 
281     return angle::Result::Continue;
282 }
283 
getCachedOrCreateSRVForSampler(const gl::Context * context,const SamplerKey & key,const d3d11::SharedSRV ** outSRV)284 angle::Result TextureStorage11::getCachedOrCreateSRVForSampler(const gl::Context *context,
285                                                                const SamplerKey &key,
286                                                                const d3d11::SharedSRV **outSRV)
287 {
288     auto iter = mSrvCacheForSampler.find(key);
289     if (iter != mSrvCacheForSampler.end())
290     {
291         *outSRV = &iter->second;
292         return angle::Result::Continue;
293     }
294 
295     const TextureHelper11 *texture = nullptr;
296     DXGI_FORMAT format             = DXGI_FORMAT_UNKNOWN;
297 
298     if (key.swizzle)
299     {
300         const auto &swizzleFormat =
301             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
302         ASSERT(!key.dropStencil || swizzleFormat.format().stencilBits == 0);
303         ANGLE_TRY(getSwizzleTexture(context, &texture));
304         format = swizzleFormat.srvFormat;
305     }
306     else if (key.dropStencil)
307     {
308         ASSERT(mDropStencilTexture.valid());
309         texture = &mDropStencilTexture;
310         format  = DXGI_FORMAT_R32_FLOAT;
311     }
312     else
313     {
314         ANGLE_TRY(getResource(context, &texture));
315         format = mFormatInfo.srvFormat;
316     }
317 
318     d3d11::SharedSRV srv;
319 
320     ANGLE_TRY(createSRVForSampler(context, key.baseLevel, key.mipLevels, format, *texture, &srv));
321 
322     const auto &insertIt = mSrvCacheForSampler.insert(std::make_pair(key, std::move(srv)));
323     *outSRV              = &insertIt.first->second;
324 
325     return angle::Result::Continue;
326 }
327 
getSRVLevel(const gl::Context * context,int mipLevel,bool blitSRV,const d3d11::SharedSRV ** outSRV)328 angle::Result TextureStorage11::getSRVLevel(const gl::Context *context,
329                                             int mipLevel,
330                                             bool blitSRV,
331                                             const d3d11::SharedSRV **outSRV)
332 {
333     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
334 
335     ANGLE_TRY(resolveTexture(context));
336     auto &levelSRVs      = (blitSRV) ? mLevelBlitSRVs : mLevelSRVs;
337     auto &otherLevelSRVs = (blitSRV) ? mLevelSRVs : mLevelBlitSRVs;
338 
339     if (!levelSRVs[mipLevel].valid())
340     {
341         // Only create a different SRV for blit if blit format is different from regular srv format
342         if (otherLevelSRVs[mipLevel].valid() && mFormatInfo.srvFormat == mFormatInfo.blitSRVFormat)
343         {
344             levelSRVs[mipLevel] = otherLevelSRVs[mipLevel].makeCopy();
345         }
346         else
347         {
348             const TextureHelper11 *resource = nullptr;
349             ANGLE_TRY(getResource(context, &resource));
350 
351             DXGI_FORMAT resourceFormat =
352                 blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat;
353             ANGLE_TRY(createSRVForSampler(context, mipLevel, 1, resourceFormat, *resource,
354                                           &levelSRVs[mipLevel]));
355         }
356     }
357 
358     *outSRV = &levelSRVs[mipLevel];
359     return angle::Result::Continue;
360 }
361 
getSRVLevels(const gl::Context * context,GLint baseLevel,GLint maxLevel,const d3d11::SharedSRV ** outSRV)362 angle::Result TextureStorage11::getSRVLevels(const gl::Context *context,
363                                              GLint baseLevel,
364                                              GLint maxLevel,
365                                              const d3d11::SharedSRV **outSRV)
366 {
367     ANGLE_TRY(resolveTexture(context));
368     unsigned int mipLevels = maxLevel - baseLevel + 1;
369 
370     // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
371     // which corresponds to GL level 0)
372     mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - baseLevel);
373 
374     if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
375     {
376         ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
377     }
378 
379     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
380     {
381         // We must ensure that the level zero texture is in sync with mipped texture.
382         ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1));
383     }
384 
385     // TODO(jmadill): Assert we don't need to drop stencil.
386 
387     SamplerKey key(baseLevel, mipLevels, false, false);
388     ANGLE_TRY(getCachedOrCreateSRVForSampler(context, key, outSRV));
389 
390     return angle::Result::Continue;
391 }
392 
getSRVForImage(const gl::Context * context,const gl::ImageUnit & imageUnit,const d3d11::SharedSRV ** outSRV)393 angle::Result TextureStorage11::getSRVForImage(const gl::Context *context,
394                                                const gl::ImageUnit &imageUnit,
395                                                const d3d11::SharedSRV **outSRV)
396 {
397     ANGLE_TRY(resolveTexture(context));
398     // TODO(Xinghua.cao@intel.com): Add solution to handle swizzle required.
399     ImageKey key(imageUnit.level, (imageUnit.layered == GL_TRUE), imageUnit.layer, imageUnit.access,
400                  imageUnit.format);
401     ANGLE_TRY(getCachedOrCreateSRVForImage(context, key, outSRV));
402     return angle::Result::Continue;
403 }
404 
getCachedOrCreateSRVForImage(const gl::Context * context,const ImageKey & key,const d3d11::SharedSRV ** outSRV)405 angle::Result TextureStorage11::getCachedOrCreateSRVForImage(const gl::Context *context,
406                                                              const ImageKey &key,
407                                                              const d3d11::SharedSRV **outSRV)
408 {
409     auto iter = mSrvCacheForImage.find(key);
410     if (iter != mSrvCacheForImage.end())
411     {
412         *outSRV = &iter->second;
413         return angle::Result::Continue;
414     }
415     const TextureHelper11 *texture = nullptr;
416     ANGLE_TRY(getResource(context, &texture));
417     DXGI_FORMAT format =
418         d3d11::Format::Get(key.format, mRenderer->getRenderer11DeviceCaps()).srvFormat;
419     d3d11::SharedSRV srv;
420     ANGLE_TRY(createSRVForImage(context, key.level, format, *texture, &srv));
421     const auto &insertIt = mSrvCacheForImage.insert(std::make_pair(key, std::move(srv)));
422     *outSRV              = &insertIt.first->second;
423     return angle::Result::Continue;
424 }
425 
getUAVForImage(const gl::Context * context,const gl::ImageUnit & imageUnit,const d3d11::SharedUAV ** outUAV)426 angle::Result TextureStorage11::getUAVForImage(const gl::Context *context,
427                                                const gl::ImageUnit &imageUnit,
428                                                const d3d11::SharedUAV **outUAV)
429 {
430     ANGLE_TRY(resolveTexture(context));
431     // TODO(Xinghua.cao@intel.com): Add solution to handle swizzle required.
432     ImageKey key(imageUnit.level, (imageUnit.layered == GL_TRUE), imageUnit.layer, imageUnit.access,
433                  imageUnit.format);
434     ANGLE_TRY(getCachedOrCreateUAVForImage(context, key, outUAV));
435     return angle::Result::Continue;
436 }
437 
getCachedOrCreateUAVForImage(const gl::Context * context,const ImageKey & key,const d3d11::SharedUAV ** outUAV)438 angle::Result TextureStorage11::getCachedOrCreateUAVForImage(const gl::Context *context,
439                                                              const ImageKey &key,
440                                                              const d3d11::SharedUAV **outUAV)
441 {
442     auto iter = mUavCacheForImage.find(key);
443     if (iter != mUavCacheForImage.end())
444     {
445         *outUAV = &iter->second;
446         return angle::Result::Continue;
447     }
448     const TextureHelper11 *texture = nullptr;
449     ANGLE_TRY(getResource(context, &texture));
450     DXGI_FORMAT format =
451         d3d11::Format::Get(key.format, mRenderer->getRenderer11DeviceCaps()).uavFormat;
452     d3d11::SharedUAV uav;
453     ANGLE_TRY(createUAVForImage(context, key.level, format, *texture, &uav));
454     const auto &insertIt = mUavCacheForImage.insert(std::make_pair(key, std::move(uav)));
455     *outUAV              = &insertIt.first->second;
456     return angle::Result::Continue;
457 }
458 
getFormatSet() const459 const d3d11::Format &TextureStorage11::getFormatSet() const
460 {
461     return mFormatInfo;
462 }
463 
generateSwizzles(const gl::Context * context,const gl::SwizzleState & swizzleTarget)464 angle::Result TextureStorage11::generateSwizzles(const gl::Context *context,
465                                                  const gl::SwizzleState &swizzleTarget)
466 {
467     ANGLE_TRY(resolveTexture(context));
468     for (int level = 0; level < getLevelCount(); level++)
469     {
470         // Check if the swizzle for this level is out of date
471         if (mSwizzleCache[level] != swizzleTarget)
472         {
473             // Need to re-render the swizzle for this level
474             const d3d11::SharedSRV *sourceSRV = nullptr;
475             ANGLE_TRY(getSRVLevel(context, level, true, &sourceSRV));
476 
477             const d3d11::RenderTargetView *destRTV;
478             ANGLE_TRY(getSwizzleRenderTarget(context, level, &destRTV));
479 
480             gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
481 
482             Blit11 *blitter = mRenderer->getBlitter();
483 
484             ANGLE_TRY(blitter->swizzleTexture(context, *sourceSRV, *destRTV, size, swizzleTarget));
485 
486             mSwizzleCache[level] = swizzleTarget;
487         }
488     }
489 
490     return angle::Result::Continue;
491 }
492 
markLevelDirty(int mipLevel)493 void TextureStorage11::markLevelDirty(int mipLevel)
494 {
495     if (mipLevel >= 0 && static_cast<size_t>(mipLevel) < mSwizzleCache.size())
496     {
497         // The default constructor of SwizzleState has GL_INVALID_INDEX for all channels which is
498         // not a valid swizzle combination
499         if (mSwizzleCache[mipLevel] != gl::SwizzleState())
500         {
501             // TODO(jmadill): Invalidate specific swizzle.
502             mRenderer->getStateManager()->invalidateSwizzles();
503             mSwizzleCache[mipLevel] = gl::SwizzleState();
504         }
505     }
506 
507     if (mDropStencilTexture.valid())
508     {
509         mDropStencilTexture.reset();
510     }
511 }
512 
markDirty()513 void TextureStorage11::markDirty()
514 {
515     for (size_t mipLevel = 0; mipLevel < mSwizzleCache.size(); ++mipLevel)
516     {
517         markLevelDirty(static_cast<int>(mipLevel));
518     }
519 }
520 
updateSubresourceLevel(const gl::Context * context,const TextureHelper11 & srcTexture,unsigned int sourceSubresource,const gl::ImageIndex & index,const gl::Box & copyArea)521 angle::Result TextureStorage11::updateSubresourceLevel(const gl::Context *context,
522                                                        const TextureHelper11 &srcTexture,
523                                                        unsigned int sourceSubresource,
524                                                        const gl::ImageIndex &index,
525                                                        const gl::Box &copyArea)
526 {
527     ASSERT(srcTexture.valid());
528 
529     ANGLE_TRY(resolveTexture(context));
530     const GLint level = index.getLevelIndex();
531 
532     markLevelDirty(level);
533 
534     gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
535 
536     bool fullCopy = copyArea.coversSameExtent(texSize);
537 
538     const TextureHelper11 *dstTexture = nullptr;
539 
540     // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
541     // should update the mipmapped texture, even if mapmaps are currently disabled.
542     if (level > 0 && mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
543     {
544         ANGLE_TRY(getMippedResource(context, &dstTexture));
545     }
546     else
547     {
548         ANGLE_TRY(getResource(context, &dstTexture));
549     }
550 
551     unsigned int dstSubresource = 0;
552     ANGLE_TRY(getSubresourceIndex(context, index, &dstSubresource));
553 
554     ASSERT(dstTexture->valid());
555 
556     const d3d11::DXGIFormatSize &dxgiFormatSizeInfo =
557         d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat);
558     if (!fullCopy && mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
559     {
560         // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
561         Blit11 *blitter = mRenderer->getBlitter();
562         return blitter->copyDepthStencil(context, srcTexture, sourceSubresource, copyArea, texSize,
563                                          *dstTexture, dstSubresource, copyArea, texSize, nullptr);
564     }
565 
566     D3D11_BOX srcBox;
567     srcBox.left = copyArea.x;
568     srcBox.top  = copyArea.y;
569     srcBox.right =
570         copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatSizeInfo.blockWidth);
571     srcBox.bottom =
572         copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatSizeInfo.blockHeight);
573     srcBox.front = copyArea.z;
574     srcBox.back  = copyArea.z + copyArea.depth;
575 
576     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
577 
578     deviceContext->CopySubresourceRegion(dstTexture->get(), dstSubresource, copyArea.x, copyArea.y,
579                                          copyArea.z, srcTexture.get(), sourceSubresource,
580                                          fullCopy ? nullptr : &srcBox);
581     return angle::Result::Continue;
582 }
583 
copySubresourceLevel(const gl::Context * context,const TextureHelper11 & dstTexture,unsigned int dstSubresource,const gl::ImageIndex & index,const gl::Box & region)584 angle::Result TextureStorage11::copySubresourceLevel(const gl::Context *context,
585                                                      const TextureHelper11 &dstTexture,
586                                                      unsigned int dstSubresource,
587                                                      const gl::ImageIndex &index,
588                                                      const gl::Box &region)
589 {
590     ASSERT(dstTexture.valid());
591 
592     ANGLE_TRY(resolveTexture(context));
593     const TextureHelper11 *srcTexture = nullptr;
594 
595     // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
596     // should update the mipmapped texture, even if mapmaps are currently disabled.
597     if (index.getLevelIndex() > 0 && mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
598     {
599         ANGLE_TRY(getMippedResource(context, &srcTexture));
600     }
601     else
602     {
603         ANGLE_TRY(getResource(context, &srcTexture));
604     }
605 
606     ASSERT(srcTexture->valid());
607 
608     unsigned int srcSubresource = 0;
609     ANGLE_TRY(getSubresourceIndex(context, index, &srcSubresource));
610 
611     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
612 
613     // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox
614     // should be nullptr.
615     D3D11_BOX srcBox;
616     D3D11_BOX *pSrcBox = nullptr;
617     if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
618     {
619         GLsizei width  = region.width;
620         GLsizei height = region.height;
621         d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, nullptr);
622 
623         // Keep srcbox as nullptr if we're dealing with tiny mips of compressed textures.
624         if (width == region.width && height == region.height)
625         {
626             // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless
627             // the source box is specified. This is okay, since we don't perform
628             // CopySubresourceRegion on depth/stencil textures on 9_3.
629             ASSERT(mFormatInfo.dsvFormat == DXGI_FORMAT_UNKNOWN);
630             srcBox.left   = region.x;
631             srcBox.right  = region.x + region.width;
632             srcBox.top    = region.y;
633             srcBox.bottom = region.y + region.height;
634             srcBox.front  = region.z;
635             srcBox.back   = region.z + region.depth;
636             pSrcBox       = &srcBox;
637         }
638     }
639 
640     deviceContext->CopySubresourceRegion(dstTexture.get(), dstSubresource, region.x, region.y,
641                                          region.z, srcTexture->get(), srcSubresource, pSrcBox);
642 
643     return angle::Result::Continue;
644 }
645 
generateMipmap(const gl::Context * context,const gl::ImageIndex & sourceIndex,const gl::ImageIndex & destIndex)646 angle::Result TextureStorage11::generateMipmap(const gl::Context *context,
647                                                const gl::ImageIndex &sourceIndex,
648                                                const gl::ImageIndex &destIndex)
649 {
650     ASSERT(sourceIndex.getLayerIndex() == destIndex.getLayerIndex());
651 
652     ANGLE_TRY(resolveTexture(context));
653     markLevelDirty(destIndex.getLevelIndex());
654 
655     RenderTargetD3D *source = nullptr;
656     ANGLE_TRY(getRenderTarget(context, sourceIndex, 0, &source));
657 
658     // dest will always have 0 since, we have just released the MS Texture struct
659     RenderTargetD3D *dest = nullptr;
660     ANGLE_TRY(getRenderTarget(context, destIndex, 0, &dest));
661 
662     RenderTarget11 *srcRT11                = GetAs<RenderTarget11>(source);
663     RenderTarget11 *dstRT11                = GetAs<RenderTarget11>(dest);
664     const d3d11::SharedSRV &sourceSRV      = srcRT11->getBlitShaderResourceView(context);
665     const d3d11::RenderTargetView &destRTV = dstRT11->getRenderTargetView();
666 
667     gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
668     gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth());
669 
670     gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth());
671     gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
672 
673     Blit11 *blitter = mRenderer->getBlitter();
674     const gl::InternalFormat &sourceInternalFormat =
675         gl::GetSizedInternalFormatInfo(source->getInternalFormat());
676     GLenum format = sourceInternalFormat.format;
677     GLenum type   = sourceInternalFormat.type;
678     return blitter->copyTexture(context, sourceSRV, sourceArea, sourceSize, format, destRTV,
679                                 destArea, destSize, nullptr, format, type, GL_LINEAR, false, false,
680                                 false);
681 }
682 
verifySwizzleExists(const gl::SwizzleState & swizzleState)683 void TextureStorage11::verifySwizzleExists(const gl::SwizzleState &swizzleState)
684 {
685     for (unsigned int level = 0; level < mMipLevels; level++)
686     {
687         ASSERT(mSwizzleCache[level] == swizzleState);
688     }
689 }
690 
clearSRVCache()691 void TextureStorage11::clearSRVCache()
692 {
693     markDirty();
694     mSrvCacheForSampler.clear();
695 
696     for (size_t level = 0; level < mLevelSRVs.size(); level++)
697     {
698         mLevelSRVs[level].reset();
699         mLevelBlitSRVs[level].reset();
700     }
701 }
702 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)703 angle::Result TextureStorage11::copyToStorage(const gl::Context *context,
704                                               TextureStorage *destStorage)
705 {
706     ASSERT(destStorage);
707 
708     ANGLE_TRY(resolveTexture(context));
709     const TextureHelper11 *sourceResouce = nullptr;
710     ANGLE_TRY(getResource(context, &sourceResouce));
711 
712     TextureStorage11 *dest11            = GetAs<TextureStorage11>(destStorage);
713     const TextureHelper11 *destResource = nullptr;
714     ANGLE_TRY(dest11->getResource(context, &destResource));
715 
716     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
717     immediateContext->CopyResource(destResource->get(), sourceResouce->get());
718 
719     dest11->markDirty();
720 
721     return angle::Result::Continue;
722 }
723 
invalidateTextures()724 void TextureStorage11::invalidateTextures()
725 {
726     mRenderer->getStateManager()->invalidateTexturesAndSamplers();
727 }
728 
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)729 angle::Result TextureStorage11::setData(const gl::Context *context,
730                                         const gl::ImageIndex &index,
731                                         ImageD3D *image,
732                                         const gl::Box *destBox,
733                                         GLenum type,
734                                         const gl::PixelUnpackState &unpack,
735                                         const uint8_t *pixelData)
736 {
737     ASSERT(!image->isDirty());
738 
739     ANGLE_TRY(resolveTexture(context));
740     markLevelDirty(index.getLevelIndex());
741 
742     const TextureHelper11 *resource = nullptr;
743     ANGLE_TRY(getResource(context, &resource));
744     ASSERT(resource && resource->valid());
745 
746     UINT destSubresource = 0;
747     ANGLE_TRY(getSubresourceIndex(context, index, &destSubresource));
748 
749     const gl::InternalFormat &internalFormatInfo =
750         gl::GetInternalFormatInfo(image->getInternalFormat(), type);
751 
752     gl::Box levelBox(0, 0, 0, getLevelWidth(index.getLevelIndex()),
753                      getLevelHeight(index.getLevelIndex()), getLevelDepth(index.getLevelIndex()));
754     bool fullUpdate = (destBox == nullptr || *destBox == levelBox);
755     ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate);
756 
757     // TODO(jmadill): Handle compressed formats
758     // Compressed formats have different load syntax, so we'll have to handle them with slightly
759     // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData
760     // with compressed formats in the calling logic.
761     ASSERT(!internalFormatInfo.compressed);
762 
763     Context11 *context11 = GetImplAs<Context11>(context);
764 
765     const int width    = destBox ? destBox->width : static_cast<int>(image->getWidth());
766     const int height   = destBox ? destBox->height : static_cast<int>(image->getHeight());
767     const int depth    = destBox ? destBox->depth : static_cast<int>(image->getDepth());
768     GLuint srcRowPitch = 0;
769     ANGLE_CHECK_GL_MATH(context11,
770                         internalFormatInfo.computeRowPitch(type, width, unpack.alignment,
771                                                            unpack.rowLength, &srcRowPitch));
772     GLuint srcDepthPitch = 0;
773     ANGLE_CHECK_GL_MATH(context11, internalFormatInfo.computeDepthPitch(
774                                        height, unpack.imageHeight, srcRowPitch, &srcDepthPitch));
775     GLuint srcSkipBytes = 0;
776     ANGLE_CHECK_GL_MATH(
777         context11, internalFormatInfo.computeSkipBytes(type, srcRowPitch, srcDepthPitch, unpack,
778                                                        index.usesTex3D(), &srcSkipBytes));
779 
780     const d3d11::Format &d3d11Format =
781         d3d11::Format::Get(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
782     const d3d11::DXGIFormatSize &dxgiFormatInfo =
783         d3d11::GetDXGIFormatSizeInfo(d3d11Format.texFormat);
784 
785     const size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
786 
787     UINT bufferRowPitch   = static_cast<unsigned int>(outputPixelSize) * width;
788     UINT bufferDepthPitch = bufferRowPitch * height;
789 
790     const size_t neededSize               = bufferDepthPitch * depth;
791     angle::MemoryBuffer *conversionBuffer = nullptr;
792     const uint8_t *data                   = nullptr;
793 
794     LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(type);
795     if (loadFunctionInfo.requiresConversion)
796     {
797         ANGLE_TRY(mRenderer->getScratchMemoryBuffer(context11, neededSize, &conversionBuffer));
798         loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch,
799                                       srcDepthPitch, conversionBuffer->data(), bufferRowPitch,
800                                       bufferDepthPitch);
801         data = conversionBuffer->data();
802     }
803     else
804     {
805         data             = pixelData + srcSkipBytes;
806         bufferRowPitch   = srcRowPitch;
807         bufferDepthPitch = srcDepthPitch;
808     }
809 
810     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
811 
812     if (!fullUpdate)
813     {
814         ASSERT(destBox);
815 
816         D3D11_BOX destD3DBox;
817         destD3DBox.left   = destBox->x;
818         destD3DBox.right  = destBox->x + destBox->width;
819         destD3DBox.top    = destBox->y;
820         destD3DBox.bottom = destBox->y + destBox->height;
821         destD3DBox.front  = destBox->z;
822         destD3DBox.back   = destBox->z + destBox->depth;
823 
824         immediateContext->UpdateSubresource(resource->get(), destSubresource, &destD3DBox, data,
825                                             bufferRowPitch, bufferDepthPitch);
826     }
827     else
828     {
829         immediateContext->UpdateSubresource(resource->get(), destSubresource, nullptr, data,
830                                             bufferRowPitch, bufferDepthPitch);
831     }
832 
833     return angle::Result::Continue;
834 }
835 
ensureDropStencilTexture(const gl::Context * context,TextureStorage11::DropStencil * dropStencilOut)836 angle::Result TextureStorage11::ensureDropStencilTexture(
837     const gl::Context *context,
838     TextureStorage11::DropStencil *dropStencilOut)
839 {
840     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
841     return angle::Result::Stop;
842 }
843 
initDropStencilTexture(const gl::Context * context,const gl::ImageIndexIterator & it)844 angle::Result TextureStorage11::initDropStencilTexture(const gl::Context *context,
845                                                        const gl::ImageIndexIterator &it)
846 {
847     const TextureHelper11 *sourceTexture = nullptr;
848     ANGLE_TRY(getResource(context, &sourceTexture));
849 
850     gl::ImageIndexIterator itCopy = it;
851 
852     while (itCopy.hasNext())
853     {
854         gl::ImageIndex index = itCopy.next();
855         gl::Box wholeArea(0, 0, 0, getLevelWidth(index.getLevelIndex()),
856                           getLevelHeight(index.getLevelIndex()), 1);
857         gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
858 
859         UINT subresource = 0;
860         ANGLE_TRY(getSubresourceIndex(context, index, &subresource));
861 
862         ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(
863             context, *sourceTexture, subresource, wholeArea, wholeSize, mDropStencilTexture,
864             subresource, wholeArea, wholeSize, nullptr));
865     }
866 
867     return angle::Result::Continue;
868 }
869 
resolveTextureHelper(const gl::Context * context,const TextureHelper11 & texture)870 angle::Result TextureStorage11::resolveTextureHelper(const gl::Context *context,
871                                                      const TextureHelper11 &texture)
872 {
873     UINT subresourceIndexSS;
874     ANGLE_TRY(getSubresourceIndex(context, mMSTexInfo->indexSS, &subresourceIndexSS));
875     UINT subresourceIndexMS;
876     ANGLE_TRY(getSubresourceIndex(context, mMSTexInfo->indexMS, &subresourceIndexMS));
877     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
878     const TextureHelper11 *resource    = nullptr;
879     ANGLE_TRY(mMSTexInfo->msTex->getResource(context, &resource));
880     deviceContext->ResolveSubresource(texture.get(), subresourceIndexSS, resource->get(),
881                                       subresourceIndexMS, texture.getFormat());
882     mMSTexInfo->msTextureNeedsResolve = false;
883     return angle::Result::Continue;
884 }
885 
releaseMultisampledTexStorageForLevel(size_t level)886 angle::Result TextureStorage11::releaseMultisampledTexStorageForLevel(size_t level)
887 {
888     if (mMSTexInfo && mMSTexInfo->indexSS.getLevelIndex() == static_cast<int>(level))
889     {
890         mMSTexInfo->msTex.reset();
891         onStateChange(angle::SubjectMessage::ContentsChanged);
892     }
893     return angle::Result::Continue;
894 }
895 
getRenderToTextureSamples() const896 GLsizei TextureStorage11::getRenderToTextureSamples() const
897 {
898     if (mMSTexInfo)
899     {
900         return mMSTexInfo->samples;
901     }
902     return 0;
903 }
904 
findMultisampledRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const905 angle::Result TextureStorage11::findMultisampledRenderTarget(const gl::Context *context,
906                                                              const gl::ImageIndex &index,
907                                                              GLsizei samples,
908                                                              RenderTargetD3D **outRT) const
909 {
910     const int level = index.getLevelIndex();
911     if (!mMSTexInfo || level != mMSTexInfo->indexSS.getLevelIndex() ||
912         samples != mMSTexInfo->samples || !mMSTexInfo->msTex)
913     {
914         *outRT = nullptr;
915         return angle::Result::Continue;
916     }
917     RenderTargetD3D *rt;
918     ANGLE_TRY(mMSTexInfo->msTex->findRenderTarget(context, mMSTexInfo->indexMS, samples, &rt));
919     *outRT = rt;
920     return angle::Result::Continue;
921 }
922 
getMultisampledRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)923 angle::Result TextureStorage11::getMultisampledRenderTarget(const gl::Context *context,
924                                                             const gl::ImageIndex &index,
925                                                             GLsizei samples,
926                                                             RenderTargetD3D **outRT)
927 {
928     const int level = index.getLevelIndex();
929     if (!mMSTexInfo || level != mMSTexInfo->indexSS.getLevelIndex() ||
930         samples != mMSTexInfo->samples || !mMSTexInfo->msTex)
931     {
932         // if mMSTexInfo already exists, then we want to resolve and release it
933         // since the mMSTexInfo must be for a different sample count or level
934         ANGLE_TRY(resolveTexture(context));
935 
936         // Now we can create a new object for the correct sample and level
937         GLsizei width         = getLevelWidth(level);
938         GLsizei height        = getLevelHeight(level);
939         GLenum internalFormat = mFormatInfo.internalFormat;
940         std::unique_ptr<TextureStorage11_2DMultisample> texMS(
941             GetAs<TextureStorage11_2DMultisample>(mRenderer->createTextureStorage2DMultisample(
942                 internalFormat, width, height, level, samples, true)));
943 
944         // make sure multisample object has the blitted information.
945         gl::Rectangle area(0, 0, width, height);
946         RenderTargetD3D *readRenderTarget = nullptr;
947         // use incoming index here since the index will correspond to the single sampled texture
948         ANGLE_TRY(getRenderTarget(context, index, 0, &readRenderTarget));
949         gl::ImageIndex indexMS            = gl::ImageIndex::Make2DMultisample();
950         RenderTargetD3D *drawRenderTarget = nullptr;
951         ANGLE_TRY(texMS->getRenderTarget(context, indexMS, samples, &drawRenderTarget));
952 
953         // blit SS -> MS
954         // mask: GL_COLOR_BUFFER_BIT, filter: GL_NEAREST
955         ANGLE_TRY(mRenderer->blitRenderbufferRect(context, area, area, readRenderTarget,
956                                                   drawRenderTarget, GL_NEAREST, nullptr, true,
957                                                   false, false));
958         mMSTexInfo = std::make_unique<MultisampledRenderToTextureInfo>(samples, index, indexMS);
959         mMSTexInfo->msTex = std::move(texMS);
960     }
961     RenderTargetD3D *rt;
962     ANGLE_TRY(mMSTexInfo->msTex->getRenderTarget(context, mMSTexInfo->indexMS, samples, &rt));
963     // By returning the multisampled render target to the caller, the render target
964     // is expected to be changed so we need to resolve to a single sampled texture
965     // next time resolveTexture is called.
966     mMSTexInfo->msTextureNeedsResolve = true;
967     *outRT                            = rt;
968     return angle::Result::Continue;
969 }
970 
TextureStorage11_2D(Renderer11 * renderer,SwapChain11 * swapchain)971 TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
972     : TextureStorage11(renderer,
973                        D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
974                        0,
975                        swapchain->getRenderTargetInternalFormat()),
976       mTexture(swapchain->getOffscreenTexture()),
977       mLevelZeroTexture(),
978       mLevelZeroRenderTarget(nullptr),
979       mUseLevelZeroTexture(false),
980       mSwizzleTexture()
981 {
982     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
983     {
984         mAssociatedImages[i] = nullptr;
985         mRenderTarget[i]     = nullptr;
986     }
987 
988     D3D11_TEXTURE2D_DESC texDesc;
989     mTexture.getDesc(&texDesc);
990     mMipLevels     = texDesc.MipLevels;
991     mTextureWidth  = texDesc.Width;
992     mTextureHeight = texDesc.Height;
993     mTextureDepth  = 1;
994     mHasKeyedMutex = (texDesc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
995 }
996 
TextureStorage11_2D(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,int levels,bool hintLevelZeroOnly)997 TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer,
998                                          GLenum internalformat,
999                                          bool renderTarget,
1000                                          GLsizei width,
1001                                          GLsizei height,
1002                                          int levels,
1003                                          bool hintLevelZeroOnly)
1004     : TextureStorage11(
1005           renderer,
1006           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
1007           GetTextureMiscFlags(internalformat,
1008                               renderer->getRenderer11DeviceCaps(),
1009                               renderTarget,
1010                               levels),
1011           internalformat),
1012       mTexture(),
1013       mHasKeyedMutex(false),
1014       mLevelZeroTexture(),
1015       mLevelZeroRenderTarget(nullptr),
1016       mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
1017       mSwizzleTexture()
1018 {
1019     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1020     {
1021         mAssociatedImages[i] = nullptr;
1022         mRenderTarget[i]     = nullptr;
1023     }
1024 
1025     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
1026     mMipLevels     = mTopLevel + levels;
1027     mTextureWidth  = width;
1028     mTextureHeight = height;
1029     mTextureDepth  = 1;
1030 
1031     // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
1032     ASSERT(!mUseLevelZeroTexture || mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
1033 }
1034 
onDestroy(const gl::Context * context)1035 angle::Result TextureStorage11_2D::onDestroy(const gl::Context *context)
1036 {
1037     for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1038     {
1039         if (mAssociatedImages[i] != nullptr)
1040         {
1041             mAssociatedImages[i]->verifyAssociatedStorageValid(this);
1042 
1043             // We must let the Images recover their data before we delete it from the
1044             // TextureStorage.
1045             ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
1046         }
1047     }
1048 
1049     if (mHasKeyedMutex)
1050     {
1051         // If the keyed mutex is released that will unbind it and cause the state cache to become
1052         // desynchronized.
1053         mRenderer->getStateManager()->invalidateBoundViews();
1054     }
1055 
1056     return angle::Result::Continue;
1057 }
1058 
~TextureStorage11_2D()1059 TextureStorage11_2D::~TextureStorage11_2D() {}
1060 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1061 angle::Result TextureStorage11_2D::copyToStorage(const gl::Context *context,
1062                                                  TextureStorage *destStorage)
1063 {
1064     ASSERT(destStorage);
1065 
1066     TextureStorage11_2D *dest11           = GetAs<TextureStorage11_2D>(destStorage);
1067     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
1068 
1069     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
1070     {
1071         // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
1072         // corresponding textures in destStorage.
1073         if (mTexture.valid())
1074         {
1075             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
1076 
1077             const TextureHelper11 *destResource = nullptr;
1078             ANGLE_TRY(dest11->getResource(context, &destResource));
1079 
1080             immediateContext->CopyResource(destResource->get(), mTexture.get());
1081         }
1082 
1083         if (mLevelZeroTexture.valid())
1084         {
1085             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
1086 
1087             const TextureHelper11 *destResource = nullptr;
1088             ANGLE_TRY(dest11->getResource(context, &destResource));
1089 
1090             immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
1091         }
1092 
1093         return angle::Result::Continue;
1094     }
1095 
1096     const TextureHelper11 *sourceResouce = nullptr;
1097     ANGLE_TRY(getResource(context, &sourceResouce));
1098 
1099     const TextureHelper11 *destResource = nullptr;
1100     ANGLE_TRY(dest11->getResource(context, &destResource));
1101 
1102     immediateContext->CopyResource(destResource->get(), sourceResouce->get());
1103     dest11->markDirty();
1104 
1105     return angle::Result::Continue;
1106 }
1107 
useLevelZeroWorkaroundTexture(const gl::Context * context,bool useLevelZeroTexture)1108 angle::Result TextureStorage11_2D::useLevelZeroWorkaroundTexture(const gl::Context *context,
1109                                                                  bool useLevelZeroTexture)
1110 {
1111     if (useLevelZeroTexture && mMipLevels > 1)
1112     {
1113         if (!mUseLevelZeroTexture && mTexture.valid())
1114         {
1115             ANGLE_TRY(ensureTextureExists(context, 1));
1116 
1117             // Pull data back from the mipped texture if necessary.
1118             ASSERT(mLevelZeroTexture.valid());
1119             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1120             deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(), 0, 0, 0, 0,
1121                                                  mTexture.get(), 0, nullptr);
1122         }
1123 
1124         mUseLevelZeroTexture = true;
1125     }
1126     else
1127     {
1128         if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
1129         {
1130             ANGLE_TRY(ensureTextureExists(context, mMipLevels));
1131 
1132             // Pull data back from the level zero texture if necessary.
1133             ASSERT(mTexture.valid());
1134             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1135             deviceContext->CopySubresourceRegion(mTexture.get(), 0, 0, 0, 0,
1136                                                  mLevelZeroTexture.get(), 0, nullptr);
1137         }
1138 
1139         mUseLevelZeroTexture = false;
1140     }
1141 
1142     return angle::Result::Continue;
1143 }
1144 
associateImage(Image11 * image,const gl::ImageIndex & index)1145 void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
1146 {
1147     const GLint level = index.getLevelIndex();
1148 
1149     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1150     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1151     {
1152         mAssociatedImages[level] = image;
1153     }
1154 }
1155 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)1156 void TextureStorage11_2D::verifyAssociatedImageValid(const gl::ImageIndex &index,
1157                                                      Image11 *expectedImage)
1158 {
1159     const GLint level = index.getLevelIndex();
1160 
1161     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1162     // This validation check should never return false. It means the Image/TextureStorage
1163     // association is broken.
1164     ASSERT(mAssociatedImages[level] == expectedImage);
1165 }
1166 
1167 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)1168 void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
1169 {
1170     const GLint level = index.getLevelIndex();
1171 
1172     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1173     ASSERT(mAssociatedImages[level] == expectedImage);
1174     mAssociatedImages[level] = nullptr;
1175 }
1176 
1177 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
1178 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)1179 angle::Result TextureStorage11_2D::releaseAssociatedImage(const gl::Context *context,
1180                                                           const gl::ImageIndex &index,
1181                                                           Image11 *incomingImage)
1182 {
1183     const GLint level = index.getLevelIndex();
1184 
1185     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1186 
1187     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1188     {
1189         // No need to let the old Image recover its data, if it is also the incoming Image.
1190         if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
1191         {
1192             // Ensure that the Image is still associated with this TextureStorage.
1193             mAssociatedImages[level]->verifyAssociatedStorageValid(this);
1194 
1195             // Force the image to recover from storage before its data is overwritten.
1196             // This will reset mAssociatedImages[level] to nullptr too.
1197             ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
1198         }
1199     }
1200 
1201     return angle::Result::Continue;
1202 }
1203 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1204 angle::Result TextureStorage11_2D::getResource(const gl::Context *context,
1205                                                const TextureHelper11 **outResource)
1206 {
1207     if (mUseLevelZeroTexture && mMipLevels > 1)
1208     {
1209         ANGLE_TRY(ensureTextureExists(context, 1));
1210 
1211         *outResource = &mLevelZeroTexture;
1212         return angle::Result::Continue;
1213     }
1214 
1215     ANGLE_TRY(ensureTextureExists(context, mMipLevels));
1216 
1217     *outResource = &mTexture;
1218     return angle::Result::Continue;
1219 }
1220 
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)1221 angle::Result TextureStorage11_2D::getMippedResource(const gl::Context *context,
1222                                                      const TextureHelper11 **outResource)
1223 {
1224     // This shouldn't be called unless the zero max LOD workaround is active.
1225     ASSERT(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
1226 
1227     ANGLE_TRY(ensureTextureExists(context, mMipLevels));
1228 
1229     *outResource = &mTexture;
1230     return angle::Result::Continue;
1231 }
1232 
ensureTextureExists(const gl::Context * context,int mipLevels)1233 angle::Result TextureStorage11_2D::ensureTextureExists(const gl::Context *context, int mipLevels)
1234 {
1235     // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
1236     ANGLE_TRY(resolveTexture(context));
1237     bool useLevelZeroTexture = mRenderer->getFeatures().zeroMaxLodWorkaround.enabled
1238                                    ? (mipLevels == 1) && (mMipLevels > 1)
1239                                    : false;
1240     TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
1241 
1242     // if the width or height is not positive this should be treated as an incomplete texture
1243     // we handle that here by skipping the d3d texture creation
1244     if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
1245     {
1246         ASSERT(mipLevels > 0);
1247 
1248         D3D11_TEXTURE2D_DESC desc;
1249         desc.Width              = mTextureWidth;  // Compressed texture size constraints?
1250         desc.Height             = mTextureHeight;
1251         desc.MipLevels          = mipLevels;
1252         desc.ArraySize          = 1;
1253         desc.Format             = mFormatInfo.texFormat;
1254         desc.SampleDesc.Count   = 1;
1255         desc.SampleDesc.Quality = 0;
1256         desc.Usage              = D3D11_USAGE_DEFAULT;
1257         desc.BindFlags          = getBindFlags();
1258         desc.CPUAccessFlags     = 0;
1259         desc.MiscFlags          = getMiscFlags();
1260 
1261         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
1262                                              outputTexture));
1263 
1264         if (useLevelZeroTexture)
1265         {
1266             outputTexture->setDebugName("TexStorage2D.Level0Texture");
1267         }
1268         else
1269         {
1270             outputTexture->setDebugName("TexStorage2D.Texture");
1271         }
1272     }
1273 
1274     return angle::Result::Continue;
1275 }
1276 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const1277 angle::Result TextureStorage11_2D::findRenderTarget(const gl::Context *context,
1278                                                     const gl::ImageIndex &index,
1279                                                     GLsizei samples,
1280                                                     RenderTargetD3D **outRT) const
1281 {
1282     ASSERT(!index.hasLayer());
1283 
1284     const int level = index.getLevelIndex();
1285     ASSERT(level >= 0 && level < getLevelCount());
1286 
1287     bool needMS = samples > 0;
1288     if (needMS)
1289     {
1290         return findMultisampledRenderTarget(context, index, samples, outRT);
1291     }
1292 
1293     ASSERT(outRT);
1294     if (mRenderTarget[level])
1295     {
1296         *outRT = mRenderTarget[level].get();
1297         return angle::Result::Continue;
1298     }
1299 
1300     if (mUseLevelZeroTexture)
1301     {
1302         ASSERT(level == 0);
1303         *outRT = mLevelZeroRenderTarget.get();
1304         return angle::Result::Continue;
1305     }
1306 
1307     *outRT = nullptr;
1308     return angle::Result::Continue;
1309 }
1310 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)1311 angle::Result TextureStorage11_2D::getRenderTarget(const gl::Context *context,
1312                                                    const gl::ImageIndex &index,
1313                                                    GLsizei samples,
1314                                                    RenderTargetD3D **outRT)
1315 {
1316     ASSERT(!index.hasLayer());
1317 
1318     const int level = index.getLevelIndex();
1319     ASSERT(level >= 0 && level < getLevelCount());
1320 
1321     bool needMS = samples > 0;
1322     if (needMS)
1323     {
1324         return getMultisampledRenderTarget(context, index, samples, outRT);
1325     }
1326     else
1327     {
1328         ANGLE_TRY(resolveTexture(context));
1329     }
1330 
1331     // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of
1332     // the GLES 2.0 spec, page 113 of version 2.0.25). Other parts of TextureStorage11_2D could
1333     // create RTVs on non-zero levels of the texture (e.g. generateMipmap).
1334     // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the
1335     // individual levels of the texture, so methods like generateMipmap can't do anything useful
1336     // with non-zero-level RTVs. Therefore if level > 0 on 9_3 then there's almost certainly
1337     // something wrong.
1338     ASSERT(
1339         !(mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0));
1340     ASSERT(outRT);
1341     if (mRenderTarget[level])
1342     {
1343         *outRT = mRenderTarget[level].get();
1344         return angle::Result::Continue;
1345     }
1346 
1347     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
1348     {
1349         ASSERT(level == 0);
1350         ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
1351     }
1352 
1353     const TextureHelper11 *texture = nullptr;
1354     ANGLE_TRY(getResource(context, &texture));
1355 
1356     const d3d11::SharedSRV *srv = nullptr;
1357     ANGLE_TRY(getSRVLevel(context, level, false, &srv));
1358 
1359     const d3d11::SharedSRV *blitSRV = nullptr;
1360     ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
1361 
1362     Context11 *context11 = GetImplAs<Context11>(context);
1363 
1364     if (mUseLevelZeroTexture)
1365     {
1366         if (!mLevelZeroRenderTarget)
1367         {
1368             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1369             rtvDesc.Format             = mFormatInfo.rtvFormat;
1370             rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
1371             rtvDesc.Texture2D.MipSlice = mTopLevel + level;
1372 
1373             d3d11::RenderTargetView rtv;
1374             ANGLE_TRY(
1375                 mRenderer->allocateResource(context11, rtvDesc, mLevelZeroTexture.get(), &rtv));
1376             rtv.setDebugName("TexStorage2D.Level0RTV");
1377 
1378             mLevelZeroRenderTarget.reset(new TextureRenderTarget11(
1379                 std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
1380                 mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
1381                 getLevelHeight(level), 1, 0));
1382         }
1383 
1384         *outRT = mLevelZeroRenderTarget.get();
1385         return angle::Result::Continue;
1386     }
1387 
1388     if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
1389     {
1390         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1391         rtvDesc.Format             = mFormatInfo.rtvFormat;
1392         rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
1393         rtvDesc.Texture2D.MipSlice = mTopLevel + level;
1394 
1395         d3d11::RenderTargetView rtv;
1396         ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
1397         rtv.setDebugName("TexStorage2D.RTV");
1398 
1399         mRenderTarget[level].reset(new TextureRenderTarget11(
1400             std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
1401             getLevelWidth(level), getLevelHeight(level), 1, 0));
1402 
1403         *outRT = mRenderTarget[level].get();
1404         return angle::Result::Continue;
1405     }
1406 
1407     ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
1408 
1409     D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
1410     dsvDesc.Format             = mFormatInfo.dsvFormat;
1411     dsvDesc.ViewDimension      = D3D11_DSV_DIMENSION_TEXTURE2D;
1412     dsvDesc.Texture2D.MipSlice = mTopLevel + level;
1413     dsvDesc.Flags              = 0;
1414 
1415     d3d11::DepthStencilView dsv;
1416     ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
1417     dsv.setDebugName("TexStorage2D.DSV");
1418 
1419     mRenderTarget[level].reset(new TextureRenderTarget11(
1420         std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
1421         getLevelWidth(level), getLevelHeight(level), 1, 0));
1422 
1423     *outRT = mRenderTarget[level].get();
1424     return angle::Result::Continue;
1425 }
1426 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1427 angle::Result TextureStorage11_2D::createSRVForSampler(const gl::Context *context,
1428                                                        int baseLevel,
1429                                                        int mipLevels,
1430                                                        DXGI_FORMAT format,
1431                                                        const TextureHelper11 &texture,
1432                                                        d3d11::SharedSRV *outSRV)
1433 {
1434     ASSERT(outSRV);
1435 
1436     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1437     srvDesc.Format                    = format;
1438     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
1439     srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
1440     srvDesc.Texture2D.MipLevels       = mipLevels;
1441 
1442     const TextureHelper11 *srvTexture = &texture;
1443 
1444     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
1445     {
1446         ASSERT(mTopLevel == 0);
1447         ASSERT(baseLevel == 0);
1448         // This code also assumes that the incoming texture equals either mLevelZeroTexture or
1449         // mTexture.
1450 
1451         if (mipLevels == 1 && mMipLevels > 1)
1452         {
1453             // We must use a SRV on the level-zero-only texture.
1454             ANGLE_TRY(ensureTextureExists(context, 1));
1455             srvTexture = &mLevelZeroTexture;
1456         }
1457         else
1458         {
1459             ASSERT(mipLevels == static_cast<int>(mMipLevels));
1460             ASSERT(mTexture.valid() && texture == mTexture);
1461             srvTexture = &mTexture;
1462         }
1463     }
1464 
1465     ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, srvTexture->get(),
1466                                           outSRV));
1467     outSRV->setDebugName("TexStorage2D.SRV");
1468 
1469     return angle::Result::Continue;
1470 }
1471 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1472 angle::Result TextureStorage11_2D::createSRVForImage(const gl::Context *context,
1473                                                      int level,
1474                                                      DXGI_FORMAT format,
1475                                                      const TextureHelper11 &texture,
1476                                                      d3d11::SharedSRV *outSRV)
1477 {
1478     ASSERT(outSRV);
1479     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1480     srvDesc.Format                    = format;
1481     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
1482     srvDesc.Texture2D.MostDetailedMip = mTopLevel + level;
1483     srvDesc.Texture2D.MipLevels       = 1;
1484     ANGLE_TRY(
1485         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
1486     outSRV->setDebugName("TexStorage2D.SRVForImage");
1487     return angle::Result::Continue;
1488 }
1489 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)1490 angle::Result TextureStorage11_2D::createUAVForImage(const gl::Context *context,
1491                                                      int level,
1492                                                      DXGI_FORMAT format,
1493                                                      const TextureHelper11 &texture,
1494                                                      d3d11::SharedUAV *outUAV)
1495 {
1496     ASSERT(outUAV);
1497     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
1498     uavDesc.Format             = format;
1499     uavDesc.ViewDimension      = D3D11_UAV_DIMENSION_TEXTURE2D;
1500     uavDesc.Texture2D.MipSlice = mTopLevel + level;
1501     ANGLE_TRY(
1502         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
1503     outUAV->setDebugName("TexStorage2D.UAVForImage");
1504     return angle::Result::Continue;
1505 }
1506 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)1507 angle::Result TextureStorage11_2D::getSwizzleTexture(const gl::Context *context,
1508                                                      const TextureHelper11 **outTexture)
1509 {
1510     ASSERT(outTexture);
1511 
1512     if (!mSwizzleTexture.valid())
1513     {
1514         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
1515 
1516         D3D11_TEXTURE2D_DESC desc;
1517         desc.Width              = mTextureWidth;
1518         desc.Height             = mTextureHeight;
1519         desc.MipLevels          = mMipLevels;
1520         desc.ArraySize          = 1;
1521         desc.Format             = format.texFormat;
1522         desc.SampleDesc.Count   = 1;
1523         desc.SampleDesc.Quality = 0;
1524         desc.Usage              = D3D11_USAGE_DEFAULT;
1525         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1526         desc.CPUAccessFlags     = 0;
1527         desc.MiscFlags          = 0;
1528 
1529         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
1530                                              &mSwizzleTexture));
1531         mSwizzleTexture.setDebugName("TexStorage2D.SwizzleTexture");
1532     }
1533 
1534     *outTexture = &mSwizzleTexture;
1535     return angle::Result::Continue;
1536 }
1537 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)1538 angle::Result TextureStorage11_2D::getSwizzleRenderTarget(const gl::Context *context,
1539                                                           int mipLevel,
1540                                                           const d3d11::RenderTargetView **outRTV)
1541 {
1542     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
1543     ASSERT(outRTV);
1544 
1545     if (!mSwizzleRenderTargets[mipLevel].valid())
1546     {
1547         const TextureHelper11 *swizzleTexture = nullptr;
1548         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
1549 
1550         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1551         rtvDesc.Format =
1552             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
1553         rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
1554         rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
1555 
1556         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
1557                                               mSwizzleTexture.get(),
1558                                               &mSwizzleRenderTargets[mipLevel]));
1559     }
1560 
1561     *outRTV = &mSwizzleRenderTargets[mipLevel];
1562     return angle::Result::Continue;
1563 }
1564 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)1565 angle::Result TextureStorage11_2D::ensureDropStencilTexture(const gl::Context *context,
1566                                                             DropStencil *dropStencilOut)
1567 {
1568     if (mDropStencilTexture.valid())
1569     {
1570         *dropStencilOut = DropStencil::ALREADY_EXISTS;
1571         return angle::Result::Continue;
1572     }
1573 
1574     D3D11_TEXTURE2D_DESC dropDesc = {};
1575     dropDesc.ArraySize            = 1;
1576     dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
1577     dropDesc.CPUAccessFlags       = 0;
1578     dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
1579     dropDesc.Height               = mTextureHeight;
1580     dropDesc.MipLevels            = mMipLevels;
1581     dropDesc.MiscFlags            = 0;
1582     dropDesc.SampleDesc.Count     = 1;
1583     dropDesc.SampleDesc.Quality   = 0;
1584     dropDesc.Usage                = D3D11_USAGE_DEFAULT;
1585     dropDesc.Width                = mTextureWidth;
1586 
1587     const auto &format =
1588         d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
1589     ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
1590                                          &mDropStencilTexture));
1591     mDropStencilTexture.setDebugName("TexStorage2D.DropStencil");
1592 
1593     ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::Make2D(0, mMipLevels)));
1594 
1595     *dropStencilOut = DropStencil::CREATED;
1596     return angle::Result::Continue;
1597 }
1598 
resolveTexture(const gl::Context * context)1599 angle::Result TextureStorage11_2D::resolveTexture(const gl::Context *context)
1600 {
1601     if (mMSTexInfo && mMSTexInfo->msTex && mMSTexInfo->msTextureNeedsResolve)
1602     {
1603         ANGLE_TRY(resolveTextureHelper(context, mTexture));
1604         onStateChange(angle::SubjectMessage::ContentsChanged);
1605     }
1606     return angle::Result::Continue;
1607 }
1608 
TextureStorage11_External(Renderer11 * renderer,egl::Stream * stream,const egl::Stream::GLTextureDescription & glDesc)1609 TextureStorage11_External::TextureStorage11_External(
1610     Renderer11 *renderer,
1611     egl::Stream *stream,
1612     const egl::Stream::GLTextureDescription &glDesc)
1613     : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat)
1614 {
1615     ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11Texture);
1616     auto *producer = static_cast<StreamProducerD3DTexture *>(stream->getImplementation());
1617     mTexture.set(producer->getD3DTexture(), mFormatInfo);
1618     mSubresourceIndex = producer->getArraySlice();
1619     mTexture.get()->AddRef();
1620     mMipLevels = 1;
1621 
1622     D3D11_TEXTURE2D_DESC desc;
1623     mTexture.getDesc(&desc);
1624     mTextureWidth  = desc.Width;
1625     mTextureHeight = desc.Height;
1626     mTextureDepth  = 1;
1627     mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
1628 }
1629 
onDestroy(const gl::Context * context)1630 angle::Result TextureStorage11_External::onDestroy(const gl::Context *context)
1631 {
1632     if (mHasKeyedMutex)
1633     {
1634         // If the keyed mutex is released that will unbind it and cause the state cache to become
1635         // desynchronized.
1636         mRenderer->getStateManager()->invalidateBoundViews();
1637     }
1638 
1639     return angle::Result::Continue;
1640 }
1641 
~TextureStorage11_External()1642 TextureStorage11_External::~TextureStorage11_External() {}
1643 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1644 angle::Result TextureStorage11_External::copyToStorage(const gl::Context *context,
1645                                                        TextureStorage *destStorage)
1646 {
1647     UNIMPLEMENTED();
1648     return angle::Result::Continue;
1649 }
1650 
associateImage(Image11 * image,const gl::ImageIndex & index)1651 void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index)
1652 {
1653     ASSERT(index.getLevelIndex() == 0);
1654     mAssociatedImage = image;
1655 }
1656 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)1657 void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index,
1658                                                            Image11 *expectedImage)
1659 {
1660     ASSERT(index.getLevelIndex() == 0 && mAssociatedImage == expectedImage);
1661 }
1662 
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)1663 void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index,
1664                                                   Image11 *expectedImage)
1665 {
1666     ASSERT(index.getLevelIndex() == 0);
1667     ASSERT(mAssociatedImage == expectedImage);
1668     mAssociatedImage = nullptr;
1669 }
1670 
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)1671 angle::Result TextureStorage11_External::releaseAssociatedImage(const gl::Context *context,
1672                                                                 const gl::ImageIndex &index,
1673                                                                 Image11 *incomingImage)
1674 {
1675     ASSERT(index.getLevelIndex() == 0);
1676 
1677     if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
1678     {
1679         mAssociatedImage->verifyAssociatedStorageValid(this);
1680 
1681         ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
1682     }
1683 
1684     return angle::Result::Continue;
1685 }
1686 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1687 angle::Result TextureStorage11_External::getResource(const gl::Context *context,
1688                                                      const TextureHelper11 **outResource)
1689 {
1690     *outResource = &mTexture;
1691     return angle::Result::Continue;
1692 }
1693 
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)1694 angle::Result TextureStorage11_External::getMippedResource(const gl::Context *context,
1695                                                            const TextureHelper11 **outResource)
1696 {
1697     *outResource = &mTexture;
1698     return angle::Result::Continue;
1699 }
1700 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const1701 angle::Result TextureStorage11_External::findRenderTarget(const gl::Context *context,
1702                                                           const gl::ImageIndex &index,
1703                                                           GLsizei samples,
1704                                                           RenderTargetD3D **outRT) const
1705 {
1706     // Render targets are not supported for external textures
1707     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1708     return angle::Result::Stop;
1709 }
1710 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)1711 angle::Result TextureStorage11_External::getRenderTarget(const gl::Context *context,
1712                                                          const gl::ImageIndex &index,
1713                                                          GLsizei samples,
1714                                                          RenderTargetD3D **outRT)
1715 {
1716     // Render targets are not supported for external textures
1717     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1718     return angle::Result::Stop;
1719 }
1720 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1721 angle::Result TextureStorage11_External::createSRVForSampler(const gl::Context *context,
1722                                                              int baseLevel,
1723                                                              int mipLevels,
1724                                                              DXGI_FORMAT format,
1725                                                              const TextureHelper11 &texture,
1726                                                              d3d11::SharedSRV *outSRV)
1727 {
1728     // Since external textures are treates as non-mipmapped textures, we ignore mipmap levels and
1729     // use the specified subresource ID the storage was created with.
1730     ASSERT(mipLevels == 1);
1731     ASSERT(outSRV);
1732 
1733     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1734     srvDesc.Format        = format;
1735     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1736     // subresource index is equal to the mip level for 2D textures
1737     srvDesc.Texture2DArray.MostDetailedMip = 0;
1738     srvDesc.Texture2DArray.MipLevels       = 1;
1739     srvDesc.Texture2DArray.FirstArraySlice = mSubresourceIndex;
1740     srvDesc.Texture2DArray.ArraySize       = 1;
1741 
1742     ANGLE_TRY(
1743         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
1744     outSRV->setDebugName("TexStorage2D.SRV");
1745 
1746     return angle::Result::Continue;
1747 }
1748 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1749 angle::Result TextureStorage11_External::createSRVForImage(const gl::Context *context,
1750                                                            int level,
1751                                                            DXGI_FORMAT format,
1752                                                            const TextureHelper11 &texture,
1753                                                            d3d11::SharedSRV *outSRV)
1754 {
1755     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1756     return angle::Result::Stop;
1757 }
1758 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)1759 angle::Result TextureStorage11_External::createUAVForImage(const gl::Context *context,
1760                                                            int level,
1761                                                            DXGI_FORMAT format,
1762                                                            const TextureHelper11 &texture,
1763                                                            d3d11::SharedUAV *outUAV)
1764 {
1765     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1766     return angle::Result::Stop;
1767 }
1768 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)1769 angle::Result TextureStorage11_External::getSwizzleTexture(const gl::Context *context,
1770                                                            const TextureHelper11 **outTexture)
1771 {
1772     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1773     return angle::Result::Stop;
1774 }
1775 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)1776 angle::Result TextureStorage11_External::getSwizzleRenderTarget(
1777     const gl::Context *context,
1778     int mipLevel,
1779     const d3d11::RenderTargetView **outRTV)
1780 {
1781     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1782     return angle::Result::Stop;
1783 }
1784 
TextureStorage11ImmutableBase(Renderer11 * renderer,UINT bindFlags,UINT miscFlags,GLenum internalFormat)1785 TextureStorage11ImmutableBase::TextureStorage11ImmutableBase(Renderer11 *renderer,
1786                                                              UINT bindFlags,
1787                                                              UINT miscFlags,
1788                                                              GLenum internalFormat)
1789     : TextureStorage11(renderer, bindFlags, miscFlags, internalFormat)
1790 {}
1791 
associateImage(Image11 *,const gl::ImageIndex &)1792 void TextureStorage11ImmutableBase::associateImage(Image11 *, const gl::ImageIndex &) {}
1793 
disassociateImage(const gl::ImageIndex &,Image11 *)1794 void TextureStorage11ImmutableBase::disassociateImage(const gl::ImageIndex &, Image11 *) {}
1795 
verifyAssociatedImageValid(const gl::ImageIndex &,Image11 *)1796 void TextureStorage11ImmutableBase::verifyAssociatedImageValid(const gl::ImageIndex &, Image11 *) {}
1797 
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex &,Image11 *)1798 angle::Result TextureStorage11ImmutableBase::releaseAssociatedImage(const gl::Context *context,
1799                                                                     const gl::ImageIndex &,
1800                                                                     Image11 *)
1801 {
1802     return angle::Result::Continue;
1803 }
1804 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1805 angle::Result TextureStorage11ImmutableBase::createSRVForImage(const gl::Context *context,
1806                                                                int level,
1807                                                                DXGI_FORMAT format,
1808                                                                const TextureHelper11 &texture,
1809                                                                d3d11::SharedSRV *outSRV)
1810 {
1811     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1812     return angle::Result::Stop;
1813 }
1814 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)1815 angle::Result TextureStorage11ImmutableBase::createUAVForImage(const gl::Context *context,
1816                                                                int level,
1817                                                                DXGI_FORMAT format,
1818                                                                const TextureHelper11 &texture,
1819                                                                d3d11::SharedUAV *outUAV)
1820 {
1821     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1822     return angle::Result::Stop;
1823 }
1824 
TextureStorage11_EGLImage(Renderer11 * renderer,EGLImageD3D * eglImage,RenderTarget11 * renderTarget11)1825 TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
1826                                                      EGLImageD3D *eglImage,
1827                                                      RenderTarget11 *renderTarget11)
1828     : TextureStorage11ImmutableBase(renderer,
1829                                     D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
1830                                     0,
1831                                     renderTarget11->getInternalFormat()),
1832       mImage(eglImage),
1833       mCurrentRenderTarget(0),
1834       mSwizzleTexture(),
1835       mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1836 {
1837     mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
1838 
1839     mMipLevels     = 1;
1840     mTextureWidth  = renderTarget11->getWidth();
1841     mTextureHeight = renderTarget11->getHeight();
1842     mTextureDepth  = 1;
1843 }
1844 
~TextureStorage11_EGLImage()1845 TextureStorage11_EGLImage::~TextureStorage11_EGLImage() {}
1846 
getSubresourceIndex(const gl::Context * context,const gl::ImageIndex & index,UINT * outSubresourceIndex) const1847 angle::Result TextureStorage11_EGLImage::getSubresourceIndex(const gl::Context *context,
1848                                                              const gl::ImageIndex &index,
1849                                                              UINT *outSubresourceIndex) const
1850 {
1851     ASSERT(index.getType() == gl::TextureType::_2D);
1852     ASSERT(index.getLevelIndex() == 0);
1853 
1854     RenderTarget11 *renderTarget11 = nullptr;
1855     ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
1856     *outSubresourceIndex = renderTarget11->getSubresourceIndex();
1857     return angle::Result::Continue;
1858 }
1859 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1860 angle::Result TextureStorage11_EGLImage::getResource(const gl::Context *context,
1861                                                      const TextureHelper11 **outResource)
1862 {
1863     ANGLE_TRY(checkForUpdatedRenderTarget(context));
1864 
1865     RenderTarget11 *renderTarget11 = nullptr;
1866     ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
1867     *outResource = &renderTarget11->getTexture();
1868     return angle::Result::Continue;
1869 }
1870 
getSRVForSampler(const gl::Context * context,const gl::TextureState & textureState,const gl::SamplerState & sampler,const d3d11::SharedSRV ** outSRV)1871 angle::Result TextureStorage11_EGLImage::getSRVForSampler(const gl::Context *context,
1872                                                           const gl::TextureState &textureState,
1873                                                           const gl::SamplerState &sampler,
1874                                                           const d3d11::SharedSRV **outSRV)
1875 {
1876     ANGLE_TRY(checkForUpdatedRenderTarget(context));
1877     return TextureStorage11::getSRVForSampler(context, textureState, sampler, outSRV);
1878 }
1879 
getMippedResource(const gl::Context * context,const TextureHelper11 **)1880 angle::Result TextureStorage11_EGLImage::getMippedResource(const gl::Context *context,
1881                                                            const TextureHelper11 **)
1882 {
1883     // This shouldn't be called unless the zero max LOD workaround is active.
1884     // EGL images are unavailable in this configuration.
1885     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1886     return angle::Result::Stop;
1887 }
1888 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const1889 angle::Result TextureStorage11_EGLImage::findRenderTarget(const gl::Context *context,
1890                                                           const gl::ImageIndex &index,
1891                                                           GLsizei samples,
1892                                                           RenderTargetD3D **outRT) const
1893 {
1894     // Since the render target of an EGL image will be updated when orphaning, trying to find a
1895     // cache of it can be rarely useful.
1896     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1897     return angle::Result::Stop;
1898 }
1899 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)1900 angle::Result TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context,
1901                                                          const gl::ImageIndex &index,
1902                                                          GLsizei samples,
1903                                                          RenderTargetD3D **outRT)
1904 {
1905     ASSERT(!index.hasLayer());
1906     ASSERT(index.getLevelIndex() == 0);
1907 
1908     ANGLE_TRY(checkForUpdatedRenderTarget(context));
1909 
1910     return mImage->getRenderTarget(context, outRT);
1911 }
1912 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1913 angle::Result TextureStorage11_EGLImage::copyToStorage(const gl::Context *context,
1914                                                        TextureStorage *destStorage)
1915 {
1916     const TextureHelper11 *sourceResouce = nullptr;
1917     ANGLE_TRY(getResource(context, &sourceResouce));
1918 
1919     ASSERT(destStorage);
1920     TextureStorage11_2D *dest11         = GetAs<TextureStorage11_2D>(destStorage);
1921     const TextureHelper11 *destResource = nullptr;
1922     ANGLE_TRY(dest11->getResource(context, &destResource));
1923 
1924     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
1925     immediateContext->CopyResource(destResource->get(), sourceResouce->get());
1926 
1927     dest11->markDirty();
1928 
1929     return angle::Result::Continue;
1930 }
1931 
useLevelZeroWorkaroundTexture(const gl::Context * context,bool)1932 angle::Result TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(const gl::Context *context,
1933                                                                        bool)
1934 {
1935     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1936     return angle::Result::Stop;
1937 }
1938 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)1939 angle::Result TextureStorage11_EGLImage::getSwizzleTexture(const gl::Context *context,
1940                                                            const TextureHelper11 **outTexture)
1941 {
1942     ASSERT(outTexture);
1943 
1944     if (!mSwizzleTexture.valid())
1945     {
1946         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
1947 
1948         D3D11_TEXTURE2D_DESC desc;
1949         desc.Width              = mTextureWidth;
1950         desc.Height             = mTextureHeight;
1951         desc.MipLevels          = mMipLevels;
1952         desc.ArraySize          = 1;
1953         desc.Format             = format.texFormat;
1954         desc.SampleDesc.Count   = 1;
1955         desc.SampleDesc.Quality = 0;
1956         desc.Usage              = D3D11_USAGE_DEFAULT;
1957         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1958         desc.CPUAccessFlags     = 0;
1959         desc.MiscFlags          = 0;
1960 
1961         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
1962                                              &mSwizzleTexture));
1963         mSwizzleTexture.setDebugName("TexStorageEGLImage.SwizzleTexture");
1964     }
1965 
1966     *outTexture = &mSwizzleTexture;
1967     return angle::Result::Continue;
1968 }
1969 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)1970 angle::Result TextureStorage11_EGLImage::getSwizzleRenderTarget(
1971     const gl::Context *context,
1972     int mipLevel,
1973     const d3d11::RenderTargetView **outRTV)
1974 {
1975     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
1976     ASSERT(outRTV);
1977 
1978     if (!mSwizzleRenderTargets[mipLevel].valid())
1979     {
1980         const TextureHelper11 *swizzleTexture = nullptr;
1981         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
1982 
1983         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1984         rtvDesc.Format =
1985             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
1986         rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
1987         rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
1988 
1989         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
1990                                               mSwizzleTexture.get(),
1991                                               &mSwizzleRenderTargets[mipLevel]));
1992     }
1993 
1994     *outRTV = &mSwizzleRenderTargets[mipLevel];
1995     return angle::Result::Continue;
1996 }
1997 
checkForUpdatedRenderTarget(const gl::Context * context)1998 angle::Result TextureStorage11_EGLImage::checkForUpdatedRenderTarget(const gl::Context *context)
1999 {
2000     RenderTarget11 *renderTarget11 = nullptr;
2001     ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
2002 
2003     if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11))
2004     {
2005         clearSRVCache();
2006         mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
2007     }
2008 
2009     return angle::Result::Continue;
2010 }
2011 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2012 angle::Result TextureStorage11_EGLImage::createSRVForSampler(const gl::Context *context,
2013                                                              int baseLevel,
2014                                                              int mipLevels,
2015                                                              DXGI_FORMAT format,
2016                                                              const TextureHelper11 &texture,
2017                                                              d3d11::SharedSRV *outSRV)
2018 {
2019     ASSERT(baseLevel == 0);
2020     ASSERT(mipLevels == 1);
2021     ASSERT(outSRV);
2022 
2023     // Create a new SRV only for the swizzle texture.  Otherwise just return the Image's
2024     // RenderTarget's SRV.
2025     if (texture == mSwizzleTexture)
2026     {
2027         D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2028         srvDesc.Format                    = format;
2029         srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
2030         srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
2031         srvDesc.Texture2D.MipLevels       = mipLevels;
2032 
2033         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(),
2034                                               outSRV));
2035         outSRV->setDebugName("TexStorageEGLImage.SRV");
2036     }
2037     else
2038     {
2039         RenderTarget11 *renderTarget = nullptr;
2040         ANGLE_TRY(getImageRenderTarget(context, &renderTarget));
2041 
2042         ASSERT(texture == renderTarget->getTexture());
2043 
2044         *outSRV = renderTarget->getShaderResourceView(context).makeCopy();
2045     }
2046 
2047     return angle::Result::Continue;
2048 }
2049 
getImageRenderTarget(const gl::Context * context,RenderTarget11 ** outRT) const2050 angle::Result TextureStorage11_EGLImage::getImageRenderTarget(const gl::Context *context,
2051                                                               RenderTarget11 **outRT) const
2052 {
2053     RenderTargetD3D *renderTargetD3D = nullptr;
2054     ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
2055     *outRT = GetAs<RenderTarget11>(renderTargetD3D);
2056     return angle::Result::Continue;
2057 }
2058 
TextureStorage11_Cube(Renderer11 * renderer,GLenum internalformat,bool renderTarget,int size,int levels,bool hintLevelZeroOnly)2059 TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer,
2060                                              GLenum internalformat,
2061                                              bool renderTarget,
2062                                              int size,
2063                                              int levels,
2064                                              bool hintLevelZeroOnly)
2065     : TextureStorage11(
2066           renderer,
2067           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
2068           GetTextureMiscFlags(internalformat,
2069                               renderer->getRenderer11DeviceCaps(),
2070                               renderTarget,
2071                               levels),
2072           internalformat),
2073       mTexture(),
2074       mLevelZeroTexture(),
2075       mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
2076       mSwizzleTexture()
2077 {
2078     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
2079     {
2080         for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
2081         {
2082             mAssociatedImages[face][level] = nullptr;
2083             mRenderTarget[face][level]     = nullptr;
2084         }
2085     }
2086 
2087     for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
2088     {
2089         mLevelZeroRenderTarget[face] = nullptr;
2090     }
2091 
2092     // adjust size if needed for compressed textures
2093     int height = size;
2094     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel);
2095 
2096     mMipLevels     = mTopLevel + levels;
2097     mTextureWidth  = size;
2098     mTextureHeight = size;
2099     mTextureDepth  = 1;
2100 
2101     // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
2102     ASSERT(!mUseLevelZeroTexture || mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
2103 }
2104 
onDestroy(const gl::Context * context)2105 angle::Result TextureStorage11_Cube::onDestroy(const gl::Context *context)
2106 {
2107     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
2108     {
2109         for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
2110         {
2111             if (mAssociatedImages[face][level] != nullptr)
2112             {
2113                 mAssociatedImages[face][level]->verifyAssociatedStorageValid(this);
2114 
2115                 // We must let the Images recover their data before we delete it from the
2116                 // TextureStorage.
2117                 ANGLE_TRY(mAssociatedImages[face][level]->recoverFromAssociatedStorage(context));
2118             }
2119         }
2120     }
2121 
2122     return angle::Result::Continue;
2123 }
2124 
~TextureStorage11_Cube()2125 TextureStorage11_Cube::~TextureStorage11_Cube() {}
2126 
getSubresourceIndex(const gl::Context * context,const gl::ImageIndex & index,UINT * outSubresourceIndex) const2127 angle::Result TextureStorage11_Cube::getSubresourceIndex(const gl::Context *context,
2128                                                          const gl::ImageIndex &index,
2129                                                          UINT *outSubresourceIndex) const
2130 {
2131     UINT arraySlice = index.cubeMapFaceIndex();
2132     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled && mUseLevelZeroTexture &&
2133         index.getLevelIndex() == 0)
2134     {
2135         UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
2136         ASSERT(subresource != std::numeric_limits<UINT>::max());
2137         *outSubresourceIndex = subresource;
2138     }
2139     else
2140     {
2141         UINT mipSlice    = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
2142         UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
2143         ASSERT(subresource != std::numeric_limits<UINT>::max());
2144         *outSubresourceIndex = subresource;
2145     }
2146     return angle::Result::Continue;
2147 }
2148 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)2149 angle::Result TextureStorage11_Cube::copyToStorage(const gl::Context *context,
2150                                                    TextureStorage *destStorage)
2151 {
2152     ASSERT(destStorage);
2153 
2154     TextureStorage11_Cube *dest11 = GetAs<TextureStorage11_Cube>(destStorage);
2155 
2156     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
2157     {
2158         ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
2159 
2160         // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
2161         // corresponding textures in destStorage.
2162         if (mTexture.valid())
2163         {
2164             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
2165 
2166             const TextureHelper11 *destResource = nullptr;
2167             ANGLE_TRY(dest11->getResource(context, &destResource));
2168 
2169             immediateContext->CopyResource(destResource->get(), mTexture.get());
2170         }
2171 
2172         if (mLevelZeroTexture.valid())
2173         {
2174             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
2175 
2176             const TextureHelper11 *destResource = nullptr;
2177             ANGLE_TRY(dest11->getResource(context, &destResource));
2178 
2179             immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
2180         }
2181     }
2182     else
2183     {
2184         const TextureHelper11 *sourceResouce = nullptr;
2185         ANGLE_TRY(getResource(context, &sourceResouce));
2186 
2187         const TextureHelper11 *destResource = nullptr;
2188         ANGLE_TRY(dest11->getResource(context, &destResource));
2189 
2190         ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
2191         immediateContext->CopyResource(destResource->get(), sourceResouce->get());
2192     }
2193 
2194     dest11->markDirty();
2195 
2196     return angle::Result::Continue;
2197 }
2198 
useLevelZeroWorkaroundTexture(const gl::Context * context,bool useLevelZeroTexture)2199 angle::Result TextureStorage11_Cube::useLevelZeroWorkaroundTexture(const gl::Context *context,
2200                                                                    bool useLevelZeroTexture)
2201 {
2202     if (useLevelZeroTexture && mMipLevels > 1)
2203     {
2204         if (!mUseLevelZeroTexture && mTexture.valid())
2205         {
2206             ANGLE_TRY(ensureTextureExists(context, 1));
2207 
2208             // Pull data back from the mipped texture if necessary.
2209             ASSERT(mLevelZeroTexture.valid());
2210             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2211 
2212             for (int face = 0; face < 6; face++)
2213             {
2214                 deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(),
2215                                                      D3D11CalcSubresource(0, face, 1), 0, 0, 0,
2216                                                      mTexture.get(), face * mMipLevels, nullptr);
2217             }
2218         }
2219 
2220         mUseLevelZeroTexture = true;
2221     }
2222     else
2223     {
2224         if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
2225         {
2226             ANGLE_TRY(ensureTextureExists(context, mMipLevels));
2227 
2228             // Pull data back from the level zero texture if necessary.
2229             ASSERT(mTexture.valid());
2230             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2231 
2232             for (int face = 0; face < 6; face++)
2233             {
2234                 deviceContext->CopySubresourceRegion(mTexture.get(),
2235                                                      D3D11CalcSubresource(0, face, mMipLevels), 0,
2236                                                      0, 0, mLevelZeroTexture.get(), face, nullptr);
2237             }
2238         }
2239 
2240         mUseLevelZeroTexture = false;
2241     }
2242 
2243     return angle::Result::Continue;
2244 }
2245 
associateImage(Image11 * image,const gl::ImageIndex & index)2246 void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index)
2247 {
2248     const GLint level       = index.getLevelIndex();
2249     const GLint layerTarget = index.cubeMapFaceIndex();
2250 
2251     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2252     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2253 
2254     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2255     {
2256         if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount))
2257         {
2258             mAssociatedImages[layerTarget][level] = image;
2259         }
2260     }
2261 }
2262 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2263 void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index,
2264                                                        Image11 *expectedImage)
2265 {
2266     const GLint level       = index.getLevelIndex();
2267     const GLint layerTarget = index.cubeMapFaceIndex();
2268 
2269     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2270     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2271     // This validation check should never return false. It means the Image/TextureStorage
2272     // association is broken.
2273     ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
2274 }
2275 
2276 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)2277 void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
2278 {
2279     const GLint level       = index.getLevelIndex();
2280     const GLint layerTarget = index.cubeMapFaceIndex();
2281 
2282     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2283     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2284     ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
2285     mAssociatedImages[layerTarget][level] = nullptr;
2286 }
2287 
2288 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
2289 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)2290 angle::Result TextureStorage11_Cube::releaseAssociatedImage(const gl::Context *context,
2291                                                             const gl::ImageIndex &index,
2292                                                             Image11 *incomingImage)
2293 {
2294     const GLint level       = index.getLevelIndex();
2295     const GLint layerTarget = index.cubeMapFaceIndex();
2296 
2297     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2298     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2299 
2300     if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2301     {
2302         if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount))
2303         {
2304             // No need to let the old Image recover its data, if it is also the incoming Image.
2305             if (mAssociatedImages[layerTarget][level] != nullptr &&
2306                 mAssociatedImages[layerTarget][level] != incomingImage)
2307             {
2308                 // Ensure that the Image is still associated with this TextureStorage.
2309                 mAssociatedImages[layerTarget][level]->verifyAssociatedStorageValid(this);
2310 
2311                 // Force the image to recover from storage before its data is overwritten.
2312                 // This will reset mAssociatedImages[level] to nullptr too.
2313                 ANGLE_TRY(
2314                     mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(context));
2315             }
2316         }
2317     }
2318 
2319     return angle::Result::Continue;
2320 }
2321 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)2322 angle::Result TextureStorage11_Cube::getResource(const gl::Context *context,
2323                                                  const TextureHelper11 **outResource)
2324 {
2325     if (mUseLevelZeroTexture && mMipLevels > 1)
2326     {
2327         ANGLE_TRY(ensureTextureExists(context, 1));
2328         *outResource = &mLevelZeroTexture;
2329     }
2330     else
2331     {
2332         ANGLE_TRY(ensureTextureExists(context, mMipLevels));
2333         *outResource = &mTexture;
2334     }
2335     return angle::Result::Continue;
2336 }
2337 
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)2338 angle::Result TextureStorage11_Cube::getMippedResource(const gl::Context *context,
2339                                                        const TextureHelper11 **outResource)
2340 {
2341     // This shouldn't be called unless the zero max LOD workaround is active.
2342     ASSERT(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
2343 
2344     ANGLE_TRY(ensureTextureExists(context, mMipLevels));
2345     *outResource = &mTexture;
2346     return angle::Result::Continue;
2347 }
2348 
ensureTextureExists(const gl::Context * context,int mipLevels)2349 angle::Result TextureStorage11_Cube::ensureTextureExists(const gl::Context *context, int mipLevels)
2350 {
2351     // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
2352     ANGLE_TRY(resolveTexture(context));
2353     bool useLevelZeroTexture = mRenderer->getFeatures().zeroMaxLodWorkaround.enabled
2354                                    ? (mipLevels == 1) && (mMipLevels > 1)
2355                                    : false;
2356     TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
2357 
2358     // if the size is not positive this should be treated as an incomplete texture
2359     // we handle that here by skipping the d3d texture creation
2360     if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
2361     {
2362         ASSERT(mMipLevels > 0);
2363 
2364         D3D11_TEXTURE2D_DESC desc;
2365         desc.Width              = mTextureWidth;
2366         desc.Height             = mTextureHeight;
2367         desc.MipLevels          = mipLevels;
2368         desc.ArraySize          = gl::kCubeFaceCount;
2369         desc.Format             = mFormatInfo.texFormat;
2370         desc.SampleDesc.Count   = 1;
2371         desc.SampleDesc.Quality = 0;
2372         desc.Usage              = D3D11_USAGE_DEFAULT;
2373         desc.BindFlags          = getBindFlags();
2374         desc.CPUAccessFlags     = 0;
2375         desc.MiscFlags          = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags();
2376 
2377         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
2378                                              outputTexture));
2379         outputTexture->setDebugName("TexStorageCube.Texture");
2380     }
2381 
2382     return angle::Result::Continue;
2383 }
2384 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const2385 angle::Result TextureStorage11_Cube::findRenderTarget(const gl::Context *context,
2386                                                       const gl::ImageIndex &index,
2387                                                       GLsizei samples,
2388                                                       RenderTargetD3D **outRT) const
2389 {
2390     const int faceIndex = index.cubeMapFaceIndex();
2391     const int level     = index.getLevelIndex();
2392 
2393     ASSERT(level >= 0 && level < getLevelCount());
2394     ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::kCubeFaceCount));
2395 
2396     bool needMS = samples > 0;
2397     if (needMS)
2398     {
2399         return findMultisampledRenderTarget(context, index, samples, outRT);
2400     }
2401 
2402     if (!mRenderTarget[faceIndex][level])
2403     {
2404         if (mUseLevelZeroTexture)
2405         {
2406             ASSERT(index.getLevelIndex() == 0);
2407             ASSERT(outRT);
2408             *outRT = mLevelZeroRenderTarget[faceIndex].get();
2409             return angle::Result::Continue;
2410         }
2411     }
2412 
2413     ASSERT(outRT);
2414     *outRT = mRenderTarget[faceIndex][level].get();
2415     return angle::Result::Continue;
2416 }
2417 
createRenderTargetSRV(const gl::Context * context,const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const2418 angle::Result TextureStorage11_Cube::createRenderTargetSRV(const gl::Context *context,
2419                                                            const TextureHelper11 &texture,
2420                                                            const gl::ImageIndex &index,
2421                                                            DXGI_FORMAT resourceFormat,
2422                                                            d3d11::SharedSRV *srv) const
2423 {
2424     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2425     srvDesc.Format                         = resourceFormat;
2426     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
2427     srvDesc.Texture2DArray.MipLevels       = 1;
2428     srvDesc.Texture2DArray.FirstArraySlice = index.cubeMapFaceIndex();
2429     srvDesc.Texture2DArray.ArraySize       = 1;
2430 
2431     if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
2432     {
2433         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
2434     }
2435     else
2436     {
2437         // Will be used with Texture2D sampler, not TextureCube
2438         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2439     }
2440 
2441     ANGLE_TRY(
2442         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
2443     return angle::Result::Continue;
2444 }
2445 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)2446 angle::Result TextureStorage11_Cube::getRenderTarget(const gl::Context *context,
2447                                                      const gl::ImageIndex &index,
2448                                                      GLsizei samples,
2449                                                      RenderTargetD3D **outRT)
2450 {
2451     const int faceIndex = index.cubeMapFaceIndex();
2452     const int level     = index.getLevelIndex();
2453 
2454     ASSERT(level >= 0 && level < getLevelCount());
2455     ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::kCubeFaceCount));
2456 
2457     bool needMS = samples > 0;
2458     if (needMS)
2459     {
2460         return getMultisampledRenderTarget(context, index, samples, outRT);
2461     }
2462     else
2463     {
2464         ANGLE_TRY(resolveTexture(context));
2465     }
2466 
2467     Context11 *context11 = GetImplAs<Context11>(context);
2468 
2469     if (!mRenderTarget[faceIndex][level])
2470     {
2471         if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
2472         {
2473             ASSERT(index.getLevelIndex() == 0);
2474             ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
2475         }
2476 
2477         const TextureHelper11 *texture = nullptr;
2478         ANGLE_TRY(getResource(context, &texture));
2479 
2480         if (mUseLevelZeroTexture)
2481         {
2482             if (!mLevelZeroRenderTarget[faceIndex])
2483             {
2484                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2485                 rtvDesc.Format                         = mFormatInfo.rtvFormat;
2486                 rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2487                 rtvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2488                 rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2489                 rtvDesc.Texture2DArray.ArraySize       = 1;
2490 
2491                 d3d11::RenderTargetView rtv;
2492                 ANGLE_TRY(
2493                     mRenderer->allocateResource(context11, rtvDesc, mLevelZeroTexture.get(), &rtv));
2494 
2495                 mLevelZeroRenderTarget[faceIndex].reset(new TextureRenderTarget11(
2496                     std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
2497                     mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
2498                     getLevelHeight(level), 1, 0));
2499             }
2500 
2501             ASSERT(outRT);
2502             *outRT = mLevelZeroRenderTarget[faceIndex].get();
2503             return angle::Result::Continue;
2504         }
2505 
2506         d3d11::SharedSRV srv;
2507         ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
2508         d3d11::SharedSRV blitSRV;
2509         if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
2510         {
2511             ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
2512                                             &blitSRV));
2513         }
2514         else
2515         {
2516             blitSRV = srv.makeCopy();
2517         }
2518 
2519         srv.setDebugName("TexStorageCube.RenderTargetSRV");
2520 
2521         if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
2522         {
2523             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2524             rtvDesc.Format                         = mFormatInfo.rtvFormat;
2525             rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2526             rtvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2527             rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2528             rtvDesc.Texture2DArray.ArraySize       = 1;
2529 
2530             d3d11::RenderTargetView rtv;
2531             ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
2532             rtv.setDebugName("TexStorageCube.RenderTargetRTV");
2533 
2534             mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
2535                 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
2536                 getLevelWidth(level), getLevelHeight(level), 1, 0));
2537         }
2538         else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
2539         {
2540             D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
2541             dsvDesc.Format                         = mFormatInfo.dsvFormat;
2542             dsvDesc.ViewDimension                  = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
2543             dsvDesc.Flags                          = 0;
2544             dsvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2545             dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2546             dsvDesc.Texture2DArray.ArraySize       = 1;
2547 
2548             d3d11::DepthStencilView dsv;
2549             ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
2550             dsv.setDebugName("TexStorageCube.RenderTargetDSV");
2551 
2552             mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
2553                 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
2554                 getLevelWidth(level), getLevelHeight(level), 1, 0));
2555         }
2556         else
2557         {
2558             UNREACHABLE();
2559         }
2560     }
2561 
2562     ASSERT(outRT);
2563     *outRT = mRenderTarget[faceIndex][level].get();
2564     return angle::Result::Continue;
2565 }
2566 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2567 angle::Result TextureStorage11_Cube::createSRVForSampler(const gl::Context *context,
2568                                                          int baseLevel,
2569                                                          int mipLevels,
2570                                                          DXGI_FORMAT format,
2571                                                          const TextureHelper11 &texture,
2572                                                          d3d11::SharedSRV *outSRV)
2573 {
2574     ASSERT(outSRV);
2575 
2576     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2577     srvDesc.Format = format;
2578 
2579     // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six
2580     // 2D textures
2581     const GLenum componentType = d3d11::GetComponentType(format);
2582     if (componentType == GL_INT || componentType == GL_UNSIGNED_INT)
2583     {
2584         srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2585         srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
2586         srvDesc.Texture2DArray.MipLevels       = mipLevels;
2587         srvDesc.Texture2DArray.FirstArraySlice = 0;
2588         srvDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2589     }
2590     else
2591     {
2592         srvDesc.ViewDimension               = D3D11_SRV_DIMENSION_TEXTURECUBE;
2593         srvDesc.TextureCube.MipLevels       = mipLevels;
2594         srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
2595     }
2596 
2597     const TextureHelper11 *srvTexture = &texture;
2598 
2599     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
2600     {
2601         ASSERT(mTopLevel == 0);
2602         ASSERT(baseLevel == 0);
2603         // This code also assumes that the incoming texture equals either mLevelZeroTexture or
2604         // mTexture.
2605 
2606         if (mipLevels == 1 && mMipLevels > 1)
2607         {
2608             // We must use a SRV on the level-zero-only texture.
2609             ANGLE_TRY(ensureTextureExists(context, 1));
2610             srvTexture = &mLevelZeroTexture;
2611         }
2612         else
2613         {
2614             ASSERT(mipLevels == static_cast<int>(mMipLevels));
2615             ASSERT(mTexture.valid() && texture == mTexture);
2616             srvTexture = &mTexture;
2617         }
2618     }
2619 
2620     ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, srvTexture->get(),
2621                                           outSRV));
2622     outSRV->setDebugName("TexStorageCube.SRV");
2623 
2624     return angle::Result::Continue;
2625 }
2626 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2627 angle::Result TextureStorage11_Cube::createSRVForImage(const gl::Context *context,
2628                                                        int level,
2629                                                        DXGI_FORMAT format,
2630                                                        const TextureHelper11 &texture,
2631                                                        d3d11::SharedSRV *outSRV)
2632 {
2633     ASSERT(outSRV);
2634     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2635     srvDesc.Format                         = format;
2636     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2637     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
2638     srvDesc.Texture2DArray.MipLevels       = 1;
2639     srvDesc.Texture2DArray.FirstArraySlice = 0;
2640     srvDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2641     ANGLE_TRY(
2642         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
2643     outSRV->setDebugName("TexStorageCube.SRVForImage");
2644     return angle::Result::Continue;
2645 }
2646 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)2647 angle::Result TextureStorage11_Cube::createUAVForImage(const gl::Context *context,
2648                                                        int level,
2649                                                        DXGI_FORMAT format,
2650                                                        const TextureHelper11 &texture,
2651                                                        d3d11::SharedUAV *outUAV)
2652 {
2653     ASSERT(outUAV);
2654     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
2655     uavDesc.Format                         = format;
2656     uavDesc.ViewDimension                  = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
2657     uavDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2658     uavDesc.Texture2DArray.FirstArraySlice = 0;
2659     uavDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2660     ANGLE_TRY(
2661         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
2662     outUAV->setDebugName("TexStorageCube.UAVForImage");
2663     return angle::Result::Continue;
2664 }
2665 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)2666 angle::Result TextureStorage11_Cube::getSwizzleTexture(const gl::Context *context,
2667                                                        const TextureHelper11 **outTexture)
2668 {
2669     ASSERT(outTexture);
2670 
2671     if (!mSwizzleTexture.valid())
2672     {
2673         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
2674 
2675         D3D11_TEXTURE2D_DESC desc;
2676         desc.Width              = mTextureWidth;
2677         desc.Height             = mTextureHeight;
2678         desc.MipLevels          = mMipLevels;
2679         desc.ArraySize          = gl::kCubeFaceCount;
2680         desc.Format             = format.texFormat;
2681         desc.SampleDesc.Count   = 1;
2682         desc.SampleDesc.Quality = 0;
2683         desc.Usage              = D3D11_USAGE_DEFAULT;
2684         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
2685         desc.CPUAccessFlags     = 0;
2686         desc.MiscFlags          = D3D11_RESOURCE_MISC_TEXTURECUBE;
2687 
2688         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
2689                                              &mSwizzleTexture));
2690         mSwizzleTexture.setDebugName("TexStorageCube.SwizzleTexture");
2691     }
2692 
2693     *outTexture = &mSwizzleTexture;
2694     return angle::Result::Continue;
2695 }
2696 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)2697 angle::Result TextureStorage11_Cube::getSwizzleRenderTarget(const gl::Context *context,
2698                                                             int mipLevel,
2699                                                             const d3d11::RenderTargetView **outRTV)
2700 {
2701     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2702     ASSERT(outRTV);
2703 
2704     if (!mSwizzleRenderTargets[mipLevel].valid())
2705     {
2706         const TextureHelper11 *swizzleTexture = nullptr;
2707         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
2708 
2709         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2710         rtvDesc.Format =
2711             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
2712         rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2713         rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
2714         rtvDesc.Texture2DArray.FirstArraySlice = 0;
2715         rtvDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2716 
2717         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
2718                                               mSwizzleTexture.get(),
2719                                               &mSwizzleRenderTargets[mipLevel]));
2720     }
2721 
2722     *outRTV = &mSwizzleRenderTargets[mipLevel];
2723     return angle::Result::Continue;
2724 }
2725 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)2726 angle::Result TextureStorage11_Cube::ensureDropStencilTexture(const gl::Context *context,
2727                                                               DropStencil *dropStencilOut)
2728 {
2729     if (mDropStencilTexture.valid())
2730     {
2731         *dropStencilOut = DropStencil::ALREADY_EXISTS;
2732         return angle::Result::Continue;
2733     }
2734 
2735     D3D11_TEXTURE2D_DESC dropDesc = {};
2736     dropDesc.ArraySize            = 6;
2737     dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
2738     dropDesc.CPUAccessFlags       = 0;
2739     dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
2740     dropDesc.Height               = mTextureHeight;
2741     dropDesc.MipLevels            = mMipLevels;
2742     dropDesc.MiscFlags            = D3D11_RESOURCE_MISC_TEXTURECUBE;
2743     dropDesc.SampleDesc.Count     = 1;
2744     dropDesc.SampleDesc.Quality   = 0;
2745     dropDesc.Usage                = D3D11_USAGE_DEFAULT;
2746     dropDesc.Width                = mTextureWidth;
2747 
2748     const auto &format =
2749         d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
2750     ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
2751                                          &mDropStencilTexture));
2752     mDropStencilTexture.setDebugName("TexStorageCube.DropStencil");
2753 
2754     ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
2755 
2756     *dropStencilOut = DropStencil::CREATED;
2757     return angle::Result::Continue;
2758 }
2759 
resolveTexture(const gl::Context * context)2760 angle::Result TextureStorage11_Cube::resolveTexture(const gl::Context *context)
2761 {
2762     if (mMSTexInfo && mMSTexInfo->msTex && mMSTexInfo->msTextureNeedsResolve)
2763     {
2764         ANGLE_TRY(resolveTextureHelper(context, mTexture));
2765         onStateChange(angle::SubjectMessage::ContentsChanged);
2766     }
2767     return angle::Result::Continue;
2768 }
2769 
TextureStorage11_3D(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels)2770 TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
2771                                          GLenum internalformat,
2772                                          bool renderTarget,
2773                                          GLsizei width,
2774                                          GLsizei height,
2775                                          GLsizei depth,
2776                                          int levels)
2777     : TextureStorage11(
2778           renderer,
2779           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
2780           GetTextureMiscFlags(internalformat,
2781                               renderer->getRenderer11DeviceCaps(),
2782                               renderTarget,
2783                               levels),
2784           internalformat)
2785 {
2786     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2787     {
2788         mAssociatedImages[i]   = nullptr;
2789         mLevelRenderTargets[i] = nullptr;
2790     }
2791 
2792     // adjust size if needed for compressed textures
2793     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
2794 
2795     mMipLevels     = mTopLevel + levels;
2796     mTextureWidth  = width;
2797     mTextureHeight = height;
2798     mTextureDepth  = depth;
2799 }
2800 
onDestroy(const gl::Context * context)2801 angle::Result TextureStorage11_3D::onDestroy(const gl::Context *context)
2802 {
2803     for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2804     {
2805         if (mAssociatedImages[i] != nullptr)
2806         {
2807             mAssociatedImages[i]->verifyAssociatedStorageValid(this);
2808 
2809             // We must let the Images recover their data before we delete it from the
2810             // TextureStorage.
2811             ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
2812         }
2813     }
2814 
2815     return angle::Result::Continue;
2816 }
2817 
~TextureStorage11_3D()2818 TextureStorage11_3D::~TextureStorage11_3D() {}
2819 
associateImage(Image11 * image,const gl::ImageIndex & index)2820 void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
2821 {
2822     const GLint level = index.getLevelIndex();
2823 
2824     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2825 
2826     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2827     {
2828         mAssociatedImages[level] = image;
2829     }
2830 }
2831 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2832 void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index,
2833                                                      Image11 *expectedImage)
2834 {
2835     const GLint level = index.getLevelIndex();
2836 
2837     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2838     // This validation check should never return false. It means the Image/TextureStorage
2839     // association is broken.
2840     ASSERT(mAssociatedImages[level] == expectedImage);
2841 }
2842 
2843 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)2844 void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
2845 {
2846     const GLint level = index.getLevelIndex();
2847 
2848     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2849     ASSERT(mAssociatedImages[level] == expectedImage);
2850     mAssociatedImages[level] = nullptr;
2851 }
2852 
2853 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
2854 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)2855 angle::Result TextureStorage11_3D::releaseAssociatedImage(const gl::Context *context,
2856                                                           const gl::ImageIndex &index,
2857                                                           Image11 *incomingImage)
2858 {
2859     const GLint level = index.getLevelIndex();
2860 
2861     ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
2862 
2863     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2864     {
2865         // No need to let the old Image recover its data, if it is also the incoming Image.
2866         if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
2867         {
2868             // Ensure that the Image is still associated with this TextureStorage.
2869             mAssociatedImages[level]->verifyAssociatedStorageValid(this);
2870 
2871             // Force the image to recover from storage before its data is overwritten.
2872             // This will reset mAssociatedImages[level] to nullptr too.
2873             ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
2874         }
2875     }
2876 
2877     return angle::Result::Continue;
2878 }
2879 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)2880 angle::Result TextureStorage11_3D::getResource(const gl::Context *context,
2881                                                const TextureHelper11 **outResource)
2882 {
2883     // If the width, height or depth are not positive this should be treated as an incomplete
2884     // texture. We handle that here by skipping the d3d texture creation.
2885     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
2886     {
2887         ASSERT(mMipLevels > 0);
2888 
2889         D3D11_TEXTURE3D_DESC desc;
2890         desc.Width          = mTextureWidth;
2891         desc.Height         = mTextureHeight;
2892         desc.Depth          = mTextureDepth;
2893         desc.MipLevels      = mMipLevels;
2894         desc.Format         = mFormatInfo.texFormat;
2895         desc.Usage          = D3D11_USAGE_DEFAULT;
2896         desc.BindFlags      = getBindFlags();
2897         desc.CPUAccessFlags = 0;
2898         desc.MiscFlags      = getMiscFlags();
2899 
2900         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
2901                                              &mTexture));
2902         mTexture.setDebugName("TexStorage3D.Texture");
2903     }
2904 
2905     *outResource = &mTexture;
2906     return angle::Result::Continue;
2907 }
2908 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2909 angle::Result TextureStorage11_3D::createSRVForSampler(const gl::Context *context,
2910                                                        int baseLevel,
2911                                                        int mipLevels,
2912                                                        DXGI_FORMAT format,
2913                                                        const TextureHelper11 &texture,
2914                                                        d3d11::SharedSRV *outSRV)
2915 {
2916     ASSERT(outSRV);
2917 
2918     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2919     srvDesc.Format                    = format;
2920     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE3D;
2921     srvDesc.Texture3D.MostDetailedMip = baseLevel;
2922     srvDesc.Texture3D.MipLevels       = mipLevels;
2923 
2924     ANGLE_TRY(
2925         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
2926     outSRV->setDebugName("TexStorage3D.SRV");
2927 
2928     return angle::Result::Continue;
2929 }
2930 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2931 angle::Result TextureStorage11_3D::createSRVForImage(const gl::Context *context,
2932                                                      int level,
2933                                                      DXGI_FORMAT format,
2934                                                      const TextureHelper11 &texture,
2935                                                      d3d11::SharedSRV *outSRV)
2936 {
2937     ASSERT(outSRV);
2938     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2939     srvDesc.Format                    = format;
2940     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE3D;
2941     srvDesc.Texture3D.MostDetailedMip = mTopLevel + level;
2942     srvDesc.Texture3D.MipLevels       = 1;
2943     ANGLE_TRY(
2944         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
2945     outSRV->setDebugName("TexStorage3D.SRVForImage");
2946     return angle::Result::Continue;
2947 }
2948 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)2949 angle::Result TextureStorage11_3D::createUAVForImage(const gl::Context *context,
2950                                                      int level,
2951                                                      DXGI_FORMAT format,
2952                                                      const TextureHelper11 &texture,
2953                                                      d3d11::SharedUAV *outUAV)
2954 {
2955     ASSERT(outUAV);
2956     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
2957     uavDesc.Format                = format;
2958     uavDesc.ViewDimension         = D3D11_UAV_DIMENSION_TEXTURE3D;
2959     uavDesc.Texture3D.MipSlice    = mTopLevel + level;
2960     uavDesc.Texture3D.FirstWSlice = 0;
2961     uavDesc.Texture3D.WSize       = mTextureDepth;
2962     ANGLE_TRY(
2963         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
2964     outUAV->setDebugName("TexStorage3D.UAVForImage");
2965     return angle::Result::Continue;
2966 }
2967 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const2968 angle::Result TextureStorage11_3D::findRenderTarget(const gl::Context *context,
2969                                                     const gl::ImageIndex &index,
2970                                                     GLsizei samples,
2971                                                     RenderTargetD3D **outRT) const
2972 {
2973     const int mipLevel = index.getLevelIndex();
2974     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2975 
2976     if (!index.hasLayer())
2977     {
2978         ASSERT(outRT);
2979         *outRT = mLevelRenderTargets[mipLevel].get();
2980         return angle::Result::Continue;
2981     }
2982 
2983     const int layer = index.getLayerIndex();
2984 
2985     LevelLayerKey key(mipLevel, layer);
2986     if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
2987     {
2988         ASSERT(outRT);
2989         *outRT = nullptr;
2990         return angle::Result::Continue;
2991     }
2992 
2993     ASSERT(outRT);
2994     *outRT = mLevelLayerRenderTargets.at(key).get();
2995     return angle::Result::Continue;
2996 }
2997 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)2998 angle::Result TextureStorage11_3D::getRenderTarget(const gl::Context *context,
2999                                                    const gl::ImageIndex &index,
3000                                                    GLsizei samples,
3001                                                    RenderTargetD3D **outRT)
3002 {
3003     const int mipLevel = index.getLevelIndex();
3004     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3005 
3006     ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
3007 
3008     Context11 *context11 = GetImplAs<Context11>(context);
3009 
3010     if (!index.hasLayer())
3011     {
3012         if (!mLevelRenderTargets[mipLevel])
3013         {
3014             const TextureHelper11 *texture = nullptr;
3015             ANGLE_TRY(getResource(context, &texture));
3016 
3017             const d3d11::SharedSRV *srv = nullptr;
3018             ANGLE_TRY(getSRVLevel(context, mipLevel, false, &srv));
3019 
3020             const d3d11::SharedSRV *blitSRV = nullptr;
3021             ANGLE_TRY(getSRVLevel(context, mipLevel, true, &blitSRV));
3022 
3023             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3024             rtvDesc.Format                = mFormatInfo.rtvFormat;
3025             rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
3026             rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
3027             rtvDesc.Texture3D.FirstWSlice = 0;
3028             rtvDesc.Texture3D.WSize       = static_cast<UINT>(-1);
3029 
3030             d3d11::RenderTargetView rtv;
3031             ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
3032             rtv.setDebugName("TexStorage3D.RTV");
3033 
3034             mLevelRenderTargets[mipLevel].reset(new TextureRenderTarget11(
3035                 std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat,
3036                 getFormatSet(), getLevelWidth(mipLevel), getLevelHeight(mipLevel),
3037                 getLevelDepth(mipLevel), 0));
3038         }
3039 
3040         ASSERT(outRT);
3041         *outRT = mLevelRenderTargets[mipLevel].get();
3042         return angle::Result::Continue;
3043     }
3044 
3045     const int layer = index.getLayerIndex();
3046 
3047     LevelLayerKey key(mipLevel, layer);
3048     if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
3049     {
3050         const TextureHelper11 *texture = nullptr;
3051         ANGLE_TRY(getResource(context, &texture));
3052 
3053         // TODO, what kind of SRV is expected here?
3054         const d3d11::SharedSRV srv;
3055         const d3d11::SharedSRV blitSRV;
3056 
3057         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3058         rtvDesc.Format                = mFormatInfo.rtvFormat;
3059         rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
3060         rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
3061         rtvDesc.Texture3D.FirstWSlice = layer;
3062         rtvDesc.Texture3D.WSize       = 1;
3063 
3064         d3d11::RenderTargetView rtv;
3065         ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
3066         rtv.setDebugName("TexStorage3D.LayerRTV");
3067 
3068         mLevelLayerRenderTargets[key].reset(new TextureRenderTarget11(
3069             std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3070             getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
3071     }
3072 
3073     ASSERT(outRT);
3074     *outRT = mLevelLayerRenderTargets[key].get();
3075     return angle::Result::Continue;
3076 }
3077 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)3078 angle::Result TextureStorage11_3D::getSwizzleTexture(const gl::Context *context,
3079                                                      const TextureHelper11 **outTexture)
3080 {
3081     ASSERT(outTexture);
3082 
3083     if (!mSwizzleTexture.valid())
3084     {
3085         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
3086 
3087         D3D11_TEXTURE3D_DESC desc;
3088         desc.Width          = mTextureWidth;
3089         desc.Height         = mTextureHeight;
3090         desc.Depth          = mTextureDepth;
3091         desc.MipLevels      = mMipLevels;
3092         desc.Format         = format.texFormat;
3093         desc.Usage          = D3D11_USAGE_DEFAULT;
3094         desc.BindFlags      = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
3095         desc.CPUAccessFlags = 0;
3096         desc.MiscFlags      = 0;
3097 
3098         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
3099                                              &mSwizzleTexture));
3100         mSwizzleTexture.setDebugName("TexStorage3D.SwizzleTexture");
3101     }
3102 
3103     *outTexture = &mSwizzleTexture;
3104     return angle::Result::Continue;
3105 }
3106 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)3107 angle::Result TextureStorage11_3D::getSwizzleRenderTarget(const gl::Context *context,
3108                                                           int mipLevel,
3109                                                           const d3d11::RenderTargetView **outRTV)
3110 {
3111     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3112     ASSERT(outRTV);
3113 
3114     if (!mSwizzleRenderTargets[mipLevel].valid())
3115     {
3116         const TextureHelper11 *swizzleTexture = nullptr;
3117         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
3118 
3119         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3120         rtvDesc.Format =
3121             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
3122         rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
3123         rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
3124         rtvDesc.Texture3D.FirstWSlice = 0;
3125         rtvDesc.Texture3D.WSize       = static_cast<UINT>(-1);
3126 
3127         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3128                                               mSwizzleTexture.get(),
3129                                               &mSwizzleRenderTargets[mipLevel]));
3130         mSwizzleRenderTargets[mipLevel].setDebugName("TexStorage3D.SwizzleRTV");
3131     }
3132 
3133     *outRTV = &mSwizzleRenderTargets[mipLevel];
3134     return angle::Result::Continue;
3135 }
3136 
TextureStorage11_2DArray(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels)3137 TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer,
3138                                                    GLenum internalformat,
3139                                                    bool renderTarget,
3140                                                    GLsizei width,
3141                                                    GLsizei height,
3142                                                    GLsizei depth,
3143                                                    int levels)
3144     : TextureStorage11(
3145           renderer,
3146           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
3147           GetTextureMiscFlags(internalformat,
3148                               renderer->getRenderer11DeviceCaps(),
3149                               renderTarget,
3150                               levels),
3151           internalformat)
3152 {
3153     // adjust size if needed for compressed textures
3154     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
3155 
3156     mMipLevels     = mTopLevel + levels;
3157     mTextureWidth  = width;
3158     mTextureHeight = height;
3159     mTextureDepth  = depth;
3160 }
3161 
onDestroy(const gl::Context * context)3162 angle::Result TextureStorage11_2DArray::onDestroy(const gl::Context *context)
3163 {
3164     for (auto iter : mAssociatedImages)
3165     {
3166         if (iter.second)
3167         {
3168             iter.second->verifyAssociatedStorageValid(this);
3169 
3170             // We must let the Images recover their data before we delete it from the
3171             // TextureStorage.
3172             ANGLE_TRY(iter.second->recoverFromAssociatedStorage(context));
3173         }
3174     }
3175     mAssociatedImages.clear();
3176 
3177     return angle::Result::Continue;
3178 }
3179 
~TextureStorage11_2DArray()3180 TextureStorage11_2DArray::~TextureStorage11_2DArray() {}
3181 
associateImage(Image11 * image,const gl::ImageIndex & index)3182 void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
3183 {
3184     const GLint level       = index.getLevelIndex();
3185     const GLint layerTarget = index.getLayerIndex();
3186     const GLint numLayers   = index.getLayerCount();
3187 
3188     ASSERT(0 <= level && level < getLevelCount());
3189 
3190     if (0 <= level && level < getLevelCount())
3191     {
3192         LevelLayerRangeKey key(level, layerTarget, numLayers);
3193         mAssociatedImages[key] = image;
3194     }
3195 }
3196 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)3197 void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index,
3198                                                           Image11 *expectedImage)
3199 {
3200     const GLint level       = index.getLevelIndex();
3201     const GLint layerTarget = index.getLayerIndex();
3202     const GLint numLayers   = index.getLayerCount();
3203 
3204     LevelLayerRangeKey key(level, layerTarget, numLayers);
3205 
3206     // This validation check should never return false. It means the Image/TextureStorage
3207     // association is broken.
3208     bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
3209                      (mAssociatedImages[key] == expectedImage));
3210     ASSERT(retValue);
3211 }
3212 
3213 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)3214 void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index,
3215                                                  Image11 *expectedImage)
3216 {
3217     const GLint level       = index.getLevelIndex();
3218     const GLint layerTarget = index.getLayerIndex();
3219     const GLint numLayers   = index.getLayerCount();
3220 
3221     LevelLayerRangeKey key(level, layerTarget, numLayers);
3222 
3223     bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
3224                                     (mAssociatedImages[key] == expectedImage));
3225     ASSERT(imageAssociationCorrect);
3226     mAssociatedImages[key] = nullptr;
3227 }
3228 
3229 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
3230 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)3231 angle::Result TextureStorage11_2DArray::releaseAssociatedImage(const gl::Context *context,
3232                                                                const gl::ImageIndex &index,
3233                                                                Image11 *incomingImage)
3234 {
3235     const GLint level       = index.getLevelIndex();
3236     const GLint layerTarget = index.getLayerIndex();
3237     const GLint numLayers   = index.getLayerCount();
3238 
3239     LevelLayerRangeKey key(level, layerTarget, numLayers);
3240 
3241     if (mAssociatedImages.find(key) != mAssociatedImages.end())
3242     {
3243         if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage)
3244         {
3245             // Ensure that the Image is still associated with this TextureStorage.
3246             mAssociatedImages[key]->verifyAssociatedStorageValid(this);
3247 
3248             // Force the image to recover from storage before its data is overwritten.
3249             // This will reset mAssociatedImages[level] to nullptr too.
3250             ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage(context));
3251         }
3252     }
3253 
3254     return angle::Result::Continue;
3255 }
3256 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3257 angle::Result TextureStorage11_2DArray::getResource(const gl::Context *context,
3258                                                     const TextureHelper11 **outResource)
3259 {
3260     // if the width, height or depth is not positive this should be treated as an incomplete texture
3261     // we handle that here by skipping the d3d texture creation
3262     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
3263     {
3264         ASSERT(mMipLevels > 0);
3265 
3266         D3D11_TEXTURE2D_DESC desc;
3267         desc.Width              = mTextureWidth;
3268         desc.Height             = mTextureHeight;
3269         desc.MipLevels          = mMipLevels;
3270         desc.ArraySize          = mTextureDepth;
3271         desc.Format             = mFormatInfo.texFormat;
3272         desc.SampleDesc.Count   = 1;
3273         desc.SampleDesc.Quality = 0;
3274         desc.Usage              = D3D11_USAGE_DEFAULT;
3275         desc.BindFlags          = getBindFlags();
3276         desc.CPUAccessFlags     = 0;
3277         desc.MiscFlags          = getMiscFlags();
3278 
3279         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
3280                                              &mTexture));
3281         mTexture.setDebugName("TexStorage2DArray.Texture");
3282     }
3283 
3284     *outResource = &mTexture;
3285     return angle::Result::Continue;
3286 }
3287 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3288 angle::Result TextureStorage11_2DArray::createSRVForSampler(const gl::Context *context,
3289                                                             int baseLevel,
3290                                                             int mipLevels,
3291                                                             DXGI_FORMAT format,
3292                                                             const TextureHelper11 &texture,
3293                                                             d3d11::SharedSRV *outSRV)
3294 {
3295     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3296     srvDesc.Format                         = format;
3297     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3298     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
3299     srvDesc.Texture2DArray.MipLevels       = mipLevels;
3300     srvDesc.Texture2DArray.FirstArraySlice = 0;
3301     srvDesc.Texture2DArray.ArraySize       = mTextureDepth;
3302 
3303     ANGLE_TRY(
3304         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3305     outSRV->setDebugName("TexStorage2DArray.SRV");
3306 
3307     return angle::Result::Continue;
3308 }
3309 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3310 angle::Result TextureStorage11_2DArray::createSRVForImage(const gl::Context *context,
3311                                                           int level,
3312                                                           DXGI_FORMAT format,
3313                                                           const TextureHelper11 &texture,
3314                                                           d3d11::SharedSRV *outSRV)
3315 {
3316     ASSERT(outSRV);
3317     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3318     srvDesc.Format                         = format;
3319     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3320     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
3321     srvDesc.Texture2DArray.MipLevels       = 1;
3322     srvDesc.Texture2DArray.FirstArraySlice = 0;
3323     srvDesc.Texture2DArray.ArraySize       = mTextureDepth;
3324     ANGLE_TRY(
3325         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3326     outSRV->setDebugName("TexStorage2DArray.SRVForImage");
3327     return angle::Result::Continue;
3328 }
3329 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)3330 angle::Result TextureStorage11_2DArray::createUAVForImage(const gl::Context *context,
3331                                                           int level,
3332                                                           DXGI_FORMAT format,
3333                                                           const TextureHelper11 &texture,
3334                                                           d3d11::SharedUAV *outUAV)
3335 {
3336     ASSERT(outUAV);
3337     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
3338     uavDesc.Format                         = format;
3339     uavDesc.ViewDimension                  = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3340     uavDesc.Texture2DArray.MipSlice        = mTopLevel + level;
3341     uavDesc.Texture2DArray.FirstArraySlice = 0;
3342     uavDesc.Texture2DArray.ArraySize       = mTextureDepth;
3343     ANGLE_TRY(
3344         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
3345     outUAV->setDebugName("TexStorage2DArray.UAVForImage");
3346     return angle::Result::Continue;
3347 }
3348 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3349 angle::Result TextureStorage11_2DArray::findRenderTarget(const gl::Context *context,
3350                                                          const gl::ImageIndex &index,
3351                                                          GLsizei samples,
3352                                                          RenderTargetD3D **outRT) const
3353 {
3354     ASSERT(index.hasLayer());
3355 
3356     const int mipLevel  = index.getLevelIndex();
3357     const int layer     = index.getLayerIndex();
3358     const int numLayers = index.getLayerCount();
3359 
3360     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3361 
3362     LevelLayerRangeKey key(mipLevel, layer, numLayers);
3363     if (mRenderTargets.find(key) == mRenderTargets.end())
3364     {
3365         ASSERT(outRT);
3366         *outRT = nullptr;
3367         return angle::Result::Continue;
3368     }
3369 
3370     ASSERT(outRT);
3371     *outRT = mRenderTargets.at(key).get();
3372     return angle::Result::Continue;
3373 }
3374 
createRenderTargetSRV(const gl::Context * context,const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const3375 angle::Result TextureStorage11_2DArray::createRenderTargetSRV(const gl::Context *context,
3376                                                               const TextureHelper11 &texture,
3377                                                               const gl::ImageIndex &index,
3378                                                               DXGI_FORMAT resourceFormat,
3379                                                               d3d11::SharedSRV *srv) const
3380 {
3381     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3382     srvDesc.Format                         = resourceFormat;
3383     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3384     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
3385     srvDesc.Texture2DArray.MipLevels       = 1;
3386     srvDesc.Texture2DArray.FirstArraySlice = index.getLayerIndex();
3387     srvDesc.Texture2DArray.ArraySize       = index.getLayerCount();
3388 
3389     ANGLE_TRY(
3390         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
3391 
3392     return angle::Result::Continue;
3393 }
3394 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)3395 angle::Result TextureStorage11_2DArray::getRenderTarget(const gl::Context *context,
3396                                                         const gl::ImageIndex &index,
3397                                                         GLsizei samples,
3398                                                         RenderTargetD3D **outRT)
3399 {
3400     ASSERT(index.hasLayer());
3401 
3402     const int mipLevel  = index.getLevelIndex();
3403     const int layer     = index.getLayerIndex();
3404     const int numLayers = index.getLayerCount();
3405 
3406     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3407 
3408     LevelLayerRangeKey key(mipLevel, layer, numLayers);
3409     if (mRenderTargets.find(key) == mRenderTargets.end())
3410     {
3411         const TextureHelper11 *texture = nullptr;
3412         ANGLE_TRY(getResource(context, &texture));
3413         d3d11::SharedSRV srv;
3414         ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
3415         d3d11::SharedSRV blitSRV;
3416         if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
3417         {
3418             ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
3419                                             &blitSRV));
3420         }
3421         else
3422         {
3423             blitSRV = srv.makeCopy();
3424         }
3425 
3426         srv.setDebugName("TexStorage2DArray.RenderTargetSRV");
3427 
3428         if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
3429         {
3430             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3431             rtvDesc.Format                         = mFormatInfo.rtvFormat;
3432             rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
3433             rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
3434             rtvDesc.Texture2DArray.FirstArraySlice = layer;
3435             rtvDesc.Texture2DArray.ArraySize       = numLayers;
3436 
3437             d3d11::RenderTargetView rtv;
3438             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3439                                                   texture->get(), &rtv));
3440             rtv.setDebugName("TexStorage2DArray.RenderTargetRTV");
3441 
3442             mRenderTargets[key].reset(new TextureRenderTarget11(
3443                 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3444                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
3445         }
3446         else
3447         {
3448             ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
3449 
3450             D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
3451             dsvDesc.Format                         = mFormatInfo.dsvFormat;
3452             dsvDesc.ViewDimension                  = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
3453             dsvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
3454             dsvDesc.Texture2DArray.FirstArraySlice = layer;
3455             dsvDesc.Texture2DArray.ArraySize       = numLayers;
3456             dsvDesc.Flags                          = 0;
3457 
3458             d3d11::DepthStencilView dsv;
3459             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), dsvDesc,
3460                                                   texture->get(), &dsv));
3461             dsv.setDebugName("TexStorage2DArray.RenderTargetDSV");
3462 
3463             mRenderTargets[key].reset(new TextureRenderTarget11(
3464                 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
3465                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
3466         }
3467     }
3468 
3469     ASSERT(outRT);
3470     *outRT = mRenderTargets[key].get();
3471     return angle::Result::Continue;
3472 }
3473 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)3474 angle::Result TextureStorage11_2DArray::getSwizzleTexture(const gl::Context *context,
3475                                                           const TextureHelper11 **outTexture)
3476 {
3477     if (!mSwizzleTexture.valid())
3478     {
3479         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
3480 
3481         D3D11_TEXTURE2D_DESC desc;
3482         desc.Width              = mTextureWidth;
3483         desc.Height             = mTextureHeight;
3484         desc.MipLevels          = mMipLevels;
3485         desc.ArraySize          = mTextureDepth;
3486         desc.Format             = format.texFormat;
3487         desc.SampleDesc.Count   = 1;
3488         desc.SampleDesc.Quality = 0;
3489         desc.Usage              = D3D11_USAGE_DEFAULT;
3490         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
3491         desc.CPUAccessFlags     = 0;
3492         desc.MiscFlags          = 0;
3493 
3494         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
3495                                              &mSwizzleTexture));
3496         mSwizzleTexture.setDebugName("TexStorage2DArray.SwizzleTexture");
3497     }
3498 
3499     *outTexture = &mSwizzleTexture;
3500     return angle::Result::Continue;
3501 }
3502 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)3503 angle::Result TextureStorage11_2DArray::getSwizzleRenderTarget(
3504     const gl::Context *context,
3505     int mipLevel,
3506     const d3d11::RenderTargetView **outRTV)
3507 {
3508     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3509     ASSERT(outRTV);
3510 
3511     if (!mSwizzleRenderTargets[mipLevel].valid())
3512     {
3513         const TextureHelper11 *swizzleTexture = nullptr;
3514         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
3515 
3516         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3517         rtvDesc.Format =
3518             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
3519         rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
3520         rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
3521         rtvDesc.Texture2DArray.FirstArraySlice = 0;
3522         rtvDesc.Texture2DArray.ArraySize       = mTextureDepth;
3523 
3524         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3525                                               mSwizzleTexture.get(),
3526                                               &mSwizzleRenderTargets[mipLevel]));
3527     }
3528 
3529     *outRTV = &mSwizzleRenderTargets[mipLevel];
3530     return angle::Result::Continue;
3531 }
3532 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)3533 angle::Result TextureStorage11_2DArray::ensureDropStencilTexture(const gl::Context *context,
3534                                                                  DropStencil *dropStencilOut)
3535 {
3536     if (mDropStencilTexture.valid())
3537     {
3538         *dropStencilOut = DropStencil::ALREADY_EXISTS;
3539         return angle::Result::Continue;
3540     }
3541 
3542     D3D11_TEXTURE2D_DESC dropDesc = {};
3543     dropDesc.ArraySize            = mTextureDepth;
3544     dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
3545     dropDesc.CPUAccessFlags       = 0;
3546     dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
3547     dropDesc.Height               = mTextureHeight;
3548     dropDesc.MipLevels            = mMipLevels;
3549     dropDesc.MiscFlags            = 0;
3550     dropDesc.SampleDesc.Count     = 1;
3551     dropDesc.SampleDesc.Quality   = 0;
3552     dropDesc.Usage                = D3D11_USAGE_DEFAULT;
3553     dropDesc.Width                = mTextureWidth;
3554 
3555     const auto &format =
3556         d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
3557     ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
3558                                          &mDropStencilTexture));
3559     mDropStencilTexture.setDebugName("TexStorage2DArray.DropStencil");
3560 
3561     std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
3562 
3563     ANGLE_TRY(initDropStencilTexture(
3564         context, gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
3565 
3566     *dropStencilOut = DropStencil::CREATED;
3567     return angle::Result::Continue;
3568 }
3569 
TextureStorage11_2DMultisample(Renderer11 * renderer,GLenum internalformat,GLsizei width,GLsizei height,int levels,int samples,bool fixedSampleLocations)3570 TextureStorage11_2DMultisample::TextureStorage11_2DMultisample(Renderer11 *renderer,
3571                                                                GLenum internalformat,
3572                                                                GLsizei width,
3573                                                                GLsizei height,
3574                                                                int levels,
3575                                                                int samples,
3576                                                                bool fixedSampleLocations)
3577     : TextureStorage11ImmutableBase(
3578           renderer,
3579           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true),
3580           GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels),
3581           internalformat),
3582       mTexture(),
3583       mRenderTarget(nullptr)
3584 {
3585     // There are no multisampled compressed formats, so there's no need to adjust texture size
3586     // according to block size.
3587     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockWidth <= 1);
3588     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockHeight <= 1);
3589 
3590     mMipLevels            = 1;
3591     mTextureWidth         = width;
3592     mTextureHeight        = height;
3593     mTextureDepth         = 1;
3594     mSamples              = samples;
3595     mFixedSampleLocations = fixedSampleLocations;
3596 }
3597 
onDestroy(const gl::Context * context)3598 angle::Result TextureStorage11_2DMultisample::onDestroy(const gl::Context *context)
3599 {
3600     mRenderTarget.reset();
3601     return angle::Result::Continue;
3602 }
3603 
~TextureStorage11_2DMultisample()3604 TextureStorage11_2DMultisample::~TextureStorage11_2DMultisample() {}
3605 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)3606 angle::Result TextureStorage11_2DMultisample::copyToStorage(const gl::Context *context,
3607                                                             TextureStorage *destStorage)
3608 {
3609     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3610     return angle::Result::Stop;
3611 }
3612 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3613 angle::Result TextureStorage11_2DMultisample::getResource(const gl::Context *context,
3614                                                           const TextureHelper11 **outResource)
3615 {
3616     ANGLE_TRY(ensureTextureExists(context, 1));
3617 
3618     *outResource = &mTexture;
3619     return angle::Result::Continue;
3620 }
3621 
ensureTextureExists(const gl::Context * context,int mipLevels)3622 angle::Result TextureStorage11_2DMultisample::ensureTextureExists(const gl::Context *context,
3623                                                                   int mipLevels)
3624 {
3625     // For Multisampled textures, mipLevels always equals 1.
3626     ASSERT(mipLevels == 1);
3627 
3628     // if the width or height is not positive this should be treated as an incomplete texture
3629     // we handle that here by skipping the d3d texture creation
3630     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
3631     {
3632         D3D11_TEXTURE2D_DESC desc;
3633         ZeroMemory(&desc, sizeof(desc));
3634         desc.Width          = mTextureWidth;  // Compressed texture size constraints?
3635         desc.Height         = mTextureHeight;
3636         desc.MipLevels      = mipLevels;
3637         desc.ArraySize      = 1;
3638         desc.Format         = mFormatInfo.texFormat;
3639         desc.Usage          = D3D11_USAGE_DEFAULT;
3640         desc.BindFlags      = getBindFlags() & ~D3D11_BIND_UNORDERED_ACCESS;
3641         desc.CPUAccessFlags = 0;
3642         desc.MiscFlags      = getMiscFlags();
3643 
3644         const gl::TextureCaps &textureCaps =
3645             mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
3646         GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
3647         desc.SampleDesc.Count   = (supportedSamples == 0) ? 1 : supportedSamples;
3648         desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples);
3649 
3650         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
3651                                              &mTexture));
3652         mTexture.setDebugName("TexStorage2DMS.Texture");
3653     }
3654 
3655     return angle::Result::Continue;
3656 }
3657 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3658 angle::Result TextureStorage11_2DMultisample::findRenderTarget(const gl::Context *context,
3659                                                                const gl::ImageIndex &index,
3660                                                                GLsizei samples,
3661                                                                RenderTargetD3D **outRT) const
3662 {
3663     ASSERT(!index.hasLayer());
3664 
3665     const int level = index.getLevelIndex();
3666     ASSERT(level == 0);
3667 
3668     ASSERT(outRT);
3669     *outRT = mRenderTarget.get();
3670     return angle::Result::Continue;
3671 }
3672 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)3673 angle::Result TextureStorage11_2DMultisample::getRenderTarget(const gl::Context *context,
3674                                                               const gl::ImageIndex &index,
3675                                                               GLsizei samples,
3676                                                               RenderTargetD3D **outRT)
3677 {
3678     ASSERT(!index.hasLayer());
3679 
3680     const int level = index.getLevelIndex();
3681     ASSERT(level == 0);
3682 
3683     ASSERT(outRT);
3684     if (mRenderTarget)
3685     {
3686         *outRT = mRenderTarget.get();
3687         return angle::Result::Continue;
3688     }
3689 
3690     const TextureHelper11 *texture = nullptr;
3691     ANGLE_TRY(getResource(context, &texture));
3692 
3693     const d3d11::SharedSRV *srv = nullptr;
3694     ANGLE_TRY(getSRVLevel(context, level, false, &srv));
3695 
3696     const d3d11::SharedSRV *blitSRV = nullptr;
3697     ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
3698 
3699     Context11 *context11 = GetImplAs<Context11>(context);
3700 
3701     if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
3702     {
3703         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3704         rtvDesc.Format        = mFormatInfo.rtvFormat;
3705         rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
3706 
3707         d3d11::RenderTargetView rtv;
3708         ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
3709 
3710         mRenderTarget.reset(new TextureRenderTarget11(
3711             std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3712             getLevelWidth(level), getLevelHeight(level), 1, mSamples));
3713 
3714         *outRT = mRenderTarget.get();
3715         return angle::Result::Continue;
3716     }
3717 
3718     ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
3719 
3720     D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
3721     dsvDesc.Format        = mFormatInfo.dsvFormat;
3722     dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
3723     dsvDesc.Flags         = 0;
3724 
3725     d3d11::DepthStencilView dsv;
3726     ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
3727 
3728     mRenderTarget.reset(new TextureRenderTarget11(
3729         std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
3730         getLevelWidth(level), getLevelHeight(level), 1, mSamples));
3731 
3732     *outRT = mRenderTarget.get();
3733     return angle::Result::Continue;
3734 }
3735 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3736 angle::Result TextureStorage11_2DMultisample::createSRVForSampler(const gl::Context *context,
3737                                                                   int baseLevel,
3738                                                                   int mipLevels,
3739                                                                   DXGI_FORMAT format,
3740                                                                   const TextureHelper11 &texture,
3741                                                                   d3d11::SharedSRV *outSRV)
3742 {
3743     ASSERT(outSRV);
3744 
3745     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3746     srvDesc.Format        = format;
3747     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3748 
3749     ANGLE_TRY(
3750         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3751     outSRV->setDebugName("TexStorage2DMS.SRV");
3752     return angle::Result::Continue;
3753 }
3754 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)3755 angle::Result TextureStorage11_2DMultisample::getSwizzleTexture(const gl::Context *context,
3756                                                                 const TextureHelper11 **outTexture)
3757 {
3758     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3759     return angle::Result::Stop;
3760 }
3761 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)3762 angle::Result TextureStorage11_2DMultisample::getSwizzleRenderTarget(
3763     const gl::Context *context,
3764     int mipLevel,
3765     const d3d11::RenderTargetView **outRTV)
3766 {
3767     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3768     return angle::Result::Stop;
3769 }
3770 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)3771 angle::Result TextureStorage11_2DMultisample::ensureDropStencilTexture(const gl::Context *context,
3772                                                                        DropStencil *dropStencilOut)
3773 {
3774     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3775     return angle::Result::Stop;
3776 }
3777 
TextureStorage11_2DMultisampleArray(Renderer11 * renderer,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,int levels,int samples,bool fixedSampleLocations)3778 TextureStorage11_2DMultisampleArray::TextureStorage11_2DMultisampleArray(Renderer11 *renderer,
3779                                                                          GLenum internalformat,
3780                                                                          GLsizei width,
3781                                                                          GLsizei height,
3782                                                                          GLsizei depth,
3783                                                                          int levels,
3784                                                                          int samples,
3785                                                                          bool fixedSampleLocations)
3786     : TextureStorage11ImmutableBase(
3787           renderer,
3788           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true),
3789           GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels),
3790           internalformat),
3791       mTexture()
3792 {
3793     // There are no multisampled compressed formats, so there's no need to adjust texture size
3794     // according to block size.
3795     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockWidth <= 1);
3796     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockHeight <= 1);
3797 
3798     mMipLevels            = 1;
3799     mTextureWidth         = width;
3800     mTextureHeight        = height;
3801     mTextureDepth         = depth;
3802     mSamples              = samples;
3803     mFixedSampleLocations = fixedSampleLocations;
3804 }
3805 
onDestroy(const gl::Context * context)3806 angle::Result TextureStorage11_2DMultisampleArray::onDestroy(const gl::Context *context)
3807 {
3808     return angle::Result::Continue;
3809 }
3810 
~TextureStorage11_2DMultisampleArray()3811 TextureStorage11_2DMultisampleArray::~TextureStorage11_2DMultisampleArray() {}
3812 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)3813 angle::Result TextureStorage11_2DMultisampleArray::copyToStorage(const gl::Context *context,
3814                                                                  TextureStorage *destStorage)
3815 {
3816     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3817     return angle::Result::Stop;
3818 }
3819 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3820 angle::Result TextureStorage11_2DMultisampleArray::getResource(const gl::Context *context,
3821                                                                const TextureHelper11 **outResource)
3822 {
3823     ANGLE_TRY(ensureTextureExists(context, 1));
3824 
3825     *outResource = &mTexture;
3826     return angle::Result::Continue;
3827 }
3828 
ensureTextureExists(const gl::Context * context,int mipLevels)3829 angle::Result TextureStorage11_2DMultisampleArray::ensureTextureExists(const gl::Context *context,
3830                                                                        int mipLevels)
3831 {
3832     // For multisampled textures, mipLevels always equals 1.
3833     ASSERT(mipLevels == 1);
3834 
3835     // if the width or height is not positive this should be treated as an incomplete texture
3836     // we handle that here by skipping the d3d texture creation
3837     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
3838     {
3839         D3D11_TEXTURE2D_DESC desc;
3840         ZeroMemory(&desc, sizeof(desc));
3841         desc.Width          = mTextureWidth;
3842         desc.Height         = mTextureHeight;
3843         desc.MipLevels      = mipLevels;
3844         desc.ArraySize      = mTextureDepth;
3845         desc.Format         = mFormatInfo.texFormat;
3846         desc.Usage          = D3D11_USAGE_DEFAULT;
3847         desc.BindFlags      = getBindFlags() & ~D3D11_BIND_UNORDERED_ACCESS;
3848         desc.CPUAccessFlags = 0;
3849         desc.MiscFlags      = getMiscFlags();
3850 
3851         const gl::TextureCaps &textureCaps =
3852             mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
3853         GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
3854         desc.SampleDesc.Count   = (supportedSamples == 0) ? 1 : supportedSamples;
3855         desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples);
3856 
3857         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
3858                                              &mTexture));
3859         mTexture.setDebugName("TexStorage2DMSArray.Texture");
3860     }
3861 
3862     return angle::Result::Continue;
3863 }
3864 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3865 angle::Result TextureStorage11_2DMultisampleArray::findRenderTarget(const gl::Context *context,
3866                                                                     const gl::ImageIndex &index,
3867                                                                     GLsizei samples,
3868                                                                     RenderTargetD3D **outRT) const
3869 {
3870     ASSERT(index.hasLayer());
3871 
3872     const int mipLevel = index.getLevelIndex();
3873     ASSERT(mipLevel == 0);
3874     const int layer     = index.getLayerIndex();
3875     const int numLayers = index.getLayerCount();
3876 
3877     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3878 
3879     TextureStorage11_2DArray::LevelLayerRangeKey key(mipLevel, layer, numLayers);
3880     if (mRenderTargets.find(key) == mRenderTargets.end())
3881     {
3882         ASSERT(outRT);
3883         *outRT = nullptr;
3884         return angle::Result::Continue;
3885     }
3886 
3887     ASSERT(outRT);
3888     *outRT = mRenderTargets.at(key).get();
3889     return angle::Result::Continue;
3890 }
3891 
createRenderTargetSRV(const gl::Context * context,const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const3892 angle::Result TextureStorage11_2DMultisampleArray::createRenderTargetSRV(
3893     const gl::Context *context,
3894     const TextureHelper11 &texture,
3895     const gl::ImageIndex &index,
3896     DXGI_FORMAT resourceFormat,
3897     d3d11::SharedSRV *srv) const
3898 {
3899     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3900     srvDesc.Format                           = resourceFormat;
3901     srvDesc.ViewDimension                    = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3902     srvDesc.Texture2DMSArray.FirstArraySlice = index.getLayerIndex();
3903     srvDesc.Texture2DMSArray.ArraySize       = index.getLayerCount();
3904 
3905     ANGLE_TRY(
3906         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
3907 
3908     return angle::Result::Continue;
3909 }
3910 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)3911 angle::Result TextureStorage11_2DMultisampleArray::getRenderTarget(const gl::Context *context,
3912                                                                    const gl::ImageIndex &index,
3913                                                                    GLsizei samples,
3914                                                                    RenderTargetD3D **outRT)
3915 {
3916     ASSERT(index.hasLayer());
3917 
3918     const int mipLevel = index.getLevelIndex();
3919     ASSERT(mipLevel == 0);
3920     const int layer     = index.getLayerIndex();
3921     const int numLayers = index.getLayerCount();
3922 
3923     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3924 
3925     TextureStorage11_2DArray::LevelLayerRangeKey key(mipLevel, layer, numLayers);
3926     if (mRenderTargets.find(key) == mRenderTargets.end())
3927     {
3928         const TextureHelper11 *texture = nullptr;
3929         ANGLE_TRY(getResource(context, &texture));
3930         d3d11::SharedSRV srv;
3931         ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
3932         d3d11::SharedSRV blitSRV;
3933         if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
3934         {
3935             ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
3936                                             &blitSRV));
3937         }
3938         else
3939         {
3940             blitSRV = srv.makeCopy();
3941         }
3942 
3943         srv.setDebugName("TexStorage2DMSArray.RenderTargetSRV");
3944 
3945         if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
3946         {
3947             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3948             rtvDesc.Format                           = mFormatInfo.rtvFormat;
3949             rtvDesc.ViewDimension                    = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
3950             rtvDesc.Texture2DMSArray.FirstArraySlice = layer;
3951             rtvDesc.Texture2DMSArray.ArraySize       = numLayers;
3952 
3953             d3d11::RenderTargetView rtv;
3954             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3955                                                   texture->get(), &rtv));
3956             rtv.setDebugName("TexStorage2DMSArray.RenderTargetRTV");
3957 
3958             mRenderTargets[key].reset(new TextureRenderTarget11(
3959                 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3960                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, mSamples));
3961         }
3962         else
3963         {
3964             ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
3965 
3966             D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
3967             dsvDesc.Format                           = mFormatInfo.dsvFormat;
3968             dsvDesc.ViewDimension                    = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
3969             dsvDesc.Texture2DMSArray.FirstArraySlice = layer;
3970             dsvDesc.Texture2DMSArray.ArraySize       = numLayers;
3971             dsvDesc.Flags                            = 0;
3972 
3973             d3d11::DepthStencilView dsv;
3974             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), dsvDesc,
3975                                                   texture->get(), &dsv));
3976             dsv.setDebugName("TexStorage2DMSArray.RenderTargetDSV");
3977 
3978             mRenderTargets[key].reset(new TextureRenderTarget11(
3979                 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
3980                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, mSamples));
3981         }
3982     }
3983 
3984     ASSERT(outRT);
3985     *outRT = mRenderTargets[key].get();
3986     return angle::Result::Continue;
3987 }
3988 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3989 angle::Result TextureStorage11_2DMultisampleArray::createSRVForSampler(
3990     const gl::Context *context,
3991     int baseLevel,
3992     int mipLevels,
3993     DXGI_FORMAT format,
3994     const TextureHelper11 &texture,
3995     d3d11::SharedSRV *outSRV)
3996 {
3997     ASSERT(outSRV);
3998 
3999     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
4000     srvDesc.Format                           = format;
4001     srvDesc.ViewDimension                    = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
4002     srvDesc.Texture2DMSArray.FirstArraySlice = 0;
4003     srvDesc.Texture2DMSArray.ArraySize       = mTextureDepth;
4004 
4005     ANGLE_TRY(
4006         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
4007     outSRV->setDebugName("TexStorage2DMSArray.SRV");
4008     return angle::Result::Continue;
4009 }
4010 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)4011 angle::Result TextureStorage11_2DMultisampleArray::getSwizzleTexture(
4012     const gl::Context *context,
4013     const TextureHelper11 **outTexture)
4014 {
4015     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
4016     return angle::Result::Stop;
4017 }
4018 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)4019 angle::Result TextureStorage11_2DMultisampleArray::getSwizzleRenderTarget(
4020     const gl::Context *context,
4021     int mipLevel,
4022     const d3d11::RenderTargetView **outRTV)
4023 {
4024     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
4025     return angle::Result::Stop;
4026 }
4027 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)4028 angle::Result TextureStorage11_2DMultisampleArray::ensureDropStencilTexture(
4029     const gl::Context *context,
4030     DropStencil *dropStencilOut)
4031 {
4032     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
4033     return angle::Result::Stop;
4034 }
4035 
4036 }  // namespace rx
4037