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