• 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, mTextureLabel)));
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 
onLabelUpdate()1042 void TextureStorage11_2D::onLabelUpdate()
1043 {
1044     if (mTexture.valid())
1045     {
1046         mTexture.setKHRDebugLabel(&mTextureLabel);
1047     }
1048     if (mLevelZeroTexture.valid())
1049     {
1050         mLevelZeroTexture.setKHRDebugLabel(&mTextureLabel);
1051     }
1052     if (mSwizzleTexture.valid())
1053     {
1054         mSwizzleTexture.setKHRDebugLabel(&mTextureLabel);
1055     }
1056 }
1057 
onDestroy(const gl::Context * context)1058 angle::Result TextureStorage11_2D::onDestroy(const gl::Context *context)
1059 {
1060     for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1061     {
1062         if (mAssociatedImages[i] != nullptr)
1063         {
1064             mAssociatedImages[i]->verifyAssociatedStorageValid(this);
1065 
1066             // We must let the Images recover their data before we delete it from the
1067             // TextureStorage.
1068             ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
1069         }
1070     }
1071 
1072     if (mHasKeyedMutex)
1073     {
1074         // If the keyed mutex is released that will unbind it and cause the state cache to become
1075         // desynchronized.
1076         mRenderer->getStateManager()->invalidateBoundViews();
1077     }
1078 
1079     return angle::Result::Continue;
1080 }
1081 
~TextureStorage11_2D()1082 TextureStorage11_2D::~TextureStorage11_2D() {}
1083 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1084 angle::Result TextureStorage11_2D::copyToStorage(const gl::Context *context,
1085                                                  TextureStorage *destStorage)
1086 {
1087     ASSERT(destStorage);
1088 
1089     TextureStorage11_2D *dest11           = GetAs<TextureStorage11_2D>(destStorage);
1090     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
1091 
1092     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
1093     {
1094         // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
1095         // corresponding textures in destStorage.
1096         if (mTexture.valid())
1097         {
1098             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
1099 
1100             const TextureHelper11 *destResource = nullptr;
1101             ANGLE_TRY(dest11->getResource(context, &destResource));
1102 
1103             immediateContext->CopyResource(destResource->get(), mTexture.get());
1104         }
1105 
1106         if (mLevelZeroTexture.valid())
1107         {
1108             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
1109 
1110             const TextureHelper11 *destResource = nullptr;
1111             ANGLE_TRY(dest11->getResource(context, &destResource));
1112 
1113             immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
1114         }
1115 
1116         return angle::Result::Continue;
1117     }
1118 
1119     const TextureHelper11 *sourceResouce = nullptr;
1120     ANGLE_TRY(getResource(context, &sourceResouce));
1121 
1122     const TextureHelper11 *destResource = nullptr;
1123     ANGLE_TRY(dest11->getResource(context, &destResource));
1124 
1125     immediateContext->CopyResource(destResource->get(), sourceResouce->get());
1126     dest11->markDirty();
1127 
1128     return angle::Result::Continue;
1129 }
1130 
useLevelZeroWorkaroundTexture(const gl::Context * context,bool useLevelZeroTexture)1131 angle::Result TextureStorage11_2D::useLevelZeroWorkaroundTexture(const gl::Context *context,
1132                                                                  bool useLevelZeroTexture)
1133 {
1134     if (useLevelZeroTexture && mMipLevels > 1)
1135     {
1136         if (!mUseLevelZeroTexture && mTexture.valid())
1137         {
1138             ANGLE_TRY(ensureTextureExists(context, 1));
1139 
1140             // Pull data back from the mipped texture if necessary.
1141             ASSERT(mLevelZeroTexture.valid());
1142             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1143             deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(), 0, 0, 0, 0,
1144                                                  mTexture.get(), 0, nullptr);
1145         }
1146 
1147         mUseLevelZeroTexture = true;
1148     }
1149     else
1150     {
1151         if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
1152         {
1153             ANGLE_TRY(ensureTextureExists(context, mMipLevels));
1154 
1155             // Pull data back from the level zero texture if necessary.
1156             ASSERT(mTexture.valid());
1157             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1158             deviceContext->CopySubresourceRegion(mTexture.get(), 0, 0, 0, 0,
1159                                                  mLevelZeroTexture.get(), 0, nullptr);
1160         }
1161 
1162         mUseLevelZeroTexture = false;
1163     }
1164 
1165     return angle::Result::Continue;
1166 }
1167 
associateImage(Image11 * image,const gl::ImageIndex & index)1168 void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
1169 {
1170     const GLint level = index.getLevelIndex();
1171 
1172     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1173     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1174     {
1175         mAssociatedImages[level] = image;
1176     }
1177 }
1178 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)1179 void TextureStorage11_2D::verifyAssociatedImageValid(const gl::ImageIndex &index,
1180                                                      Image11 *expectedImage)
1181 {
1182     const GLint level = index.getLevelIndex();
1183 
1184     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1185     // This validation check should never return false. It means the Image/TextureStorage
1186     // association is broken.
1187     ASSERT(mAssociatedImages[level] == expectedImage);
1188 }
1189 
1190 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)1191 void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
1192 {
1193     const GLint level = index.getLevelIndex();
1194 
1195     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1196     ASSERT(mAssociatedImages[level] == expectedImage);
1197     mAssociatedImages[level] = nullptr;
1198 }
1199 
1200 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
1201 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)1202 angle::Result TextureStorage11_2D::releaseAssociatedImage(const gl::Context *context,
1203                                                           const gl::ImageIndex &index,
1204                                                           Image11 *incomingImage)
1205 {
1206     const GLint level = index.getLevelIndex();
1207 
1208     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1209 
1210     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1211     {
1212         // No need to let the old Image recover its data, if it is also the incoming Image.
1213         if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
1214         {
1215             // Ensure that the Image is still associated with this TextureStorage.
1216             mAssociatedImages[level]->verifyAssociatedStorageValid(this);
1217 
1218             // Force the image to recover from storage before its data is overwritten.
1219             // This will reset mAssociatedImages[level] to nullptr too.
1220             ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
1221         }
1222     }
1223 
1224     return angle::Result::Continue;
1225 }
1226 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1227 angle::Result TextureStorage11_2D::getResource(const gl::Context *context,
1228                                                const TextureHelper11 **outResource)
1229 {
1230     if (mUseLevelZeroTexture && mMipLevels > 1)
1231     {
1232         ANGLE_TRY(ensureTextureExists(context, 1));
1233 
1234         *outResource = &mLevelZeroTexture;
1235         return angle::Result::Continue;
1236     }
1237 
1238     ANGLE_TRY(ensureTextureExists(context, mMipLevels));
1239 
1240     *outResource = &mTexture;
1241     return angle::Result::Continue;
1242 }
1243 
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)1244 angle::Result TextureStorage11_2D::getMippedResource(const gl::Context *context,
1245                                                      const TextureHelper11 **outResource)
1246 {
1247     // This shouldn't be called unless the zero max LOD workaround is active.
1248     ASSERT(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
1249 
1250     ANGLE_TRY(ensureTextureExists(context, mMipLevels));
1251 
1252     *outResource = &mTexture;
1253     return angle::Result::Continue;
1254 }
1255 
ensureTextureExists(const gl::Context * context,int mipLevels)1256 angle::Result TextureStorage11_2D::ensureTextureExists(const gl::Context *context, int mipLevels)
1257 {
1258     // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
1259     ANGLE_TRY(resolveTexture(context));
1260     bool useLevelZeroTexture = mRenderer->getFeatures().zeroMaxLodWorkaround.enabled
1261                                    ? (mipLevels == 1) && (mMipLevels > 1)
1262                                    : false;
1263     TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
1264 
1265     // if the width or height is not positive this should be treated as an incomplete texture
1266     // we handle that here by skipping the d3d texture creation
1267     if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
1268     {
1269         ASSERT(mipLevels > 0);
1270 
1271         D3D11_TEXTURE2D_DESC desc;
1272         desc.Width              = mTextureWidth;  // Compressed texture size constraints?
1273         desc.Height             = mTextureHeight;
1274         desc.MipLevels          = mipLevels;
1275         desc.ArraySize          = 1;
1276         desc.Format             = mFormatInfo.texFormat;
1277         desc.SampleDesc.Count   = 1;
1278         desc.SampleDesc.Quality = 0;
1279         desc.Usage              = D3D11_USAGE_DEFAULT;
1280         desc.BindFlags          = getBindFlags();
1281         desc.CPUAccessFlags     = 0;
1282         desc.MiscFlags          = getMiscFlags();
1283 
1284         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
1285                                              outputTexture));
1286 
1287         if (useLevelZeroTexture)
1288         {
1289             outputTexture->setLabels("TexStorage2D.Level0Texture", &mTextureLabel);
1290         }
1291         else
1292         {
1293             outputTexture->setLabels("TexStorage2D.Texture", &mTextureLabel);
1294         }
1295     }
1296 
1297     return angle::Result::Continue;
1298 }
1299 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const1300 angle::Result TextureStorage11_2D::findRenderTarget(const gl::Context *context,
1301                                                     const gl::ImageIndex &index,
1302                                                     GLsizei samples,
1303                                                     RenderTargetD3D **outRT) const
1304 {
1305     ASSERT(!index.hasLayer());
1306 
1307     const int level = index.getLevelIndex();
1308     ASSERT(level >= 0 && level < getLevelCount());
1309 
1310     bool needMS = samples > 0;
1311     if (needMS)
1312     {
1313         return findMultisampledRenderTarget(context, index, samples, outRT);
1314     }
1315 
1316     ASSERT(outRT);
1317     if (mRenderTarget[level])
1318     {
1319         *outRT = mRenderTarget[level].get();
1320         return angle::Result::Continue;
1321     }
1322 
1323     if (mUseLevelZeroTexture)
1324     {
1325         ASSERT(level == 0);
1326         *outRT = mLevelZeroRenderTarget.get();
1327         return angle::Result::Continue;
1328     }
1329 
1330     *outRT = nullptr;
1331     return angle::Result::Continue;
1332 }
1333 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)1334 angle::Result TextureStorage11_2D::getRenderTarget(const gl::Context *context,
1335                                                    const gl::ImageIndex &index,
1336                                                    GLsizei samples,
1337                                                    RenderTargetD3D **outRT)
1338 {
1339     ASSERT(!index.hasLayer());
1340 
1341     const int level = index.getLevelIndex();
1342     ASSERT(level >= 0 && level < getLevelCount());
1343 
1344     bool needMS = samples > 0;
1345     if (needMS)
1346     {
1347         return getMultisampledRenderTarget(context, index, samples, outRT);
1348     }
1349     else
1350     {
1351         ANGLE_TRY(resolveTexture(context));
1352     }
1353 
1354     // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of
1355     // the GLES 2.0 spec, page 113 of version 2.0.25). Other parts of TextureStorage11_2D could
1356     // create RTVs on non-zero levels of the texture (e.g. generateMipmap).
1357     // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the
1358     // individual levels of the texture, so methods like generateMipmap can't do anything useful
1359     // with non-zero-level RTVs. Therefore if level > 0 on 9_3 then there's almost certainly
1360     // something wrong.
1361     ASSERT(
1362         !(mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0));
1363     ASSERT(outRT);
1364     if (mRenderTarget[level])
1365     {
1366         *outRT = mRenderTarget[level].get();
1367         return angle::Result::Continue;
1368     }
1369 
1370     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
1371     {
1372         ASSERT(level == 0);
1373         ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
1374     }
1375 
1376     const TextureHelper11 *texture = nullptr;
1377     ANGLE_TRY(getResource(context, &texture));
1378 
1379     const d3d11::SharedSRV *srv = nullptr;
1380     ANGLE_TRY(getSRVLevel(context, level, false, &srv));
1381 
1382     const d3d11::SharedSRV *blitSRV = nullptr;
1383     ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
1384 
1385     Context11 *context11 = GetImplAs<Context11>(context);
1386 
1387     if (mUseLevelZeroTexture)
1388     {
1389         if (!mLevelZeroRenderTarget)
1390         {
1391             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1392             rtvDesc.Format             = mFormatInfo.rtvFormat;
1393             rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
1394             rtvDesc.Texture2D.MipSlice = mTopLevel + level;
1395 
1396             d3d11::RenderTargetView rtv;
1397             ANGLE_TRY(
1398                 mRenderer->allocateResource(context11, rtvDesc, mLevelZeroTexture.get(), &rtv));
1399             rtv.setLabels("TexStorage2D.Level0RTV", &mTextureLabel);
1400 
1401             mLevelZeroRenderTarget.reset(new TextureRenderTarget11(
1402                 std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
1403                 mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
1404                 getLevelHeight(level), 1, 0));
1405         }
1406 
1407         *outRT = mLevelZeroRenderTarget.get();
1408         return angle::Result::Continue;
1409     }
1410 
1411     if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
1412     {
1413         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1414         rtvDesc.Format             = mFormatInfo.rtvFormat;
1415         rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
1416         rtvDesc.Texture2D.MipSlice = mTopLevel + level;
1417 
1418         d3d11::RenderTargetView rtv;
1419         ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
1420         rtv.setLabels("TexStorage2D.RTV", &mTextureLabel);
1421 
1422         mRenderTarget[level].reset(new TextureRenderTarget11(
1423             std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
1424             getLevelWidth(level), getLevelHeight(level), 1, 0));
1425 
1426         *outRT = mRenderTarget[level].get();
1427         return angle::Result::Continue;
1428     }
1429 
1430     ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
1431 
1432     D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
1433     dsvDesc.Format             = mFormatInfo.dsvFormat;
1434     dsvDesc.ViewDimension      = D3D11_DSV_DIMENSION_TEXTURE2D;
1435     dsvDesc.Texture2D.MipSlice = mTopLevel + level;
1436     dsvDesc.Flags              = 0;
1437 
1438     d3d11::DepthStencilView dsv;
1439     ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
1440     dsv.setLabels("TexStorage2D.DSV", &mTextureLabel);
1441 
1442     mRenderTarget[level].reset(new TextureRenderTarget11(
1443         std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
1444         getLevelWidth(level), getLevelHeight(level), 1, 0));
1445 
1446     *outRT = mRenderTarget[level].get();
1447     return angle::Result::Continue;
1448 }
1449 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1450 angle::Result TextureStorage11_2D::createSRVForSampler(const gl::Context *context,
1451                                                        int baseLevel,
1452                                                        int mipLevels,
1453                                                        DXGI_FORMAT format,
1454                                                        const TextureHelper11 &texture,
1455                                                        d3d11::SharedSRV *outSRV)
1456 {
1457     ASSERT(outSRV);
1458 
1459     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1460     srvDesc.Format                    = format;
1461     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
1462     srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
1463     srvDesc.Texture2D.MipLevels       = mipLevels;
1464 
1465     const TextureHelper11 *srvTexture = &texture;
1466 
1467     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
1468     {
1469         ASSERT(mTopLevel == 0);
1470         ASSERT(baseLevel == 0);
1471         // This code also assumes that the incoming texture equals either mLevelZeroTexture or
1472         // mTexture.
1473 
1474         if (mipLevels == 1 && mMipLevels > 1)
1475         {
1476             // We must use a SRV on the level-zero-only texture.
1477             ANGLE_TRY(ensureTextureExists(context, 1));
1478             srvTexture = &mLevelZeroTexture;
1479         }
1480         else
1481         {
1482             ASSERT(mipLevels == static_cast<int>(mMipLevels));
1483             ASSERT(mTexture.valid() && texture == mTexture);
1484             srvTexture = &mTexture;
1485         }
1486     }
1487 
1488     ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, srvTexture->get(),
1489                                           outSRV));
1490     outSRV->setLabels("TexStorage2D.SRV", &mTextureLabel);
1491 
1492     return angle::Result::Continue;
1493 }
1494 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1495 angle::Result TextureStorage11_2D::createSRVForImage(const gl::Context *context,
1496                                                      int level,
1497                                                      DXGI_FORMAT format,
1498                                                      const TextureHelper11 &texture,
1499                                                      d3d11::SharedSRV *outSRV)
1500 {
1501     ASSERT(outSRV);
1502     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1503     srvDesc.Format                    = format;
1504     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
1505     srvDesc.Texture2D.MostDetailedMip = mTopLevel + level;
1506     srvDesc.Texture2D.MipLevels       = 1;
1507     ANGLE_TRY(
1508         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
1509     outSRV->setLabels("TexStorage2D.SRVForImage", &mTextureLabel);
1510     return angle::Result::Continue;
1511 }
1512 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)1513 angle::Result TextureStorage11_2D::createUAVForImage(const gl::Context *context,
1514                                                      int level,
1515                                                      DXGI_FORMAT format,
1516                                                      const TextureHelper11 &texture,
1517                                                      d3d11::SharedUAV *outUAV)
1518 {
1519     ASSERT(outUAV);
1520     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
1521     uavDesc.Format             = format;
1522     uavDesc.ViewDimension      = D3D11_UAV_DIMENSION_TEXTURE2D;
1523     uavDesc.Texture2D.MipSlice = mTopLevel + level;
1524     ANGLE_TRY(
1525         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
1526     outUAV->setLabels("TexStorage2D.UAVForImage", &mTextureLabel);
1527     return angle::Result::Continue;
1528 }
1529 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)1530 angle::Result TextureStorage11_2D::getSwizzleTexture(const gl::Context *context,
1531                                                      const TextureHelper11 **outTexture)
1532 {
1533     ASSERT(outTexture);
1534 
1535     if (!mSwizzleTexture.valid())
1536     {
1537         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
1538 
1539         D3D11_TEXTURE2D_DESC desc;
1540         desc.Width              = mTextureWidth;
1541         desc.Height             = mTextureHeight;
1542         desc.MipLevels          = mMipLevels;
1543         desc.ArraySize          = 1;
1544         desc.Format             = format.texFormat;
1545         desc.SampleDesc.Count   = 1;
1546         desc.SampleDesc.Quality = 0;
1547         desc.Usage              = D3D11_USAGE_DEFAULT;
1548         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1549         desc.CPUAccessFlags     = 0;
1550         desc.MiscFlags          = 0;
1551 
1552         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
1553                                              &mSwizzleTexture));
1554         mSwizzleTexture.setLabels("TexStorage2D.SwizzleTexture", &mTextureLabel);
1555     }
1556 
1557     *outTexture = &mSwizzleTexture;
1558     return angle::Result::Continue;
1559 }
1560 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)1561 angle::Result TextureStorage11_2D::getSwizzleRenderTarget(const gl::Context *context,
1562                                                           int mipLevel,
1563                                                           const d3d11::RenderTargetView **outRTV)
1564 {
1565     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
1566     ASSERT(outRTV);
1567 
1568     if (!mSwizzleRenderTargets[mipLevel].valid())
1569     {
1570         const TextureHelper11 *swizzleTexture = nullptr;
1571         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
1572 
1573         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1574         rtvDesc.Format =
1575             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
1576         rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
1577         rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
1578 
1579         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
1580                                               mSwizzleTexture.get(),
1581                                               &mSwizzleRenderTargets[mipLevel]));
1582     }
1583 
1584     *outRTV = &mSwizzleRenderTargets[mipLevel];
1585     return angle::Result::Continue;
1586 }
1587 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)1588 angle::Result TextureStorage11_2D::ensureDropStencilTexture(const gl::Context *context,
1589                                                             DropStencil *dropStencilOut)
1590 {
1591     if (mDropStencilTexture.valid())
1592     {
1593         *dropStencilOut = DropStencil::ALREADY_EXISTS;
1594         return angle::Result::Continue;
1595     }
1596 
1597     D3D11_TEXTURE2D_DESC dropDesc = {};
1598     dropDesc.ArraySize            = 1;
1599     dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
1600     dropDesc.CPUAccessFlags       = 0;
1601     dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
1602     dropDesc.Height               = mTextureHeight;
1603     dropDesc.MipLevels            = mMipLevels;
1604     dropDesc.MiscFlags            = 0;
1605     dropDesc.SampleDesc.Count     = 1;
1606     dropDesc.SampleDesc.Quality   = 0;
1607     dropDesc.Usage                = D3D11_USAGE_DEFAULT;
1608     dropDesc.Width                = mTextureWidth;
1609 
1610     const auto &format =
1611         d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
1612     ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
1613                                          &mDropStencilTexture));
1614     mDropStencilTexture.setLabels("TexStorage2D.DropStencil", &mTextureLabel);
1615 
1616     ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::Make2D(0, mMipLevels)));
1617 
1618     *dropStencilOut = DropStencil::CREATED;
1619     return angle::Result::Continue;
1620 }
1621 
resolveTexture(const gl::Context * context)1622 angle::Result TextureStorage11_2D::resolveTexture(const gl::Context *context)
1623 {
1624     if (mMSTexInfo && mMSTexInfo->msTex && mMSTexInfo->msTextureNeedsResolve)
1625     {
1626         ANGLE_TRY(resolveTextureHelper(context, mTexture));
1627         onStateChange(angle::SubjectMessage::ContentsChanged);
1628     }
1629     return angle::Result::Continue;
1630 }
1631 
TextureStorage11_External(Renderer11 * renderer,egl::Stream * stream,const egl::Stream::GLTextureDescription & glDesc,const std::string & label)1632 TextureStorage11_External::TextureStorage11_External(
1633     Renderer11 *renderer,
1634     egl::Stream *stream,
1635     const egl::Stream::GLTextureDescription &glDesc,
1636     const std::string &label)
1637     : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat, label)
1638 {
1639     ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11Texture);
1640     auto *producer = static_cast<StreamProducerD3DTexture *>(stream->getImplementation());
1641     mTexture.set(producer->getD3DTexture(), mFormatInfo);
1642     mSubresourceIndex = producer->getArraySlice();
1643     mTexture.get()->AddRef();
1644     mMipLevels = 1;
1645 
1646     D3D11_TEXTURE2D_DESC desc;
1647     mTexture.getDesc(&desc);
1648     mTextureWidth  = desc.Width;
1649     mTextureHeight = desc.Height;
1650     mTextureDepth  = 1;
1651     mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
1652 }
1653 
onDestroy(const gl::Context * context)1654 angle::Result TextureStorage11_External::onDestroy(const gl::Context *context)
1655 {
1656     if (mHasKeyedMutex)
1657     {
1658         // If the keyed mutex is released that will unbind it and cause the state cache to become
1659         // desynchronized.
1660         mRenderer->getStateManager()->invalidateBoundViews();
1661     }
1662 
1663     return angle::Result::Continue;
1664 }
1665 
~TextureStorage11_External()1666 TextureStorage11_External::~TextureStorage11_External() {}
1667 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1668 angle::Result TextureStorage11_External::copyToStorage(const gl::Context *context,
1669                                                        TextureStorage *destStorage)
1670 {
1671     UNIMPLEMENTED();
1672     return angle::Result::Continue;
1673 }
1674 
associateImage(Image11 * image,const gl::ImageIndex & index)1675 void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index)
1676 {
1677     ASSERT(index.getLevelIndex() == 0);
1678     mAssociatedImage = image;
1679 }
1680 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)1681 void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index,
1682                                                            Image11 *expectedImage)
1683 {
1684     ASSERT(index.getLevelIndex() == 0 && mAssociatedImage == expectedImage);
1685 }
1686 
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)1687 void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index,
1688                                                   Image11 *expectedImage)
1689 {
1690     ASSERT(index.getLevelIndex() == 0);
1691     ASSERT(mAssociatedImage == expectedImage);
1692     mAssociatedImage = nullptr;
1693 }
1694 
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)1695 angle::Result TextureStorage11_External::releaseAssociatedImage(const gl::Context *context,
1696                                                                 const gl::ImageIndex &index,
1697                                                                 Image11 *incomingImage)
1698 {
1699     ASSERT(index.getLevelIndex() == 0);
1700 
1701     if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
1702     {
1703         mAssociatedImage->verifyAssociatedStorageValid(this);
1704 
1705         ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
1706     }
1707 
1708     return angle::Result::Continue;
1709 }
1710 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1711 angle::Result TextureStorage11_External::getResource(const gl::Context *context,
1712                                                      const TextureHelper11 **outResource)
1713 {
1714     *outResource = &mTexture;
1715     return angle::Result::Continue;
1716 }
1717 
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)1718 angle::Result TextureStorage11_External::getMippedResource(const gl::Context *context,
1719                                                            const TextureHelper11 **outResource)
1720 {
1721     *outResource = &mTexture;
1722     return angle::Result::Continue;
1723 }
1724 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const1725 angle::Result TextureStorage11_External::findRenderTarget(const gl::Context *context,
1726                                                           const gl::ImageIndex &index,
1727                                                           GLsizei samples,
1728                                                           RenderTargetD3D **outRT) const
1729 {
1730     // Render targets are not supported for external textures
1731     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1732     return angle::Result::Stop;
1733 }
1734 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)1735 angle::Result TextureStorage11_External::getRenderTarget(const gl::Context *context,
1736                                                          const gl::ImageIndex &index,
1737                                                          GLsizei samples,
1738                                                          RenderTargetD3D **outRT)
1739 {
1740     // Render targets are not supported for external textures
1741     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1742     return angle::Result::Stop;
1743 }
1744 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1745 angle::Result TextureStorage11_External::createSRVForSampler(const gl::Context *context,
1746                                                              int baseLevel,
1747                                                              int mipLevels,
1748                                                              DXGI_FORMAT format,
1749                                                              const TextureHelper11 &texture,
1750                                                              d3d11::SharedSRV *outSRV)
1751 {
1752     // Since external textures are treates as non-mipmapped textures, we ignore mipmap levels and
1753     // use the specified subresource ID the storage was created with.
1754     ASSERT(mipLevels == 1);
1755     ASSERT(outSRV);
1756 
1757     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1758     srvDesc.Format        = format;
1759     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1760     // subresource index is equal to the mip level for 2D textures
1761     srvDesc.Texture2DArray.MostDetailedMip = 0;
1762     srvDesc.Texture2DArray.MipLevels       = 1;
1763     srvDesc.Texture2DArray.FirstArraySlice = mSubresourceIndex;
1764     srvDesc.Texture2DArray.ArraySize       = 1;
1765 
1766     ANGLE_TRY(
1767         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
1768     outSRV->setLabels("TexStorage2D.SRV", &mTextureLabel);
1769 
1770     return angle::Result::Continue;
1771 }
1772 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1773 angle::Result TextureStorage11_External::createSRVForImage(const gl::Context *context,
1774                                                            int level,
1775                                                            DXGI_FORMAT format,
1776                                                            const TextureHelper11 &texture,
1777                                                            d3d11::SharedSRV *outSRV)
1778 {
1779     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1780     return angle::Result::Stop;
1781 }
1782 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)1783 angle::Result TextureStorage11_External::createUAVForImage(const gl::Context *context,
1784                                                            int level,
1785                                                            DXGI_FORMAT format,
1786                                                            const TextureHelper11 &texture,
1787                                                            d3d11::SharedUAV *outUAV)
1788 {
1789     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1790     return angle::Result::Stop;
1791 }
1792 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)1793 angle::Result TextureStorage11_External::getSwizzleTexture(const gl::Context *context,
1794                                                            const TextureHelper11 **outTexture)
1795 {
1796     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1797     return angle::Result::Stop;
1798 }
1799 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)1800 angle::Result TextureStorage11_External::getSwizzleRenderTarget(
1801     const gl::Context *context,
1802     int mipLevel,
1803     const d3d11::RenderTargetView **outRTV)
1804 {
1805     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1806     return angle::Result::Stop;
1807 }
1808 
onLabelUpdate()1809 void TextureStorage11_External::onLabelUpdate()
1810 {
1811     if (mTexture.valid())
1812     {
1813         mTexture.setKHRDebugLabel(&mTextureLabel);
1814     }
1815 }
1816 
TextureStorage11ImmutableBase(Renderer11 * renderer,UINT bindFlags,UINT miscFlags,GLenum internalFormat,const std::string & label)1817 TextureStorage11ImmutableBase::TextureStorage11ImmutableBase(Renderer11 *renderer,
1818                                                              UINT bindFlags,
1819                                                              UINT miscFlags,
1820                                                              GLenum internalFormat,
1821                                                              const std::string &label)
1822     : TextureStorage11(renderer, bindFlags, miscFlags, internalFormat, label)
1823 {}
1824 
associateImage(Image11 *,const gl::ImageIndex &)1825 void TextureStorage11ImmutableBase::associateImage(Image11 *, const gl::ImageIndex &) {}
1826 
disassociateImage(const gl::ImageIndex &,Image11 *)1827 void TextureStorage11ImmutableBase::disassociateImage(const gl::ImageIndex &, Image11 *) {}
1828 
verifyAssociatedImageValid(const gl::ImageIndex &,Image11 *)1829 void TextureStorage11ImmutableBase::verifyAssociatedImageValid(const gl::ImageIndex &, Image11 *) {}
1830 
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex &,Image11 *)1831 angle::Result TextureStorage11ImmutableBase::releaseAssociatedImage(const gl::Context *context,
1832                                                                     const gl::ImageIndex &,
1833                                                                     Image11 *)
1834 {
1835     return angle::Result::Continue;
1836 }
1837 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1838 angle::Result TextureStorage11ImmutableBase::createSRVForImage(const gl::Context *context,
1839                                                                int level,
1840                                                                DXGI_FORMAT format,
1841                                                                const TextureHelper11 &texture,
1842                                                                d3d11::SharedSRV *outSRV)
1843 {
1844     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1845     return angle::Result::Stop;
1846 }
1847 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)1848 angle::Result TextureStorage11ImmutableBase::createUAVForImage(const gl::Context *context,
1849                                                                int level,
1850                                                                DXGI_FORMAT format,
1851                                                                const TextureHelper11 &texture,
1852                                                                d3d11::SharedUAV *outUAV)
1853 {
1854     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1855     return angle::Result::Stop;
1856 }
1857 
TextureStorage11_EGLImage(Renderer11 * renderer,EGLImageD3D * eglImage,RenderTarget11 * renderTarget11,const std::string & label)1858 TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
1859                                                      EGLImageD3D *eglImage,
1860                                                      RenderTarget11 *renderTarget11,
1861                                                      const std::string &label)
1862     : TextureStorage11ImmutableBase(renderer,
1863                                     D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
1864                                     0,
1865                                     renderTarget11->getInternalFormat(),
1866                                     label),
1867       mImage(eglImage),
1868       mCurrentRenderTarget(0),
1869       mSwizzleTexture(),
1870       mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1871 {
1872     mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
1873 
1874     mMipLevels     = 1;
1875     mTextureWidth  = renderTarget11->getWidth();
1876     mTextureHeight = renderTarget11->getHeight();
1877     mTextureDepth  = 1;
1878 }
1879 
~TextureStorage11_EGLImage()1880 TextureStorage11_EGLImage::~TextureStorage11_EGLImage() {}
1881 
getSubresourceIndex(const gl::Context * context,const gl::ImageIndex & index,UINT * outSubresourceIndex) const1882 angle::Result TextureStorage11_EGLImage::getSubresourceIndex(const gl::Context *context,
1883                                                              const gl::ImageIndex &index,
1884                                                              UINT *outSubresourceIndex) const
1885 {
1886     ASSERT(index.getType() == gl::TextureType::_2D);
1887     ASSERT(index.getLevelIndex() == 0);
1888 
1889     RenderTarget11 *renderTarget11 = nullptr;
1890     ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
1891     *outSubresourceIndex = renderTarget11->getSubresourceIndex();
1892     return angle::Result::Continue;
1893 }
1894 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1895 angle::Result TextureStorage11_EGLImage::getResource(const gl::Context *context,
1896                                                      const TextureHelper11 **outResource)
1897 {
1898     ANGLE_TRY(checkForUpdatedRenderTarget(context));
1899 
1900     RenderTarget11 *renderTarget11 = nullptr;
1901     ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
1902     *outResource = &renderTarget11->getTexture();
1903     return angle::Result::Continue;
1904 }
1905 
getSRVForSampler(const gl::Context * context,const gl::TextureState & textureState,const gl::SamplerState & sampler,const d3d11::SharedSRV ** outSRV)1906 angle::Result TextureStorage11_EGLImage::getSRVForSampler(const gl::Context *context,
1907                                                           const gl::TextureState &textureState,
1908                                                           const gl::SamplerState &sampler,
1909                                                           const d3d11::SharedSRV **outSRV)
1910 {
1911     ANGLE_TRY(checkForUpdatedRenderTarget(context));
1912     return TextureStorage11::getSRVForSampler(context, textureState, sampler, outSRV);
1913 }
1914 
getMippedResource(const gl::Context * context,const TextureHelper11 **)1915 angle::Result TextureStorage11_EGLImage::getMippedResource(const gl::Context *context,
1916                                                            const TextureHelper11 **)
1917 {
1918     // This shouldn't be called unless the zero max LOD workaround is active.
1919     // EGL images are unavailable in this configuration.
1920     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1921     return angle::Result::Stop;
1922 }
1923 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const1924 angle::Result TextureStorage11_EGLImage::findRenderTarget(const gl::Context *context,
1925                                                           const gl::ImageIndex &index,
1926                                                           GLsizei samples,
1927                                                           RenderTargetD3D **outRT) const
1928 {
1929     // Since the render target of an EGL image will be updated when orphaning, trying to find a
1930     // cache of it can be rarely useful.
1931     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1932     return angle::Result::Stop;
1933 }
1934 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)1935 angle::Result TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context,
1936                                                          const gl::ImageIndex &index,
1937                                                          GLsizei samples,
1938                                                          RenderTargetD3D **outRT)
1939 {
1940     ASSERT(!index.hasLayer());
1941     ASSERT(index.getLevelIndex() == 0);
1942 
1943     ANGLE_TRY(checkForUpdatedRenderTarget(context));
1944 
1945     return mImage->getRenderTarget(context, outRT);
1946 }
1947 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1948 angle::Result TextureStorage11_EGLImage::copyToStorage(const gl::Context *context,
1949                                                        TextureStorage *destStorage)
1950 {
1951     const TextureHelper11 *sourceResouce = nullptr;
1952     ANGLE_TRY(getResource(context, &sourceResouce));
1953 
1954     ASSERT(destStorage);
1955     TextureStorage11_2D *dest11         = GetAs<TextureStorage11_2D>(destStorage);
1956     const TextureHelper11 *destResource = nullptr;
1957     ANGLE_TRY(dest11->getResource(context, &destResource));
1958 
1959     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
1960     immediateContext->CopyResource(destResource->get(), sourceResouce->get());
1961 
1962     dest11->markDirty();
1963 
1964     return angle::Result::Continue;
1965 }
1966 
useLevelZeroWorkaroundTexture(const gl::Context * context,bool)1967 angle::Result TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(const gl::Context *context,
1968                                                                        bool)
1969 {
1970     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1971     return angle::Result::Stop;
1972 }
1973 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)1974 angle::Result TextureStorage11_EGLImage::getSwizzleTexture(const gl::Context *context,
1975                                                            const TextureHelper11 **outTexture)
1976 {
1977     ASSERT(outTexture);
1978 
1979     if (!mSwizzleTexture.valid())
1980     {
1981         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
1982 
1983         D3D11_TEXTURE2D_DESC desc;
1984         desc.Width              = mTextureWidth;
1985         desc.Height             = mTextureHeight;
1986         desc.MipLevels          = mMipLevels;
1987         desc.ArraySize          = 1;
1988         desc.Format             = format.texFormat;
1989         desc.SampleDesc.Count   = 1;
1990         desc.SampleDesc.Quality = 0;
1991         desc.Usage              = D3D11_USAGE_DEFAULT;
1992         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1993         desc.CPUAccessFlags     = 0;
1994         desc.MiscFlags          = 0;
1995 
1996         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
1997                                              &mSwizzleTexture));
1998         mSwizzleTexture.setLabels("TexStorageEGLImage.SwizzleTexture", &mTextureLabel);
1999     }
2000 
2001     *outTexture = &mSwizzleTexture;
2002     return angle::Result::Continue;
2003 }
2004 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)2005 angle::Result TextureStorage11_EGLImage::getSwizzleRenderTarget(
2006     const gl::Context *context,
2007     int mipLevel,
2008     const d3d11::RenderTargetView **outRTV)
2009 {
2010     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2011     ASSERT(outRTV);
2012 
2013     if (!mSwizzleRenderTargets[mipLevel].valid())
2014     {
2015         const TextureHelper11 *swizzleTexture = nullptr;
2016         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
2017 
2018         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2019         rtvDesc.Format =
2020             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
2021         rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
2022         rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
2023 
2024         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
2025                                               mSwizzleTexture.get(),
2026                                               &mSwizzleRenderTargets[mipLevel]));
2027     }
2028 
2029     *outRTV = &mSwizzleRenderTargets[mipLevel];
2030     return angle::Result::Continue;
2031 }
2032 
checkForUpdatedRenderTarget(const gl::Context * context)2033 angle::Result TextureStorage11_EGLImage::checkForUpdatedRenderTarget(const gl::Context *context)
2034 {
2035     RenderTarget11 *renderTarget11 = nullptr;
2036     ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
2037 
2038     if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11))
2039     {
2040         clearSRVCache();
2041         mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
2042     }
2043 
2044     return angle::Result::Continue;
2045 }
2046 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2047 angle::Result TextureStorage11_EGLImage::createSRVForSampler(const gl::Context *context,
2048                                                              int baseLevel,
2049                                                              int mipLevels,
2050                                                              DXGI_FORMAT format,
2051                                                              const TextureHelper11 &texture,
2052                                                              d3d11::SharedSRV *outSRV)
2053 {
2054     ASSERT(baseLevel == 0);
2055     ASSERT(mipLevels == 1);
2056     ASSERT(outSRV);
2057 
2058     // Create a new SRV only for the swizzle texture.  Otherwise just return the Image's
2059     // RenderTarget's SRV.
2060     if (texture == mSwizzleTexture)
2061     {
2062         D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2063         srvDesc.Format                    = format;
2064         srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
2065         srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
2066         srvDesc.Texture2D.MipLevels       = mipLevels;
2067 
2068         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(),
2069                                               outSRV));
2070         outSRV->setLabels("TexStorageEGLImage.SRV", &mTextureLabel);
2071     }
2072     else
2073     {
2074         RenderTarget11 *renderTarget = nullptr;
2075         ANGLE_TRY(getImageRenderTarget(context, &renderTarget));
2076 
2077         ASSERT(texture == renderTarget->getTexture());
2078 
2079         *outSRV = renderTarget->getShaderResourceView(context).makeCopy();
2080     }
2081 
2082     return angle::Result::Continue;
2083 }
2084 
getImageRenderTarget(const gl::Context * context,RenderTarget11 ** outRT) const2085 angle::Result TextureStorage11_EGLImage::getImageRenderTarget(const gl::Context *context,
2086                                                               RenderTarget11 **outRT) const
2087 {
2088     RenderTargetD3D *renderTargetD3D = nullptr;
2089     ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
2090     *outRT = GetAs<RenderTarget11>(renderTargetD3D);
2091     return angle::Result::Continue;
2092 }
2093 
onLabelUpdate()2094 void TextureStorage11_EGLImage::onLabelUpdate()
2095 {
2096     if (mSwizzleTexture.valid())
2097     {
2098         mSwizzleTexture.setKHRDebugLabel(&mTextureLabel);
2099     }
2100 }
2101 
TextureStorage11_Cube(Renderer11 * renderer,GLenum internalformat,bool renderTarget,int size,int levels,bool hintLevelZeroOnly,const std::string & label)2102 TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer,
2103                                              GLenum internalformat,
2104                                              bool renderTarget,
2105                                              int size,
2106                                              int levels,
2107                                              bool hintLevelZeroOnly,
2108                                              const std::string &label)
2109     : TextureStorage11(
2110           renderer,
2111           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
2112           GetTextureMiscFlags(internalformat,
2113                               renderer->getRenderer11DeviceCaps(),
2114                               renderTarget,
2115                               levels),
2116           internalformat,
2117           label),
2118       mTexture(),
2119       mLevelZeroTexture(),
2120       mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
2121       mSwizzleTexture()
2122 {
2123     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
2124     {
2125         for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
2126         {
2127             mAssociatedImages[face][level] = nullptr;
2128             mRenderTarget[face][level]     = nullptr;
2129         }
2130     }
2131 
2132     for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
2133     {
2134         mLevelZeroRenderTarget[face] = nullptr;
2135     }
2136 
2137     // adjust size if needed for compressed textures
2138     int height = size;
2139     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel);
2140 
2141     mMipLevels     = mTopLevel + levels;
2142     mTextureWidth  = size;
2143     mTextureHeight = size;
2144     mTextureDepth  = 1;
2145 
2146     // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
2147     ASSERT(!mUseLevelZeroTexture || mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
2148 }
2149 
onDestroy(const gl::Context * context)2150 angle::Result TextureStorage11_Cube::onDestroy(const gl::Context *context)
2151 {
2152     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
2153     {
2154         for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
2155         {
2156             if (mAssociatedImages[face][level] != nullptr)
2157             {
2158                 mAssociatedImages[face][level]->verifyAssociatedStorageValid(this);
2159 
2160                 // We must let the Images recover their data before we delete it from the
2161                 // TextureStorage.
2162                 ANGLE_TRY(mAssociatedImages[face][level]->recoverFromAssociatedStorage(context));
2163             }
2164         }
2165     }
2166 
2167     return angle::Result::Continue;
2168 }
2169 
~TextureStorage11_Cube()2170 TextureStorage11_Cube::~TextureStorage11_Cube() {}
2171 
getSubresourceIndex(const gl::Context * context,const gl::ImageIndex & index,UINT * outSubresourceIndex) const2172 angle::Result TextureStorage11_Cube::getSubresourceIndex(const gl::Context *context,
2173                                                          const gl::ImageIndex &index,
2174                                                          UINT *outSubresourceIndex) const
2175 {
2176     UINT arraySlice = index.cubeMapFaceIndex();
2177     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled && mUseLevelZeroTexture &&
2178         index.getLevelIndex() == 0)
2179     {
2180         UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
2181         ASSERT(subresource != std::numeric_limits<UINT>::max());
2182         *outSubresourceIndex = subresource;
2183     }
2184     else
2185     {
2186         UINT mipSlice    = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
2187         UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
2188         ASSERT(subresource != std::numeric_limits<UINT>::max());
2189         *outSubresourceIndex = subresource;
2190     }
2191     return angle::Result::Continue;
2192 }
2193 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)2194 angle::Result TextureStorage11_Cube::copyToStorage(const gl::Context *context,
2195                                                    TextureStorage *destStorage)
2196 {
2197     ASSERT(destStorage);
2198 
2199     TextureStorage11_Cube *dest11 = GetAs<TextureStorage11_Cube>(destStorage);
2200 
2201     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
2202     {
2203         ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
2204 
2205         // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
2206         // corresponding textures in destStorage.
2207         if (mTexture.valid())
2208         {
2209             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
2210 
2211             const TextureHelper11 *destResource = nullptr;
2212             ANGLE_TRY(dest11->getResource(context, &destResource));
2213 
2214             immediateContext->CopyResource(destResource->get(), mTexture.get());
2215         }
2216 
2217         if (mLevelZeroTexture.valid())
2218         {
2219             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
2220 
2221             const TextureHelper11 *destResource = nullptr;
2222             ANGLE_TRY(dest11->getResource(context, &destResource));
2223 
2224             immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
2225         }
2226     }
2227     else
2228     {
2229         const TextureHelper11 *sourceResouce = nullptr;
2230         ANGLE_TRY(getResource(context, &sourceResouce));
2231 
2232         const TextureHelper11 *destResource = nullptr;
2233         ANGLE_TRY(dest11->getResource(context, &destResource));
2234 
2235         ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
2236         immediateContext->CopyResource(destResource->get(), sourceResouce->get());
2237     }
2238 
2239     dest11->markDirty();
2240 
2241     return angle::Result::Continue;
2242 }
2243 
useLevelZeroWorkaroundTexture(const gl::Context * context,bool useLevelZeroTexture)2244 angle::Result TextureStorage11_Cube::useLevelZeroWorkaroundTexture(const gl::Context *context,
2245                                                                    bool useLevelZeroTexture)
2246 {
2247     if (useLevelZeroTexture && mMipLevels > 1)
2248     {
2249         if (!mUseLevelZeroTexture && mTexture.valid())
2250         {
2251             ANGLE_TRY(ensureTextureExists(context, 1));
2252 
2253             // Pull data back from the mipped texture if necessary.
2254             ASSERT(mLevelZeroTexture.valid());
2255             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2256 
2257             for (int face = 0; face < 6; face++)
2258             {
2259                 deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(),
2260                                                      D3D11CalcSubresource(0, face, 1), 0, 0, 0,
2261                                                      mTexture.get(), face * mMipLevels, nullptr);
2262             }
2263         }
2264 
2265         mUseLevelZeroTexture = true;
2266     }
2267     else
2268     {
2269         if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
2270         {
2271             ANGLE_TRY(ensureTextureExists(context, mMipLevels));
2272 
2273             // Pull data back from the level zero texture if necessary.
2274             ASSERT(mTexture.valid());
2275             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2276 
2277             for (int face = 0; face < 6; face++)
2278             {
2279                 deviceContext->CopySubresourceRegion(mTexture.get(),
2280                                                      D3D11CalcSubresource(0, face, mMipLevels), 0,
2281                                                      0, 0, mLevelZeroTexture.get(), face, nullptr);
2282             }
2283         }
2284 
2285         mUseLevelZeroTexture = false;
2286     }
2287 
2288     return angle::Result::Continue;
2289 }
2290 
associateImage(Image11 * image,const gl::ImageIndex & index)2291 void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index)
2292 {
2293     const GLint level       = index.getLevelIndex();
2294     const GLint layerTarget = index.cubeMapFaceIndex();
2295 
2296     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2297     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2298 
2299     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2300     {
2301         if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount))
2302         {
2303             mAssociatedImages[layerTarget][level] = image;
2304         }
2305     }
2306 }
2307 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2308 void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index,
2309                                                        Image11 *expectedImage)
2310 {
2311     const GLint level       = index.getLevelIndex();
2312     const GLint layerTarget = index.cubeMapFaceIndex();
2313 
2314     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2315     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2316     // This validation check should never return false. It means the Image/TextureStorage
2317     // association is broken.
2318     ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
2319 }
2320 
2321 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)2322 void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
2323 {
2324     const GLint level       = index.getLevelIndex();
2325     const GLint layerTarget = index.cubeMapFaceIndex();
2326 
2327     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2328     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2329     ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
2330     mAssociatedImages[layerTarget][level] = nullptr;
2331 }
2332 
2333 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
2334 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)2335 angle::Result TextureStorage11_Cube::releaseAssociatedImage(const gl::Context *context,
2336                                                             const gl::ImageIndex &index,
2337                                                             Image11 *incomingImage)
2338 {
2339     const GLint level       = index.getLevelIndex();
2340     const GLint layerTarget = index.cubeMapFaceIndex();
2341 
2342     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2343     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2344 
2345     if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2346     {
2347         if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount))
2348         {
2349             // No need to let the old Image recover its data, if it is also the incoming Image.
2350             if (mAssociatedImages[layerTarget][level] != nullptr &&
2351                 mAssociatedImages[layerTarget][level] != incomingImage)
2352             {
2353                 // Ensure that the Image is still associated with this TextureStorage.
2354                 mAssociatedImages[layerTarget][level]->verifyAssociatedStorageValid(this);
2355 
2356                 // Force the image to recover from storage before its data is overwritten.
2357                 // This will reset mAssociatedImages[level] to nullptr too.
2358                 ANGLE_TRY(
2359                     mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(context));
2360             }
2361         }
2362     }
2363 
2364     return angle::Result::Continue;
2365 }
2366 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)2367 angle::Result TextureStorage11_Cube::getResource(const gl::Context *context,
2368                                                  const TextureHelper11 **outResource)
2369 {
2370     if (mUseLevelZeroTexture && mMipLevels > 1)
2371     {
2372         ANGLE_TRY(ensureTextureExists(context, 1));
2373         *outResource = &mLevelZeroTexture;
2374     }
2375     else
2376     {
2377         ANGLE_TRY(ensureTextureExists(context, mMipLevels));
2378         *outResource = &mTexture;
2379     }
2380     return angle::Result::Continue;
2381 }
2382 
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)2383 angle::Result TextureStorage11_Cube::getMippedResource(const gl::Context *context,
2384                                                        const TextureHelper11 **outResource)
2385 {
2386     // This shouldn't be called unless the zero max LOD workaround is active.
2387     ASSERT(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
2388 
2389     ANGLE_TRY(ensureTextureExists(context, mMipLevels));
2390     *outResource = &mTexture;
2391     return angle::Result::Continue;
2392 }
2393 
ensureTextureExists(const gl::Context * context,int mipLevels)2394 angle::Result TextureStorage11_Cube::ensureTextureExists(const gl::Context *context, int mipLevels)
2395 {
2396     // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
2397     ANGLE_TRY(resolveTexture(context));
2398     bool useLevelZeroTexture = mRenderer->getFeatures().zeroMaxLodWorkaround.enabled
2399                                    ? (mipLevels == 1) && (mMipLevels > 1)
2400                                    : false;
2401     TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
2402 
2403     // if the size is not positive this should be treated as an incomplete texture
2404     // we handle that here by skipping the d3d texture creation
2405     if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
2406     {
2407         ASSERT(mMipLevels > 0);
2408 
2409         D3D11_TEXTURE2D_DESC desc;
2410         desc.Width              = mTextureWidth;
2411         desc.Height             = mTextureHeight;
2412         desc.MipLevels          = mipLevels;
2413         desc.ArraySize          = gl::kCubeFaceCount;
2414         desc.Format             = mFormatInfo.texFormat;
2415         desc.SampleDesc.Count   = 1;
2416         desc.SampleDesc.Quality = 0;
2417         desc.Usage              = D3D11_USAGE_DEFAULT;
2418         desc.BindFlags          = getBindFlags();
2419         desc.CPUAccessFlags     = 0;
2420         desc.MiscFlags          = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags();
2421 
2422         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
2423                                              outputTexture));
2424         outputTexture->setLabels("TexStorageCube.Texture", &mTextureLabel);
2425     }
2426 
2427     return angle::Result::Continue;
2428 }
2429 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const2430 angle::Result TextureStorage11_Cube::findRenderTarget(const gl::Context *context,
2431                                                       const gl::ImageIndex &index,
2432                                                       GLsizei samples,
2433                                                       RenderTargetD3D **outRT) const
2434 {
2435     const int faceIndex = index.cubeMapFaceIndex();
2436     const int level     = index.getLevelIndex();
2437 
2438     ASSERT(level >= 0 && level < getLevelCount());
2439     ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::kCubeFaceCount));
2440 
2441     bool needMS = samples > 0;
2442     if (needMS)
2443     {
2444         return findMultisampledRenderTarget(context, index, samples, outRT);
2445     }
2446 
2447     if (!mRenderTarget[faceIndex][level])
2448     {
2449         if (mUseLevelZeroTexture)
2450         {
2451             ASSERT(index.getLevelIndex() == 0);
2452             ASSERT(outRT);
2453             *outRT = mLevelZeroRenderTarget[faceIndex].get();
2454             return angle::Result::Continue;
2455         }
2456     }
2457 
2458     ASSERT(outRT);
2459     *outRT = mRenderTarget[faceIndex][level].get();
2460     return angle::Result::Continue;
2461 }
2462 
createRenderTargetSRV(const gl::Context * context,const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const2463 angle::Result TextureStorage11_Cube::createRenderTargetSRV(const gl::Context *context,
2464                                                            const TextureHelper11 &texture,
2465                                                            const gl::ImageIndex &index,
2466                                                            DXGI_FORMAT resourceFormat,
2467                                                            d3d11::SharedSRV *srv) const
2468 {
2469     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2470     srvDesc.Format                         = resourceFormat;
2471     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
2472     srvDesc.Texture2DArray.MipLevels       = 1;
2473     srvDesc.Texture2DArray.FirstArraySlice = index.cubeMapFaceIndex();
2474     srvDesc.Texture2DArray.ArraySize       = 1;
2475 
2476     if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
2477     {
2478         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
2479     }
2480     else
2481     {
2482         // Will be used with Texture2D sampler, not TextureCube
2483         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2484     }
2485 
2486     ANGLE_TRY(
2487         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
2488     return angle::Result::Continue;
2489 }
2490 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)2491 angle::Result TextureStorage11_Cube::getRenderTarget(const gl::Context *context,
2492                                                      const gl::ImageIndex &index,
2493                                                      GLsizei samples,
2494                                                      RenderTargetD3D **outRT)
2495 {
2496     const int faceIndex = index.cubeMapFaceIndex();
2497     const int level     = index.getLevelIndex();
2498 
2499     ASSERT(level >= 0 && level < getLevelCount());
2500     ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::kCubeFaceCount));
2501 
2502     bool needMS = samples > 0;
2503     if (needMS)
2504     {
2505         return getMultisampledRenderTarget(context, index, samples, outRT);
2506     }
2507     else
2508     {
2509         ANGLE_TRY(resolveTexture(context));
2510     }
2511 
2512     Context11 *context11 = GetImplAs<Context11>(context);
2513 
2514     if (!mRenderTarget[faceIndex][level])
2515     {
2516         if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
2517         {
2518             ASSERT(index.getLevelIndex() == 0);
2519             ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
2520         }
2521 
2522         const TextureHelper11 *texture = nullptr;
2523         ANGLE_TRY(getResource(context, &texture));
2524 
2525         if (mUseLevelZeroTexture)
2526         {
2527             if (!mLevelZeroRenderTarget[faceIndex])
2528             {
2529                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2530                 rtvDesc.Format                         = mFormatInfo.rtvFormat;
2531                 rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2532                 rtvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2533                 rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2534                 rtvDesc.Texture2DArray.ArraySize       = 1;
2535 
2536                 d3d11::RenderTargetView rtv;
2537                 ANGLE_TRY(
2538                     mRenderer->allocateResource(context11, rtvDesc, mLevelZeroTexture.get(), &rtv));
2539 
2540                 mLevelZeroRenderTarget[faceIndex].reset(new TextureRenderTarget11(
2541                     std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
2542                     mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
2543                     getLevelHeight(level), 1, 0));
2544             }
2545 
2546             ASSERT(outRT);
2547             *outRT = mLevelZeroRenderTarget[faceIndex].get();
2548             return angle::Result::Continue;
2549         }
2550 
2551         d3d11::SharedSRV srv;
2552         ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
2553         d3d11::SharedSRV blitSRV;
2554         if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
2555         {
2556             ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
2557                                             &blitSRV));
2558         }
2559         else
2560         {
2561             blitSRV = srv.makeCopy();
2562         }
2563 
2564         srv.setLabels("TexStorageCube.RenderTargetSRV", &mTextureLabel);
2565 
2566         if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
2567         {
2568             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2569             rtvDesc.Format                         = mFormatInfo.rtvFormat;
2570             rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2571             rtvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2572             rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2573             rtvDesc.Texture2DArray.ArraySize       = 1;
2574 
2575             d3d11::RenderTargetView rtv;
2576             ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
2577             rtv.setLabels("TexStorageCube.RenderTargetRTV", &mTextureLabel);
2578 
2579             mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
2580                 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
2581                 getLevelWidth(level), getLevelHeight(level), 1, 0));
2582         }
2583         else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
2584         {
2585             D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
2586             dsvDesc.Format                         = mFormatInfo.dsvFormat;
2587             dsvDesc.ViewDimension                  = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
2588             dsvDesc.Flags                          = 0;
2589             dsvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2590             dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2591             dsvDesc.Texture2DArray.ArraySize       = 1;
2592 
2593             d3d11::DepthStencilView dsv;
2594             ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
2595             dsv.setLabels("TexStorageCube.RenderTargetDSV", &mTextureLabel);
2596 
2597             mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
2598                 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
2599                 getLevelWidth(level), getLevelHeight(level), 1, 0));
2600         }
2601         else
2602         {
2603             UNREACHABLE();
2604         }
2605     }
2606 
2607     ASSERT(outRT);
2608     *outRT = mRenderTarget[faceIndex][level].get();
2609     return angle::Result::Continue;
2610 }
2611 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2612 angle::Result TextureStorage11_Cube::createSRVForSampler(const gl::Context *context,
2613                                                          int baseLevel,
2614                                                          int mipLevels,
2615                                                          DXGI_FORMAT format,
2616                                                          const TextureHelper11 &texture,
2617                                                          d3d11::SharedSRV *outSRV)
2618 {
2619     ASSERT(outSRV);
2620 
2621     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2622     srvDesc.Format = format;
2623 
2624     // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six
2625     // 2D textures
2626     const GLenum componentType = d3d11::GetComponentType(format);
2627     if (componentType == GL_INT || componentType == GL_UNSIGNED_INT)
2628     {
2629         srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2630         srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
2631         srvDesc.Texture2DArray.MipLevels       = mipLevels;
2632         srvDesc.Texture2DArray.FirstArraySlice = 0;
2633         srvDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2634     }
2635     else
2636     {
2637         srvDesc.ViewDimension               = D3D11_SRV_DIMENSION_TEXTURECUBE;
2638         srvDesc.TextureCube.MipLevels       = mipLevels;
2639         srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
2640     }
2641 
2642     const TextureHelper11 *srvTexture = &texture;
2643 
2644     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
2645     {
2646         ASSERT(mTopLevel == 0);
2647         ASSERT(baseLevel == 0);
2648         // This code also assumes that the incoming texture equals either mLevelZeroTexture or
2649         // mTexture.
2650 
2651         if (mipLevels == 1 && mMipLevels > 1)
2652         {
2653             // We must use a SRV on the level-zero-only texture.
2654             ANGLE_TRY(ensureTextureExists(context, 1));
2655             srvTexture = &mLevelZeroTexture;
2656         }
2657         else
2658         {
2659             ASSERT(mipLevels == static_cast<int>(mMipLevels));
2660             ASSERT(mTexture.valid() && texture == mTexture);
2661             srvTexture = &mTexture;
2662         }
2663     }
2664 
2665     ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, srvTexture->get(),
2666                                           outSRV));
2667     outSRV->setLabels("TexStorageCube.SRV", &mTextureLabel);
2668 
2669     return angle::Result::Continue;
2670 }
2671 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2672 angle::Result TextureStorage11_Cube::createSRVForImage(const gl::Context *context,
2673                                                        int level,
2674                                                        DXGI_FORMAT format,
2675                                                        const TextureHelper11 &texture,
2676                                                        d3d11::SharedSRV *outSRV)
2677 {
2678     ASSERT(outSRV);
2679     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2680     srvDesc.Format                         = format;
2681     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2682     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
2683     srvDesc.Texture2DArray.MipLevels       = 1;
2684     srvDesc.Texture2DArray.FirstArraySlice = 0;
2685     srvDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2686     ANGLE_TRY(
2687         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
2688     outSRV->setLabels("TexStorageCube.SRVForImage", &mTextureLabel);
2689     return angle::Result::Continue;
2690 }
2691 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)2692 angle::Result TextureStorage11_Cube::createUAVForImage(const gl::Context *context,
2693                                                        int level,
2694                                                        DXGI_FORMAT format,
2695                                                        const TextureHelper11 &texture,
2696                                                        d3d11::SharedUAV *outUAV)
2697 {
2698     ASSERT(outUAV);
2699     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
2700     uavDesc.Format                         = format;
2701     uavDesc.ViewDimension                  = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
2702     uavDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2703     uavDesc.Texture2DArray.FirstArraySlice = 0;
2704     uavDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2705     ANGLE_TRY(
2706         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
2707     outUAV->setLabels("TexStorageCube.UAVForImage", &mTextureLabel);
2708     return angle::Result::Continue;
2709 }
2710 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)2711 angle::Result TextureStorage11_Cube::getSwizzleTexture(const gl::Context *context,
2712                                                        const TextureHelper11 **outTexture)
2713 {
2714     ASSERT(outTexture);
2715 
2716     if (!mSwizzleTexture.valid())
2717     {
2718         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
2719 
2720         D3D11_TEXTURE2D_DESC desc;
2721         desc.Width              = mTextureWidth;
2722         desc.Height             = mTextureHeight;
2723         desc.MipLevels          = mMipLevels;
2724         desc.ArraySize          = gl::kCubeFaceCount;
2725         desc.Format             = format.texFormat;
2726         desc.SampleDesc.Count   = 1;
2727         desc.SampleDesc.Quality = 0;
2728         desc.Usage              = D3D11_USAGE_DEFAULT;
2729         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
2730         desc.CPUAccessFlags     = 0;
2731         desc.MiscFlags          = D3D11_RESOURCE_MISC_TEXTURECUBE;
2732 
2733         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
2734                                              &mSwizzleTexture));
2735         mSwizzleTexture.setLabels("TexStorageCube.SwizzleTexture", &mTextureLabel);
2736     }
2737 
2738     *outTexture = &mSwizzleTexture;
2739     return angle::Result::Continue;
2740 }
2741 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)2742 angle::Result TextureStorage11_Cube::getSwizzleRenderTarget(const gl::Context *context,
2743                                                             int mipLevel,
2744                                                             const d3d11::RenderTargetView **outRTV)
2745 {
2746     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2747     ASSERT(outRTV);
2748 
2749     if (!mSwizzleRenderTargets[mipLevel].valid())
2750     {
2751         const TextureHelper11 *swizzleTexture = nullptr;
2752         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
2753 
2754         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2755         rtvDesc.Format =
2756             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
2757         rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2758         rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
2759         rtvDesc.Texture2DArray.FirstArraySlice = 0;
2760         rtvDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2761 
2762         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
2763                                               mSwizzleTexture.get(),
2764                                               &mSwizzleRenderTargets[mipLevel]));
2765     }
2766 
2767     *outRTV = &mSwizzleRenderTargets[mipLevel];
2768     return angle::Result::Continue;
2769 }
2770 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)2771 angle::Result TextureStorage11_Cube::ensureDropStencilTexture(const gl::Context *context,
2772                                                               DropStencil *dropStencilOut)
2773 {
2774     if (mDropStencilTexture.valid())
2775     {
2776         *dropStencilOut = DropStencil::ALREADY_EXISTS;
2777         return angle::Result::Continue;
2778     }
2779 
2780     D3D11_TEXTURE2D_DESC dropDesc = {};
2781     dropDesc.ArraySize            = 6;
2782     dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
2783     dropDesc.CPUAccessFlags       = 0;
2784     dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
2785     dropDesc.Height               = mTextureHeight;
2786     dropDesc.MipLevels            = mMipLevels;
2787     dropDesc.MiscFlags            = D3D11_RESOURCE_MISC_TEXTURECUBE;
2788     dropDesc.SampleDesc.Count     = 1;
2789     dropDesc.SampleDesc.Quality   = 0;
2790     dropDesc.Usage                = D3D11_USAGE_DEFAULT;
2791     dropDesc.Width                = mTextureWidth;
2792 
2793     const auto &format =
2794         d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
2795     ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
2796                                          &mDropStencilTexture));
2797     mDropStencilTexture.setLabels("TexStorageCube.DropStencil", &mTextureLabel);
2798 
2799     ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
2800 
2801     *dropStencilOut = DropStencil::CREATED;
2802     return angle::Result::Continue;
2803 }
2804 
resolveTexture(const gl::Context * context)2805 angle::Result TextureStorage11_Cube::resolveTexture(const gl::Context *context)
2806 {
2807     if (mMSTexInfo && mMSTexInfo->msTex && mMSTexInfo->msTextureNeedsResolve)
2808     {
2809         ANGLE_TRY(resolveTextureHelper(context, mTexture));
2810         onStateChange(angle::SubjectMessage::ContentsChanged);
2811     }
2812     return angle::Result::Continue;
2813 }
2814 
onLabelUpdate()2815 void TextureStorage11_Cube::onLabelUpdate()
2816 {
2817     if (mTexture.valid())
2818     {
2819         mTexture.setKHRDebugLabel(&mTextureLabel);
2820     }
2821     if (mLevelZeroTexture.valid())
2822     {
2823         mLevelZeroTexture.setKHRDebugLabel(&mTextureLabel);
2824     }
2825     if (mSwizzleTexture.valid())
2826     {
2827         mSwizzleTexture.setKHRDebugLabel(&mTextureLabel);
2828     }
2829 }
2830 
TextureStorage11_3D(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels,const std::string & label)2831 TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
2832                                          GLenum internalformat,
2833                                          bool renderTarget,
2834                                          GLsizei width,
2835                                          GLsizei height,
2836                                          GLsizei depth,
2837                                          int levels,
2838                                          const std::string &label)
2839     : TextureStorage11(
2840           renderer,
2841           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
2842           GetTextureMiscFlags(internalformat,
2843                               renderer->getRenderer11DeviceCaps(),
2844                               renderTarget,
2845                               levels),
2846           internalformat,
2847           label)
2848 {
2849     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2850     {
2851         mAssociatedImages[i]   = nullptr;
2852         mLevelRenderTargets[i] = nullptr;
2853     }
2854 
2855     // adjust size if needed for compressed textures
2856     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
2857 
2858     mMipLevels     = mTopLevel + levels;
2859     mTextureWidth  = width;
2860     mTextureHeight = height;
2861     mTextureDepth  = depth;
2862 }
2863 
onDestroy(const gl::Context * context)2864 angle::Result TextureStorage11_3D::onDestroy(const gl::Context *context)
2865 {
2866     for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2867     {
2868         if (mAssociatedImages[i] != nullptr)
2869         {
2870             mAssociatedImages[i]->verifyAssociatedStorageValid(this);
2871 
2872             // We must let the Images recover their data before we delete it from the
2873             // TextureStorage.
2874             ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
2875         }
2876     }
2877 
2878     return angle::Result::Continue;
2879 }
2880 
~TextureStorage11_3D()2881 TextureStorage11_3D::~TextureStorage11_3D() {}
2882 
associateImage(Image11 * image,const gl::ImageIndex & index)2883 void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
2884 {
2885     const GLint level = index.getLevelIndex();
2886 
2887     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2888 
2889     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2890     {
2891         mAssociatedImages[level] = image;
2892     }
2893 }
2894 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2895 void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index,
2896                                                      Image11 *expectedImage)
2897 {
2898     const GLint level = index.getLevelIndex();
2899 
2900     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2901     // This validation check should never return false. It means the Image/TextureStorage
2902     // association is broken.
2903     ASSERT(mAssociatedImages[level] == expectedImage);
2904 }
2905 
2906 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)2907 void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
2908 {
2909     const GLint level = index.getLevelIndex();
2910 
2911     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2912     ASSERT(mAssociatedImages[level] == expectedImage);
2913     mAssociatedImages[level] = nullptr;
2914 }
2915 
2916 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
2917 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)2918 angle::Result TextureStorage11_3D::releaseAssociatedImage(const gl::Context *context,
2919                                                           const gl::ImageIndex &index,
2920                                                           Image11 *incomingImage)
2921 {
2922     const GLint level = index.getLevelIndex();
2923 
2924     ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
2925 
2926     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2927     {
2928         // No need to let the old Image recover its data, if it is also the incoming Image.
2929         if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
2930         {
2931             // Ensure that the Image is still associated with this TextureStorage.
2932             mAssociatedImages[level]->verifyAssociatedStorageValid(this);
2933 
2934             // Force the image to recover from storage before its data is overwritten.
2935             // This will reset mAssociatedImages[level] to nullptr too.
2936             ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
2937         }
2938     }
2939 
2940     return angle::Result::Continue;
2941 }
2942 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)2943 angle::Result TextureStorage11_3D::getResource(const gl::Context *context,
2944                                                const TextureHelper11 **outResource)
2945 {
2946     // If the width, height or depth are not positive this should be treated as an incomplete
2947     // texture. We handle that here by skipping the d3d texture creation.
2948     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
2949     {
2950         ASSERT(mMipLevels > 0);
2951 
2952         D3D11_TEXTURE3D_DESC desc;
2953         desc.Width          = mTextureWidth;
2954         desc.Height         = mTextureHeight;
2955         desc.Depth          = mTextureDepth;
2956         desc.MipLevels      = mMipLevels;
2957         desc.Format         = mFormatInfo.texFormat;
2958         desc.Usage          = D3D11_USAGE_DEFAULT;
2959         desc.BindFlags      = getBindFlags();
2960         desc.CPUAccessFlags = 0;
2961         desc.MiscFlags      = getMiscFlags();
2962 
2963         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
2964                                              &mTexture));
2965         mTexture.setLabels("TexStorage3D.Texture", &mTextureLabel);
2966     }
2967 
2968     *outResource = &mTexture;
2969     return angle::Result::Continue;
2970 }
2971 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2972 angle::Result TextureStorage11_3D::createSRVForSampler(const gl::Context *context,
2973                                                        int baseLevel,
2974                                                        int mipLevels,
2975                                                        DXGI_FORMAT format,
2976                                                        const TextureHelper11 &texture,
2977                                                        d3d11::SharedSRV *outSRV)
2978 {
2979     ASSERT(outSRV);
2980 
2981     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2982     srvDesc.Format                    = format;
2983     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE3D;
2984     srvDesc.Texture3D.MostDetailedMip = baseLevel;
2985     srvDesc.Texture3D.MipLevels       = mipLevels;
2986 
2987     ANGLE_TRY(
2988         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
2989     outSRV->setLabels("TexStorage3D.SRV", &mTextureLabel);
2990 
2991     return angle::Result::Continue;
2992 }
2993 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2994 angle::Result TextureStorage11_3D::createSRVForImage(const gl::Context *context,
2995                                                      int level,
2996                                                      DXGI_FORMAT format,
2997                                                      const TextureHelper11 &texture,
2998                                                      d3d11::SharedSRV *outSRV)
2999 {
3000     ASSERT(outSRV);
3001     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3002     srvDesc.Format                    = format;
3003     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE3D;
3004     srvDesc.Texture3D.MostDetailedMip = mTopLevel + level;
3005     srvDesc.Texture3D.MipLevels       = 1;
3006     ANGLE_TRY(
3007         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3008     outSRV->setLabels("TexStorage3D.SRVForImage", &mTextureLabel);
3009     return angle::Result::Continue;
3010 }
3011 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)3012 angle::Result TextureStorage11_3D::createUAVForImage(const gl::Context *context,
3013                                                      int level,
3014                                                      DXGI_FORMAT format,
3015                                                      const TextureHelper11 &texture,
3016                                                      d3d11::SharedUAV *outUAV)
3017 {
3018     ASSERT(outUAV);
3019     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
3020     uavDesc.Format                = format;
3021     uavDesc.ViewDimension         = D3D11_UAV_DIMENSION_TEXTURE3D;
3022     uavDesc.Texture3D.MipSlice    = mTopLevel + level;
3023     uavDesc.Texture3D.FirstWSlice = 0;
3024     uavDesc.Texture3D.WSize       = mTextureDepth;
3025     ANGLE_TRY(
3026         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
3027     outUAV->setLabels("TexStorage3D.UAVForImage", &mTextureLabel);
3028     return angle::Result::Continue;
3029 }
3030 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3031 angle::Result TextureStorage11_3D::findRenderTarget(const gl::Context *context,
3032                                                     const gl::ImageIndex &index,
3033                                                     GLsizei samples,
3034                                                     RenderTargetD3D **outRT) const
3035 {
3036     const int mipLevel = index.getLevelIndex();
3037     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3038 
3039     if (!index.hasLayer())
3040     {
3041         ASSERT(outRT);
3042         *outRT = mLevelRenderTargets[mipLevel].get();
3043         return angle::Result::Continue;
3044     }
3045 
3046     const int layer = index.getLayerIndex();
3047 
3048     LevelLayerKey key(mipLevel, layer);
3049     if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
3050     {
3051         ASSERT(outRT);
3052         *outRT = nullptr;
3053         return angle::Result::Continue;
3054     }
3055 
3056     ASSERT(outRT);
3057     *outRT = mLevelLayerRenderTargets.at(key).get();
3058     return angle::Result::Continue;
3059 }
3060 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)3061 angle::Result TextureStorage11_3D::getRenderTarget(const gl::Context *context,
3062                                                    const gl::ImageIndex &index,
3063                                                    GLsizei samples,
3064                                                    RenderTargetD3D **outRT)
3065 {
3066     const int mipLevel = index.getLevelIndex();
3067     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3068 
3069     ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
3070 
3071     Context11 *context11 = GetImplAs<Context11>(context);
3072 
3073     if (!index.hasLayer())
3074     {
3075         if (!mLevelRenderTargets[mipLevel])
3076         {
3077             const TextureHelper11 *texture = nullptr;
3078             ANGLE_TRY(getResource(context, &texture));
3079 
3080             const d3d11::SharedSRV *srv = nullptr;
3081             ANGLE_TRY(getSRVLevel(context, mipLevel, false, &srv));
3082 
3083             const d3d11::SharedSRV *blitSRV = nullptr;
3084             ANGLE_TRY(getSRVLevel(context, mipLevel, true, &blitSRV));
3085 
3086             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3087             rtvDesc.Format                = mFormatInfo.rtvFormat;
3088             rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
3089             rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
3090             rtvDesc.Texture3D.FirstWSlice = 0;
3091             rtvDesc.Texture3D.WSize       = static_cast<UINT>(-1);
3092 
3093             d3d11::RenderTargetView rtv;
3094             ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
3095             rtv.setLabels("TexStorage3D.RTV", &mTextureLabel);
3096 
3097             mLevelRenderTargets[mipLevel].reset(new TextureRenderTarget11(
3098                 std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat,
3099                 getFormatSet(), getLevelWidth(mipLevel), getLevelHeight(mipLevel),
3100                 getLevelDepth(mipLevel), 0));
3101         }
3102 
3103         ASSERT(outRT);
3104         *outRT = mLevelRenderTargets[mipLevel].get();
3105         return angle::Result::Continue;
3106     }
3107 
3108     const int layer = index.getLayerIndex();
3109 
3110     LevelLayerKey key(mipLevel, layer);
3111     if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
3112     {
3113         const TextureHelper11 *texture = nullptr;
3114         ANGLE_TRY(getResource(context, &texture));
3115 
3116         // TODO, what kind of SRV is expected here?
3117         const d3d11::SharedSRV srv;
3118         const d3d11::SharedSRV blitSRV;
3119 
3120         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3121         rtvDesc.Format                = mFormatInfo.rtvFormat;
3122         rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
3123         rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
3124         rtvDesc.Texture3D.FirstWSlice = layer;
3125         rtvDesc.Texture3D.WSize       = 1;
3126 
3127         d3d11::RenderTargetView rtv;
3128         ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
3129         rtv.setLabels("TexStorage3D.LayerRTV", &mTextureLabel);
3130 
3131         mLevelLayerRenderTargets[key].reset(new TextureRenderTarget11(
3132             std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3133             getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
3134     }
3135 
3136     ASSERT(outRT);
3137     *outRT = mLevelLayerRenderTargets[key].get();
3138     return angle::Result::Continue;
3139 }
3140 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)3141 angle::Result TextureStorage11_3D::getSwizzleTexture(const gl::Context *context,
3142                                                      const TextureHelper11 **outTexture)
3143 {
3144     ASSERT(outTexture);
3145 
3146     if (!mSwizzleTexture.valid())
3147     {
3148         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
3149 
3150         D3D11_TEXTURE3D_DESC desc;
3151         desc.Width          = mTextureWidth;
3152         desc.Height         = mTextureHeight;
3153         desc.Depth          = mTextureDepth;
3154         desc.MipLevels      = mMipLevels;
3155         desc.Format         = format.texFormat;
3156         desc.Usage          = D3D11_USAGE_DEFAULT;
3157         desc.BindFlags      = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
3158         desc.CPUAccessFlags = 0;
3159         desc.MiscFlags      = 0;
3160 
3161         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
3162                                              &mSwizzleTexture));
3163         mSwizzleTexture.setLabels("TexStorage3D.SwizzleTexture", &mTextureLabel);
3164     }
3165 
3166     *outTexture = &mSwizzleTexture;
3167     return angle::Result::Continue;
3168 }
3169 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)3170 angle::Result TextureStorage11_3D::getSwizzleRenderTarget(const gl::Context *context,
3171                                                           int mipLevel,
3172                                                           const d3d11::RenderTargetView **outRTV)
3173 {
3174     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3175     ASSERT(outRTV);
3176 
3177     if (!mSwizzleRenderTargets[mipLevel].valid())
3178     {
3179         const TextureHelper11 *swizzleTexture = nullptr;
3180         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
3181 
3182         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3183         rtvDesc.Format =
3184             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
3185         rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
3186         rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
3187         rtvDesc.Texture3D.FirstWSlice = 0;
3188         rtvDesc.Texture3D.WSize       = static_cast<UINT>(-1);
3189 
3190         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3191                                               mSwizzleTexture.get(),
3192                                               &mSwizzleRenderTargets[mipLevel]));
3193         mSwizzleRenderTargets[mipLevel].setLabels("TexStorage3D.SwizzleRTV", &mTextureLabel);
3194     }
3195 
3196     *outRTV = &mSwizzleRenderTargets[mipLevel];
3197     return angle::Result::Continue;
3198 }
3199 
onLabelUpdate()3200 void TextureStorage11_3D::onLabelUpdate()
3201 {
3202     if (mTexture.valid())
3203     {
3204         mTexture.setKHRDebugLabel(&mTextureLabel);
3205     }
3206     if (mSwizzleTexture.valid())
3207     {
3208         mSwizzleTexture.setKHRDebugLabel(&mTextureLabel);
3209     }
3210 }
3211 
TextureStorage11_2DArray(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels,const std::string & label)3212 TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer,
3213                                                    GLenum internalformat,
3214                                                    bool renderTarget,
3215                                                    GLsizei width,
3216                                                    GLsizei height,
3217                                                    GLsizei depth,
3218                                                    int levels,
3219                                                    const std::string &label)
3220     : TextureStorage11(
3221           renderer,
3222           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
3223           GetTextureMiscFlags(internalformat,
3224                               renderer->getRenderer11DeviceCaps(),
3225                               renderTarget,
3226                               levels),
3227           internalformat,
3228           label)
3229 {
3230     // adjust size if needed for compressed textures
3231     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
3232 
3233     mMipLevels     = mTopLevel + levels;
3234     mTextureWidth  = width;
3235     mTextureHeight = height;
3236     mTextureDepth  = depth;
3237 }
3238 
onDestroy(const gl::Context * context)3239 angle::Result TextureStorage11_2DArray::onDestroy(const gl::Context *context)
3240 {
3241     for (auto iter : mAssociatedImages)
3242     {
3243         if (iter.second)
3244         {
3245             iter.second->verifyAssociatedStorageValid(this);
3246 
3247             // We must let the Images recover their data before we delete it from the
3248             // TextureStorage.
3249             ANGLE_TRY(iter.second->recoverFromAssociatedStorage(context));
3250         }
3251     }
3252     mAssociatedImages.clear();
3253 
3254     return angle::Result::Continue;
3255 }
3256 
~TextureStorage11_2DArray()3257 TextureStorage11_2DArray::~TextureStorage11_2DArray() {}
3258 
associateImage(Image11 * image,const gl::ImageIndex & index)3259 void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
3260 {
3261     const GLint level       = index.getLevelIndex();
3262     const GLint layerTarget = index.getLayerIndex();
3263     const GLint numLayers   = index.getLayerCount();
3264 
3265     ASSERT(0 <= level && level < getLevelCount());
3266 
3267     if (0 <= level && level < getLevelCount())
3268     {
3269         LevelLayerRangeKey key(level, layerTarget, numLayers);
3270         mAssociatedImages[key] = image;
3271     }
3272 }
3273 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)3274 void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index,
3275                                                           Image11 *expectedImage)
3276 {
3277     const GLint level       = index.getLevelIndex();
3278     const GLint layerTarget = index.getLayerIndex();
3279     const GLint numLayers   = index.getLayerCount();
3280 
3281     LevelLayerRangeKey key(level, layerTarget, numLayers);
3282 
3283     // This validation check should never return false. It means the Image/TextureStorage
3284     // association is broken.
3285     bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
3286                      (mAssociatedImages[key] == expectedImage));
3287     ASSERT(retValue);
3288 }
3289 
3290 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)3291 void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index,
3292                                                  Image11 *expectedImage)
3293 {
3294     const GLint level       = index.getLevelIndex();
3295     const GLint layerTarget = index.getLayerIndex();
3296     const GLint numLayers   = index.getLayerCount();
3297 
3298     LevelLayerRangeKey key(level, layerTarget, numLayers);
3299 
3300     bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
3301                                     (mAssociatedImages[key] == expectedImage));
3302     ASSERT(imageAssociationCorrect);
3303     mAssociatedImages[key] = nullptr;
3304 }
3305 
3306 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
3307 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)3308 angle::Result TextureStorage11_2DArray::releaseAssociatedImage(const gl::Context *context,
3309                                                                const gl::ImageIndex &index,
3310                                                                Image11 *incomingImage)
3311 {
3312     const GLint level       = index.getLevelIndex();
3313     const GLint layerTarget = index.getLayerIndex();
3314     const GLint numLayers   = index.getLayerCount();
3315 
3316     LevelLayerRangeKey key(level, layerTarget, numLayers);
3317 
3318     if (mAssociatedImages.find(key) != mAssociatedImages.end())
3319     {
3320         if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage)
3321         {
3322             // Ensure that the Image is still associated with this TextureStorage.
3323             mAssociatedImages[key]->verifyAssociatedStorageValid(this);
3324 
3325             // Force the image to recover from storage before its data is overwritten.
3326             // This will reset mAssociatedImages[level] to nullptr too.
3327             ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage(context));
3328         }
3329     }
3330 
3331     return angle::Result::Continue;
3332 }
3333 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3334 angle::Result TextureStorage11_2DArray::getResource(const gl::Context *context,
3335                                                     const TextureHelper11 **outResource)
3336 {
3337     // if the width, height or depth is not positive this should be treated as an incomplete texture
3338     // we handle that here by skipping the d3d texture creation
3339     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
3340     {
3341         ASSERT(mMipLevels > 0);
3342 
3343         D3D11_TEXTURE2D_DESC desc;
3344         desc.Width              = mTextureWidth;
3345         desc.Height             = mTextureHeight;
3346         desc.MipLevels          = mMipLevels;
3347         desc.ArraySize          = mTextureDepth;
3348         desc.Format             = mFormatInfo.texFormat;
3349         desc.SampleDesc.Count   = 1;
3350         desc.SampleDesc.Quality = 0;
3351         desc.Usage              = D3D11_USAGE_DEFAULT;
3352         desc.BindFlags          = getBindFlags();
3353         desc.CPUAccessFlags     = 0;
3354         desc.MiscFlags          = getMiscFlags();
3355 
3356         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
3357                                              &mTexture));
3358         mTexture.setLabels("TexStorage2DArray.Texture", &mTextureLabel);
3359     }
3360 
3361     *outResource = &mTexture;
3362     return angle::Result::Continue;
3363 }
3364 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3365 angle::Result TextureStorage11_2DArray::createSRVForSampler(const gl::Context *context,
3366                                                             int baseLevel,
3367                                                             int mipLevels,
3368                                                             DXGI_FORMAT format,
3369                                                             const TextureHelper11 &texture,
3370                                                             d3d11::SharedSRV *outSRV)
3371 {
3372     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3373     srvDesc.Format                         = format;
3374     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3375     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
3376     srvDesc.Texture2DArray.MipLevels       = mipLevels;
3377     srvDesc.Texture2DArray.FirstArraySlice = 0;
3378     srvDesc.Texture2DArray.ArraySize       = mTextureDepth;
3379 
3380     ANGLE_TRY(
3381         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3382     outSRV->setLabels("TexStorage2DArray.SRV", &mTextureLabel);
3383 
3384     return angle::Result::Continue;
3385 }
3386 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3387 angle::Result TextureStorage11_2DArray::createSRVForImage(const gl::Context *context,
3388                                                           int level,
3389                                                           DXGI_FORMAT format,
3390                                                           const TextureHelper11 &texture,
3391                                                           d3d11::SharedSRV *outSRV)
3392 {
3393     ASSERT(outSRV);
3394     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3395     srvDesc.Format                         = format;
3396     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3397     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
3398     srvDesc.Texture2DArray.MipLevels       = 1;
3399     srvDesc.Texture2DArray.FirstArraySlice = 0;
3400     srvDesc.Texture2DArray.ArraySize       = mTextureDepth;
3401     ANGLE_TRY(
3402         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3403     outSRV->setLabels("TexStorage2DArray.SRVForImage", &mTextureLabel);
3404     return angle::Result::Continue;
3405 }
3406 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)3407 angle::Result TextureStorage11_2DArray::createUAVForImage(const gl::Context *context,
3408                                                           int level,
3409                                                           DXGI_FORMAT format,
3410                                                           const TextureHelper11 &texture,
3411                                                           d3d11::SharedUAV *outUAV)
3412 {
3413     ASSERT(outUAV);
3414     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
3415     uavDesc.Format                         = format;
3416     uavDesc.ViewDimension                  = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3417     uavDesc.Texture2DArray.MipSlice        = mTopLevel + level;
3418     uavDesc.Texture2DArray.FirstArraySlice = 0;
3419     uavDesc.Texture2DArray.ArraySize       = mTextureDepth;
3420     ANGLE_TRY(
3421         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
3422     outUAV->setLabels("TexStorage2DArray.UAVForImage", &mTextureLabel);
3423     return angle::Result::Continue;
3424 }
3425 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3426 angle::Result TextureStorage11_2DArray::findRenderTarget(const gl::Context *context,
3427                                                          const gl::ImageIndex &index,
3428                                                          GLsizei samples,
3429                                                          RenderTargetD3D **outRT) const
3430 {
3431     ASSERT(index.hasLayer());
3432 
3433     const int mipLevel  = index.getLevelIndex();
3434     const int layer     = index.getLayerIndex();
3435     const int numLayers = index.getLayerCount();
3436 
3437     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3438 
3439     LevelLayerRangeKey key(mipLevel, layer, numLayers);
3440     if (mRenderTargets.find(key) == mRenderTargets.end())
3441     {
3442         ASSERT(outRT);
3443         *outRT = nullptr;
3444         return angle::Result::Continue;
3445     }
3446 
3447     ASSERT(outRT);
3448     *outRT = mRenderTargets.at(key).get();
3449     return angle::Result::Continue;
3450 }
3451 
createRenderTargetSRV(const gl::Context * context,const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const3452 angle::Result TextureStorage11_2DArray::createRenderTargetSRV(const gl::Context *context,
3453                                                               const TextureHelper11 &texture,
3454                                                               const gl::ImageIndex &index,
3455                                                               DXGI_FORMAT resourceFormat,
3456                                                               d3d11::SharedSRV *srv) const
3457 {
3458     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3459     srvDesc.Format                         = resourceFormat;
3460     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3461     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
3462     srvDesc.Texture2DArray.MipLevels       = 1;
3463     srvDesc.Texture2DArray.FirstArraySlice = index.getLayerIndex();
3464     srvDesc.Texture2DArray.ArraySize       = index.getLayerCount();
3465 
3466     ANGLE_TRY(
3467         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
3468 
3469     return angle::Result::Continue;
3470 }
3471 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)3472 angle::Result TextureStorage11_2DArray::getRenderTarget(const gl::Context *context,
3473                                                         const gl::ImageIndex &index,
3474                                                         GLsizei samples,
3475                                                         RenderTargetD3D **outRT)
3476 {
3477     ASSERT(index.hasLayer());
3478 
3479     const int mipLevel  = index.getLevelIndex();
3480     const int layer     = index.getLayerIndex();
3481     const int numLayers = index.getLayerCount();
3482 
3483     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3484 
3485     LevelLayerRangeKey key(mipLevel, layer, numLayers);
3486     if (mRenderTargets.find(key) == mRenderTargets.end())
3487     {
3488         const TextureHelper11 *texture = nullptr;
3489         ANGLE_TRY(getResource(context, &texture));
3490         d3d11::SharedSRV srv;
3491         ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
3492         d3d11::SharedSRV blitSRV;
3493         if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
3494         {
3495             ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
3496                                             &blitSRV));
3497         }
3498         else
3499         {
3500             blitSRV = srv.makeCopy();
3501         }
3502 
3503         srv.setLabels("TexStorage2DArray.RenderTargetSRV", &mTextureLabel);
3504 
3505         if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
3506         {
3507             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3508             rtvDesc.Format                         = mFormatInfo.rtvFormat;
3509             rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
3510             rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
3511             rtvDesc.Texture2DArray.FirstArraySlice = layer;
3512             rtvDesc.Texture2DArray.ArraySize       = numLayers;
3513 
3514             d3d11::RenderTargetView rtv;
3515             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3516                                                   texture->get(), &rtv));
3517             rtv.setLabels("TexStorage2DArray.RenderTargetRTV", &mTextureLabel);
3518 
3519             mRenderTargets[key].reset(new TextureRenderTarget11(
3520                 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3521                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
3522         }
3523         else
3524         {
3525             ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
3526 
3527             D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
3528             dsvDesc.Format                         = mFormatInfo.dsvFormat;
3529             dsvDesc.ViewDimension                  = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
3530             dsvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
3531             dsvDesc.Texture2DArray.FirstArraySlice = layer;
3532             dsvDesc.Texture2DArray.ArraySize       = numLayers;
3533             dsvDesc.Flags                          = 0;
3534 
3535             d3d11::DepthStencilView dsv;
3536             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), dsvDesc,
3537                                                   texture->get(), &dsv));
3538             dsv.setLabels("TexStorage2DArray.RenderTargetDSV", &mTextureLabel);
3539 
3540             mRenderTargets[key].reset(new TextureRenderTarget11(
3541                 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
3542                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
3543         }
3544     }
3545 
3546     ASSERT(outRT);
3547     *outRT = mRenderTargets[key].get();
3548     return angle::Result::Continue;
3549 }
3550 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)3551 angle::Result TextureStorage11_2DArray::getSwizzleTexture(const gl::Context *context,
3552                                                           const TextureHelper11 **outTexture)
3553 {
3554     if (!mSwizzleTexture.valid())
3555     {
3556         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
3557 
3558         D3D11_TEXTURE2D_DESC desc;
3559         desc.Width              = mTextureWidth;
3560         desc.Height             = mTextureHeight;
3561         desc.MipLevels          = mMipLevels;
3562         desc.ArraySize          = mTextureDepth;
3563         desc.Format             = format.texFormat;
3564         desc.SampleDesc.Count   = 1;
3565         desc.SampleDesc.Quality = 0;
3566         desc.Usage              = D3D11_USAGE_DEFAULT;
3567         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
3568         desc.CPUAccessFlags     = 0;
3569         desc.MiscFlags          = 0;
3570 
3571         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
3572                                              &mSwizzleTexture));
3573         mSwizzleTexture.setLabels("TexStorage2DArray.SwizzleTexture", &mTextureLabel);
3574     }
3575 
3576     *outTexture = &mSwizzleTexture;
3577     return angle::Result::Continue;
3578 }
3579 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)3580 angle::Result TextureStorage11_2DArray::getSwizzleRenderTarget(
3581     const gl::Context *context,
3582     int mipLevel,
3583     const d3d11::RenderTargetView **outRTV)
3584 {
3585     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3586     ASSERT(outRTV);
3587 
3588     if (!mSwizzleRenderTargets[mipLevel].valid())
3589     {
3590         const TextureHelper11 *swizzleTexture = nullptr;
3591         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
3592 
3593         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3594         rtvDesc.Format =
3595             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
3596         rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
3597         rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
3598         rtvDesc.Texture2DArray.FirstArraySlice = 0;
3599         rtvDesc.Texture2DArray.ArraySize       = mTextureDepth;
3600 
3601         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3602                                               mSwizzleTexture.get(),
3603                                               &mSwizzleRenderTargets[mipLevel]));
3604     }
3605 
3606     *outRTV = &mSwizzleRenderTargets[mipLevel];
3607     return angle::Result::Continue;
3608 }
3609 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)3610 angle::Result TextureStorage11_2DArray::ensureDropStencilTexture(const gl::Context *context,
3611                                                                  DropStencil *dropStencilOut)
3612 {
3613     if (mDropStencilTexture.valid())
3614     {
3615         *dropStencilOut = DropStencil::ALREADY_EXISTS;
3616         return angle::Result::Continue;
3617     }
3618 
3619     D3D11_TEXTURE2D_DESC dropDesc = {};
3620     dropDesc.ArraySize            = mTextureDepth;
3621     dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
3622     dropDesc.CPUAccessFlags       = 0;
3623     dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
3624     dropDesc.Height               = mTextureHeight;
3625     dropDesc.MipLevels            = mMipLevels;
3626     dropDesc.MiscFlags            = 0;
3627     dropDesc.SampleDesc.Count     = 1;
3628     dropDesc.SampleDesc.Quality   = 0;
3629     dropDesc.Usage                = D3D11_USAGE_DEFAULT;
3630     dropDesc.Width                = mTextureWidth;
3631 
3632     const auto &format =
3633         d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
3634     ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
3635                                          &mDropStencilTexture));
3636     mDropStencilTexture.setLabels("TexStorage2DArray.DropStencil", &mTextureLabel);
3637 
3638     std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
3639 
3640     ANGLE_TRY(initDropStencilTexture(
3641         context, gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
3642 
3643     *dropStencilOut = DropStencil::CREATED;
3644     return angle::Result::Continue;
3645 }
3646 
onLabelUpdate()3647 void TextureStorage11_2DArray::onLabelUpdate()
3648 {
3649     if (mTexture.valid())
3650     {
3651         mTexture.setKHRDebugLabel(&mTextureLabel);
3652     }
3653     if (mSwizzleTexture.valid())
3654     {
3655         mSwizzleTexture.setKHRDebugLabel(&mTextureLabel);
3656     }
3657 }
3658 
TextureStorage11_2DMultisample(Renderer11 * renderer,GLenum internalformat,GLsizei width,GLsizei height,int levels,int samples,bool fixedSampleLocations,const std::string & label)3659 TextureStorage11_2DMultisample::TextureStorage11_2DMultisample(Renderer11 *renderer,
3660                                                                GLenum internalformat,
3661                                                                GLsizei width,
3662                                                                GLsizei height,
3663                                                                int levels,
3664                                                                int samples,
3665                                                                bool fixedSampleLocations,
3666                                                                const std::string &label)
3667     : TextureStorage11ImmutableBase(
3668           renderer,
3669           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true),
3670           GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels),
3671           internalformat,
3672           label),
3673       mTexture(),
3674       mRenderTarget(nullptr)
3675 {
3676     // There are no multisampled compressed formats, so there's no need to adjust texture size
3677     // according to block size.
3678     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockWidth <= 1);
3679     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockHeight <= 1);
3680 
3681     mMipLevels            = 1;
3682     mTextureWidth         = width;
3683     mTextureHeight        = height;
3684     mTextureDepth         = 1;
3685     mSamples              = samples;
3686     mFixedSampleLocations = fixedSampleLocations;
3687 }
3688 
onDestroy(const gl::Context * context)3689 angle::Result TextureStorage11_2DMultisample::onDestroy(const gl::Context *context)
3690 {
3691     mRenderTarget.reset();
3692     return angle::Result::Continue;
3693 }
3694 
~TextureStorage11_2DMultisample()3695 TextureStorage11_2DMultisample::~TextureStorage11_2DMultisample() {}
3696 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)3697 angle::Result TextureStorage11_2DMultisample::copyToStorage(const gl::Context *context,
3698                                                             TextureStorage *destStorage)
3699 {
3700     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3701     return angle::Result::Stop;
3702 }
3703 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3704 angle::Result TextureStorage11_2DMultisample::getResource(const gl::Context *context,
3705                                                           const TextureHelper11 **outResource)
3706 {
3707     ANGLE_TRY(ensureTextureExists(context, 1));
3708 
3709     *outResource = &mTexture;
3710     return angle::Result::Continue;
3711 }
3712 
ensureTextureExists(const gl::Context * context,int mipLevels)3713 angle::Result TextureStorage11_2DMultisample::ensureTextureExists(const gl::Context *context,
3714                                                                   int mipLevels)
3715 {
3716     // For Multisampled textures, mipLevels always equals 1.
3717     ASSERT(mipLevels == 1);
3718 
3719     // if the width or height is not positive this should be treated as an incomplete texture
3720     // we handle that here by skipping the d3d texture creation
3721     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
3722     {
3723         D3D11_TEXTURE2D_DESC desc;
3724         ZeroMemory(&desc, sizeof(desc));
3725         desc.Width          = mTextureWidth;  // Compressed texture size constraints?
3726         desc.Height         = mTextureHeight;
3727         desc.MipLevels      = mipLevels;
3728         desc.ArraySize      = 1;
3729         desc.Format         = mFormatInfo.texFormat;
3730         desc.Usage          = D3D11_USAGE_DEFAULT;
3731         desc.BindFlags      = getBindFlags() & ~D3D11_BIND_UNORDERED_ACCESS;
3732         desc.CPUAccessFlags = 0;
3733         desc.MiscFlags      = getMiscFlags();
3734 
3735         const gl::TextureCaps &textureCaps =
3736             mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
3737         GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
3738         desc.SampleDesc.Count   = (supportedSamples == 0) ? 1 : supportedSamples;
3739         desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples);
3740 
3741         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
3742                                              &mTexture));
3743         mTexture.setLabels("TexStorage2DMS.Texture", &mTextureLabel);
3744     }
3745 
3746     return angle::Result::Continue;
3747 }
3748 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3749 angle::Result TextureStorage11_2DMultisample::findRenderTarget(const gl::Context *context,
3750                                                                const gl::ImageIndex &index,
3751                                                                GLsizei samples,
3752                                                                RenderTargetD3D **outRT) const
3753 {
3754     ASSERT(!index.hasLayer());
3755 
3756     const int level = index.getLevelIndex();
3757     ASSERT(level == 0);
3758 
3759     ASSERT(outRT);
3760     *outRT = mRenderTarget.get();
3761     return angle::Result::Continue;
3762 }
3763 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)3764 angle::Result TextureStorage11_2DMultisample::getRenderTarget(const gl::Context *context,
3765                                                               const gl::ImageIndex &index,
3766                                                               GLsizei samples,
3767                                                               RenderTargetD3D **outRT)
3768 {
3769     ASSERT(!index.hasLayer());
3770 
3771     const int level = index.getLevelIndex();
3772     ASSERT(level == 0);
3773 
3774     ASSERT(outRT);
3775     if (mRenderTarget)
3776     {
3777         *outRT = mRenderTarget.get();
3778         return angle::Result::Continue;
3779     }
3780 
3781     const TextureHelper11 *texture = nullptr;
3782     ANGLE_TRY(getResource(context, &texture));
3783 
3784     const d3d11::SharedSRV *srv = nullptr;
3785     ANGLE_TRY(getSRVLevel(context, level, false, &srv));
3786 
3787     const d3d11::SharedSRV *blitSRV = nullptr;
3788     ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
3789 
3790     Context11 *context11 = GetImplAs<Context11>(context);
3791 
3792     if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
3793     {
3794         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3795         rtvDesc.Format        = mFormatInfo.rtvFormat;
3796         rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
3797 
3798         d3d11::RenderTargetView rtv;
3799         ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
3800 
3801         mRenderTarget.reset(new TextureRenderTarget11(
3802             std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3803             getLevelWidth(level), getLevelHeight(level), 1, mSamples));
3804 
3805         *outRT = mRenderTarget.get();
3806         return angle::Result::Continue;
3807     }
3808 
3809     ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
3810 
3811     D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
3812     dsvDesc.Format        = mFormatInfo.dsvFormat;
3813     dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
3814     dsvDesc.Flags         = 0;
3815 
3816     d3d11::DepthStencilView dsv;
3817     ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
3818 
3819     mRenderTarget.reset(new TextureRenderTarget11(
3820         std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
3821         getLevelWidth(level), getLevelHeight(level), 1, mSamples));
3822 
3823     *outRT = mRenderTarget.get();
3824     return angle::Result::Continue;
3825 }
3826 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3827 angle::Result TextureStorage11_2DMultisample::createSRVForSampler(const gl::Context *context,
3828                                                                   int baseLevel,
3829                                                                   int mipLevels,
3830                                                                   DXGI_FORMAT format,
3831                                                                   const TextureHelper11 &texture,
3832                                                                   d3d11::SharedSRV *outSRV)
3833 {
3834     ASSERT(outSRV);
3835 
3836     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3837     srvDesc.Format        = format;
3838     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3839 
3840     ANGLE_TRY(
3841         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3842     outSRV->setLabels("TexStorage2DMS.SRV", &mTextureLabel);
3843     return angle::Result::Continue;
3844 }
3845 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)3846 angle::Result TextureStorage11_2DMultisample::getSwizzleTexture(const gl::Context *context,
3847                                                                 const TextureHelper11 **outTexture)
3848 {
3849     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3850     return angle::Result::Stop;
3851 }
3852 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)3853 angle::Result TextureStorage11_2DMultisample::getSwizzleRenderTarget(
3854     const gl::Context *context,
3855     int mipLevel,
3856     const d3d11::RenderTargetView **outRTV)
3857 {
3858     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3859     return angle::Result::Stop;
3860 }
3861 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)3862 angle::Result TextureStorage11_2DMultisample::ensureDropStencilTexture(const gl::Context *context,
3863                                                                        DropStencil *dropStencilOut)
3864 {
3865     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3866     return angle::Result::Stop;
3867 }
3868 
onLabelUpdate()3869 void TextureStorage11_2DMultisample::onLabelUpdate()
3870 {
3871     if (mTexture.valid())
3872     {
3873         mTexture.setKHRDebugLabel(&mTextureLabel);
3874     }
3875 }
3876 
TextureStorage11_2DMultisampleArray(Renderer11 * renderer,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,int levels,int samples,bool fixedSampleLocations,const std::string & label)3877 TextureStorage11_2DMultisampleArray::TextureStorage11_2DMultisampleArray(Renderer11 *renderer,
3878                                                                          GLenum internalformat,
3879                                                                          GLsizei width,
3880                                                                          GLsizei height,
3881                                                                          GLsizei depth,
3882                                                                          int levels,
3883                                                                          int samples,
3884                                                                          bool fixedSampleLocations,
3885                                                                          const std::string &label)
3886     : TextureStorage11ImmutableBase(
3887           renderer,
3888           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true),
3889           GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels),
3890           internalformat,
3891           label),
3892       mTexture()
3893 {
3894     // There are no multisampled compressed formats, so there's no need to adjust texture size
3895     // according to block size.
3896     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockWidth <= 1);
3897     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockHeight <= 1);
3898 
3899     mMipLevels            = 1;
3900     mTextureWidth         = width;
3901     mTextureHeight        = height;
3902     mTextureDepth         = depth;
3903     mSamples              = samples;
3904     mFixedSampleLocations = fixedSampleLocations;
3905 }
3906 
onDestroy(const gl::Context * context)3907 angle::Result TextureStorage11_2DMultisampleArray::onDestroy(const gl::Context *context)
3908 {
3909     return angle::Result::Continue;
3910 }
3911 
~TextureStorage11_2DMultisampleArray()3912 TextureStorage11_2DMultisampleArray::~TextureStorage11_2DMultisampleArray() {}
3913 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)3914 angle::Result TextureStorage11_2DMultisampleArray::copyToStorage(const gl::Context *context,
3915                                                                  TextureStorage *destStorage)
3916 {
3917     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3918     return angle::Result::Stop;
3919 }
3920 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3921 angle::Result TextureStorage11_2DMultisampleArray::getResource(const gl::Context *context,
3922                                                                const TextureHelper11 **outResource)
3923 {
3924     ANGLE_TRY(ensureTextureExists(context, 1));
3925 
3926     *outResource = &mTexture;
3927     return angle::Result::Continue;
3928 }
3929 
ensureTextureExists(const gl::Context * context,int mipLevels)3930 angle::Result TextureStorage11_2DMultisampleArray::ensureTextureExists(const gl::Context *context,
3931                                                                        int mipLevels)
3932 {
3933     // For multisampled textures, mipLevels always equals 1.
3934     ASSERT(mipLevels == 1);
3935 
3936     // if the width or height is not positive this should be treated as an incomplete texture
3937     // we handle that here by skipping the d3d texture creation
3938     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
3939     {
3940         D3D11_TEXTURE2D_DESC desc;
3941         ZeroMemory(&desc, sizeof(desc));
3942         desc.Width          = mTextureWidth;
3943         desc.Height         = mTextureHeight;
3944         desc.MipLevels      = mipLevels;
3945         desc.ArraySize      = mTextureDepth;
3946         desc.Format         = mFormatInfo.texFormat;
3947         desc.Usage          = D3D11_USAGE_DEFAULT;
3948         desc.BindFlags      = getBindFlags() & ~D3D11_BIND_UNORDERED_ACCESS;
3949         desc.CPUAccessFlags = 0;
3950         desc.MiscFlags      = getMiscFlags();
3951 
3952         const gl::TextureCaps &textureCaps =
3953             mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
3954         GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
3955         desc.SampleDesc.Count   = (supportedSamples == 0) ? 1 : supportedSamples;
3956         desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples);
3957 
3958         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
3959                                              &mTexture));
3960         mTexture.setLabels("TexStorage2DMSArray.Texture", &mTextureLabel);
3961     }
3962 
3963     return angle::Result::Continue;
3964 }
3965 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3966 angle::Result TextureStorage11_2DMultisampleArray::findRenderTarget(const gl::Context *context,
3967                                                                     const gl::ImageIndex &index,
3968                                                                     GLsizei samples,
3969                                                                     RenderTargetD3D **outRT) const
3970 {
3971     ASSERT(index.hasLayer());
3972 
3973     const int mipLevel = index.getLevelIndex();
3974     ASSERT(mipLevel == 0);
3975     const int layer     = index.getLayerIndex();
3976     const int numLayers = index.getLayerCount();
3977 
3978     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3979 
3980     TextureStorage11_2DArray::LevelLayerRangeKey key(mipLevel, layer, numLayers);
3981     if (mRenderTargets.find(key) == mRenderTargets.end())
3982     {
3983         ASSERT(outRT);
3984         *outRT = nullptr;
3985         return angle::Result::Continue;
3986     }
3987 
3988     ASSERT(outRT);
3989     *outRT = mRenderTargets.at(key).get();
3990     return angle::Result::Continue;
3991 }
3992 
createRenderTargetSRV(const gl::Context * context,const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const3993 angle::Result TextureStorage11_2DMultisampleArray::createRenderTargetSRV(
3994     const gl::Context *context,
3995     const TextureHelper11 &texture,
3996     const gl::ImageIndex &index,
3997     DXGI_FORMAT resourceFormat,
3998     d3d11::SharedSRV *srv) const
3999 {
4000     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
4001     srvDesc.Format                           = resourceFormat;
4002     srvDesc.ViewDimension                    = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
4003     srvDesc.Texture2DMSArray.FirstArraySlice = index.getLayerIndex();
4004     srvDesc.Texture2DMSArray.ArraySize       = index.getLayerCount();
4005 
4006     ANGLE_TRY(
4007         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
4008 
4009     return angle::Result::Continue;
4010 }
4011 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)4012 angle::Result TextureStorage11_2DMultisampleArray::getRenderTarget(const gl::Context *context,
4013                                                                    const gl::ImageIndex &index,
4014                                                                    GLsizei samples,
4015                                                                    RenderTargetD3D **outRT)
4016 {
4017     ASSERT(index.hasLayer());
4018 
4019     const int mipLevel = index.getLevelIndex();
4020     ASSERT(mipLevel == 0);
4021     const int layer     = index.getLayerIndex();
4022     const int numLayers = index.getLayerCount();
4023 
4024     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
4025 
4026     TextureStorage11_2DArray::LevelLayerRangeKey key(mipLevel, layer, numLayers);
4027     if (mRenderTargets.find(key) == mRenderTargets.end())
4028     {
4029         const TextureHelper11 *texture = nullptr;
4030         ANGLE_TRY(getResource(context, &texture));
4031         d3d11::SharedSRV srv;
4032         ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
4033         d3d11::SharedSRV blitSRV;
4034         if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
4035         {
4036             ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
4037                                             &blitSRV));
4038         }
4039         else
4040         {
4041             blitSRV = srv.makeCopy();
4042         }
4043 
4044         srv.setLabels("TexStorage2DMSArray.RenderTargetSRV", &mTextureLabel);
4045 
4046         if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
4047         {
4048             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
4049             rtvDesc.Format                           = mFormatInfo.rtvFormat;
4050             rtvDesc.ViewDimension                    = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4051             rtvDesc.Texture2DMSArray.FirstArraySlice = layer;
4052             rtvDesc.Texture2DMSArray.ArraySize       = numLayers;
4053 
4054             d3d11::RenderTargetView rtv;
4055             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
4056                                                   texture->get(), &rtv));
4057             rtv.setLabels("TexStorage2DMSArray.RenderTargetRTV", &mTextureLabel);
4058 
4059             mRenderTargets[key].reset(new TextureRenderTarget11(
4060                 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
4061                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, mSamples));
4062         }
4063         else
4064         {
4065             ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
4066 
4067             D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
4068             dsvDesc.Format                           = mFormatInfo.dsvFormat;
4069             dsvDesc.ViewDimension                    = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4070             dsvDesc.Texture2DMSArray.FirstArraySlice = layer;
4071             dsvDesc.Texture2DMSArray.ArraySize       = numLayers;
4072             dsvDesc.Flags                            = 0;
4073 
4074             d3d11::DepthStencilView dsv;
4075             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), dsvDesc,
4076                                                   texture->get(), &dsv));
4077             dsv.setLabels("TexStorage2DMSArray.RenderTargetDSV", &mTextureLabel);
4078 
4079             mRenderTargets[key].reset(new TextureRenderTarget11(
4080                 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
4081                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, mSamples));
4082         }
4083     }
4084 
4085     ASSERT(outRT);
4086     *outRT = mRenderTargets[key].get();
4087     return angle::Result::Continue;
4088 }
4089 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)4090 angle::Result TextureStorage11_2DMultisampleArray::createSRVForSampler(
4091     const gl::Context *context,
4092     int baseLevel,
4093     int mipLevels,
4094     DXGI_FORMAT format,
4095     const TextureHelper11 &texture,
4096     d3d11::SharedSRV *outSRV)
4097 {
4098     ASSERT(outSRV);
4099 
4100     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
4101     srvDesc.Format                           = format;
4102     srvDesc.ViewDimension                    = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
4103     srvDesc.Texture2DMSArray.FirstArraySlice = 0;
4104     srvDesc.Texture2DMSArray.ArraySize       = mTextureDepth;
4105 
4106     ANGLE_TRY(
4107         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
4108     outSRV->setLabels("TexStorage2DMSArray.SRV", &mTextureLabel);
4109     return angle::Result::Continue;
4110 }
4111 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)4112 angle::Result TextureStorage11_2DMultisampleArray::getSwizzleTexture(
4113     const gl::Context *context,
4114     const TextureHelper11 **outTexture)
4115 {
4116     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
4117     return angle::Result::Stop;
4118 }
4119 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)4120 angle::Result TextureStorage11_2DMultisampleArray::getSwizzleRenderTarget(
4121     const gl::Context *context,
4122     int mipLevel,
4123     const d3d11::RenderTargetView **outRTV)
4124 {
4125     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
4126     return angle::Result::Stop;
4127 }
4128 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)4129 angle::Result TextureStorage11_2DMultisampleArray::ensureDropStencilTexture(
4130     const gl::Context *context,
4131     DropStencil *dropStencilOut)
4132 {
4133     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
4134     return angle::Result::Stop;
4135 }
4136 
onLabelUpdate()4137 void TextureStorage11_2DMultisampleArray::onLabelUpdate()
4138 {
4139     if (mTexture.valid())
4140     {
4141         mTexture.setKHRDebugLabel(&mTextureLabel);
4142     }
4143 }
4144 
4145 }  // namespace rx
4146