• 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       mAssociatedImage(nullptr)
1639 {
1640     ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11Texture);
1641     auto *producer = static_cast<StreamProducerD3DTexture *>(stream->getImplementation());
1642     mTexture.set(producer->getD3DTexture(), mFormatInfo);
1643     mSubresourceIndex = producer->getArraySlice();
1644     mTexture.get()->AddRef();
1645     mMipLevels = 1;
1646 
1647     D3D11_TEXTURE2D_DESC desc;
1648     mTexture.getDesc(&desc);
1649     mTextureWidth  = desc.Width;
1650     mTextureHeight = desc.Height;
1651     mTextureDepth  = 1;
1652     mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
1653 }
1654 
onDestroy(const gl::Context * context)1655 angle::Result TextureStorage11_External::onDestroy(const gl::Context *context)
1656 {
1657     if (mHasKeyedMutex)
1658     {
1659         // If the keyed mutex is released that will unbind it and cause the state cache to become
1660         // desynchronized.
1661         mRenderer->getStateManager()->invalidateBoundViews();
1662     }
1663 
1664     if (mAssociatedImage != nullptr)
1665     {
1666         mAssociatedImage->verifyAssociatedStorageValid(this);
1667 
1668         // We must let the Images recover their data before we delete it from the
1669         // TextureStorage.
1670         ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
1671     }
1672 
1673     return angle::Result::Continue;
1674 }
1675 
~TextureStorage11_External()1676 TextureStorage11_External::~TextureStorage11_External() {}
1677 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1678 angle::Result TextureStorage11_External::copyToStorage(const gl::Context *context,
1679                                                        TextureStorage *destStorage)
1680 {
1681     UNIMPLEMENTED();
1682     return angle::Result::Continue;
1683 }
1684 
associateImage(Image11 * image,const gl::ImageIndex & index)1685 void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index)
1686 {
1687     ASSERT(index.getLevelIndex() == 0);
1688     mAssociatedImage = image;
1689 }
1690 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)1691 void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index,
1692                                                            Image11 *expectedImage)
1693 {
1694     ASSERT(index.getLevelIndex() == 0 && mAssociatedImage == expectedImage);
1695 }
1696 
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)1697 void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index,
1698                                                   Image11 *expectedImage)
1699 {
1700     ASSERT(index.getLevelIndex() == 0);
1701     ASSERT(mAssociatedImage == expectedImage);
1702     mAssociatedImage = nullptr;
1703 }
1704 
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)1705 angle::Result TextureStorage11_External::releaseAssociatedImage(const gl::Context *context,
1706                                                                 const gl::ImageIndex &index,
1707                                                                 Image11 *incomingImage)
1708 {
1709     ASSERT(index.getLevelIndex() == 0);
1710 
1711     if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
1712     {
1713         mAssociatedImage->verifyAssociatedStorageValid(this);
1714 
1715         ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
1716     }
1717 
1718     return angle::Result::Continue;
1719 }
1720 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1721 angle::Result TextureStorage11_External::getResource(const gl::Context *context,
1722                                                      const TextureHelper11 **outResource)
1723 {
1724     *outResource = &mTexture;
1725     return angle::Result::Continue;
1726 }
1727 
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)1728 angle::Result TextureStorage11_External::getMippedResource(const gl::Context *context,
1729                                                            const TextureHelper11 **outResource)
1730 {
1731     *outResource = &mTexture;
1732     return angle::Result::Continue;
1733 }
1734 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const1735 angle::Result TextureStorage11_External::findRenderTarget(const gl::Context *context,
1736                                                           const gl::ImageIndex &index,
1737                                                           GLsizei samples,
1738                                                           RenderTargetD3D **outRT) const
1739 {
1740     // Render targets are not supported for external textures
1741     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1742     return angle::Result::Stop;
1743 }
1744 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)1745 angle::Result TextureStorage11_External::getRenderTarget(const gl::Context *context,
1746                                                          const gl::ImageIndex &index,
1747                                                          GLsizei samples,
1748                                                          RenderTargetD3D **outRT)
1749 {
1750     // Render targets are not supported for external textures
1751     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1752     return angle::Result::Stop;
1753 }
1754 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1755 angle::Result TextureStorage11_External::createSRVForSampler(const gl::Context *context,
1756                                                              int baseLevel,
1757                                                              int mipLevels,
1758                                                              DXGI_FORMAT format,
1759                                                              const TextureHelper11 &texture,
1760                                                              d3d11::SharedSRV *outSRV)
1761 {
1762     // Since external textures are treates as non-mipmapped textures, we ignore mipmap levels and
1763     // use the specified subresource ID the storage was created with.
1764     ASSERT(mipLevels == 1);
1765     ASSERT(outSRV);
1766 
1767     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1768     srvDesc.Format        = format;
1769     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1770     // subresource index is equal to the mip level for 2D textures
1771     srvDesc.Texture2DArray.MostDetailedMip = 0;
1772     srvDesc.Texture2DArray.MipLevels       = 1;
1773     srvDesc.Texture2DArray.FirstArraySlice = mSubresourceIndex;
1774     srvDesc.Texture2DArray.ArraySize       = 1;
1775 
1776     ANGLE_TRY(
1777         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
1778     outSRV->setLabels("TexStorage2D.SRV", &mTextureLabel);
1779 
1780     return angle::Result::Continue;
1781 }
1782 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1783 angle::Result TextureStorage11_External::createSRVForImage(const gl::Context *context,
1784                                                            int level,
1785                                                            DXGI_FORMAT format,
1786                                                            const TextureHelper11 &texture,
1787                                                            d3d11::SharedSRV *outSRV)
1788 {
1789     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1790     return angle::Result::Stop;
1791 }
1792 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)1793 angle::Result TextureStorage11_External::createUAVForImage(const gl::Context *context,
1794                                                            int level,
1795                                                            DXGI_FORMAT format,
1796                                                            const TextureHelper11 &texture,
1797                                                            d3d11::SharedUAV *outUAV)
1798 {
1799     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1800     return angle::Result::Stop;
1801 }
1802 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)1803 angle::Result TextureStorage11_External::getSwizzleTexture(const gl::Context *context,
1804                                                            const TextureHelper11 **outTexture)
1805 {
1806     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1807     return angle::Result::Stop;
1808 }
1809 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)1810 angle::Result TextureStorage11_External::getSwizzleRenderTarget(
1811     const gl::Context *context,
1812     int mipLevel,
1813     const d3d11::RenderTargetView **outRTV)
1814 {
1815     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1816     return angle::Result::Stop;
1817 }
1818 
onLabelUpdate()1819 void TextureStorage11_External::onLabelUpdate()
1820 {
1821     if (mTexture.valid())
1822     {
1823         mTexture.setKHRDebugLabel(&mTextureLabel);
1824     }
1825 }
1826 
TextureStorage11ImmutableBase(Renderer11 * renderer,UINT bindFlags,UINT miscFlags,GLenum internalFormat,const std::string & label)1827 TextureStorage11ImmutableBase::TextureStorage11ImmutableBase(Renderer11 *renderer,
1828                                                              UINT bindFlags,
1829                                                              UINT miscFlags,
1830                                                              GLenum internalFormat,
1831                                                              const std::string &label)
1832     : TextureStorage11(renderer, bindFlags, miscFlags, internalFormat, label)
1833 {}
1834 
associateImage(Image11 *,const gl::ImageIndex &)1835 void TextureStorage11ImmutableBase::associateImage(Image11 *, const gl::ImageIndex &) {}
1836 
disassociateImage(const gl::ImageIndex &,Image11 *)1837 void TextureStorage11ImmutableBase::disassociateImage(const gl::ImageIndex &, Image11 *) {}
1838 
verifyAssociatedImageValid(const gl::ImageIndex &,Image11 *)1839 void TextureStorage11ImmutableBase::verifyAssociatedImageValid(const gl::ImageIndex &, Image11 *) {}
1840 
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex &,Image11 *)1841 angle::Result TextureStorage11ImmutableBase::releaseAssociatedImage(const gl::Context *context,
1842                                                                     const gl::ImageIndex &,
1843                                                                     Image11 *)
1844 {
1845     return angle::Result::Continue;
1846 }
1847 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)1848 angle::Result TextureStorage11ImmutableBase::createSRVForImage(const gl::Context *context,
1849                                                                int level,
1850                                                                DXGI_FORMAT format,
1851                                                                const TextureHelper11 &texture,
1852                                                                d3d11::SharedSRV *outSRV)
1853 {
1854     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1855     return angle::Result::Stop;
1856 }
1857 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)1858 angle::Result TextureStorage11ImmutableBase::createUAVForImage(const gl::Context *context,
1859                                                                int level,
1860                                                                DXGI_FORMAT format,
1861                                                                const TextureHelper11 &texture,
1862                                                                d3d11::SharedUAV *outUAV)
1863 {
1864     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1865     return angle::Result::Stop;
1866 }
1867 
TextureStorage11_EGLImage(Renderer11 * renderer,EGLImageD3D * eglImage,RenderTarget11 * renderTarget11,const std::string & label)1868 TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
1869                                                      EGLImageD3D *eglImage,
1870                                                      RenderTarget11 *renderTarget11,
1871                                                      const std::string &label)
1872     : TextureStorage11ImmutableBase(renderer,
1873                                     D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
1874                                     0,
1875                                     renderTarget11->getInternalFormat(),
1876                                     label),
1877       mImage(eglImage),
1878       mCurrentRenderTarget(0),
1879       mSwizzleTexture(),
1880       mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS),
1881       mAssociatedImage(nullptr)
1882 {
1883     mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
1884 
1885     mMipLevels     = 1;
1886     mTextureWidth  = renderTarget11->getWidth();
1887     mTextureHeight = renderTarget11->getHeight();
1888     mTextureDepth  = 1;
1889 }
1890 
~TextureStorage11_EGLImage()1891 TextureStorage11_EGLImage::~TextureStorage11_EGLImage() {}
1892 
onDestroy(const gl::Context * context)1893 angle::Result TextureStorage11_EGLImage::onDestroy(const gl::Context *context)
1894 {
1895     if (mAssociatedImage != nullptr)
1896     {
1897         mAssociatedImage->verifyAssociatedStorageValid(this);
1898 
1899         // We must let the Images recover their data before we delete it from the
1900         // TextureStorage.
1901         ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
1902     }
1903 
1904     return angle::Result::Continue;
1905 }
1906 
getSubresourceIndex(const gl::Context * context,const gl::ImageIndex & index,UINT * outSubresourceIndex) const1907 angle::Result TextureStorage11_EGLImage::getSubresourceIndex(const gl::Context *context,
1908                                                              const gl::ImageIndex &index,
1909                                                              UINT *outSubresourceIndex) const
1910 {
1911     ASSERT(index.getType() == gl::TextureType::_2D);
1912     ASSERT(index.getLevelIndex() == 0);
1913 
1914     RenderTarget11 *renderTarget11 = nullptr;
1915     ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
1916     *outSubresourceIndex = renderTarget11->getSubresourceIndex();
1917     return angle::Result::Continue;
1918 }
1919 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)1920 angle::Result TextureStorage11_EGLImage::getResource(const gl::Context *context,
1921                                                      const TextureHelper11 **outResource)
1922 {
1923     ANGLE_TRY(checkForUpdatedRenderTarget(context));
1924 
1925     RenderTarget11 *renderTarget11 = nullptr;
1926     ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
1927     *outResource = &renderTarget11->getTexture();
1928     return angle::Result::Continue;
1929 }
1930 
getSRVForSampler(const gl::Context * context,const gl::TextureState & textureState,const gl::SamplerState & sampler,const d3d11::SharedSRV ** outSRV)1931 angle::Result TextureStorage11_EGLImage::getSRVForSampler(const gl::Context *context,
1932                                                           const gl::TextureState &textureState,
1933                                                           const gl::SamplerState &sampler,
1934                                                           const d3d11::SharedSRV **outSRV)
1935 {
1936     ANGLE_TRY(checkForUpdatedRenderTarget(context));
1937     return TextureStorage11::getSRVForSampler(context, textureState, sampler, outSRV);
1938 }
1939 
getMippedResource(const gl::Context * context,const TextureHelper11 **)1940 angle::Result TextureStorage11_EGLImage::getMippedResource(const gl::Context *context,
1941                                                            const TextureHelper11 **)
1942 {
1943     // This shouldn't be called unless the zero max LOD workaround is active.
1944     // EGL images are unavailable in this configuration.
1945     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1946     return angle::Result::Stop;
1947 }
1948 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const1949 angle::Result TextureStorage11_EGLImage::findRenderTarget(const gl::Context *context,
1950                                                           const gl::ImageIndex &index,
1951                                                           GLsizei samples,
1952                                                           RenderTargetD3D **outRT) const
1953 {
1954     // Since the render target of an EGL image will be updated when orphaning, trying to find a
1955     // cache of it can be rarely useful.
1956     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1957     return angle::Result::Stop;
1958 }
1959 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)1960 angle::Result TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context,
1961                                                          const gl::ImageIndex &index,
1962                                                          GLsizei samples,
1963                                                          RenderTargetD3D **outRT)
1964 {
1965     ASSERT(!index.hasLayer());
1966     ASSERT(index.getLevelIndex() == 0);
1967 
1968     ANGLE_TRY(checkForUpdatedRenderTarget(context));
1969 
1970     return mImage->getRenderTarget(context, outRT);
1971 }
1972 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)1973 angle::Result TextureStorage11_EGLImage::copyToStorage(const gl::Context *context,
1974                                                        TextureStorage *destStorage)
1975 {
1976     const TextureHelper11 *sourceResouce = nullptr;
1977     ANGLE_TRY(getResource(context, &sourceResouce));
1978 
1979     ASSERT(destStorage);
1980     TextureStorage11_2D *dest11         = GetAs<TextureStorage11_2D>(destStorage);
1981     const TextureHelper11 *destResource = nullptr;
1982     ANGLE_TRY(dest11->getResource(context, &destResource));
1983 
1984     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
1985     immediateContext->CopyResource(destResource->get(), sourceResouce->get());
1986 
1987     dest11->markDirty();
1988 
1989     return angle::Result::Continue;
1990 }
1991 
useLevelZeroWorkaroundTexture(const gl::Context * context,bool)1992 angle::Result TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(const gl::Context *context,
1993                                                                        bool)
1994 {
1995     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1996     return angle::Result::Stop;
1997 }
1998 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)1999 angle::Result TextureStorage11_EGLImage::getSwizzleTexture(const gl::Context *context,
2000                                                            const TextureHelper11 **outTexture)
2001 {
2002     ASSERT(outTexture);
2003 
2004     if (!mSwizzleTexture.valid())
2005     {
2006         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
2007 
2008         D3D11_TEXTURE2D_DESC desc;
2009         desc.Width              = mTextureWidth;
2010         desc.Height             = mTextureHeight;
2011         desc.MipLevels          = mMipLevels;
2012         desc.ArraySize          = 1;
2013         desc.Format             = format.texFormat;
2014         desc.SampleDesc.Count   = 1;
2015         desc.SampleDesc.Quality = 0;
2016         desc.Usage              = D3D11_USAGE_DEFAULT;
2017         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
2018         desc.CPUAccessFlags     = 0;
2019         desc.MiscFlags          = 0;
2020 
2021         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
2022                                              &mSwizzleTexture));
2023         mSwizzleTexture.setLabels("TexStorageEGLImage.SwizzleTexture", &mTextureLabel);
2024     }
2025 
2026     *outTexture = &mSwizzleTexture;
2027     return angle::Result::Continue;
2028 }
2029 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)2030 angle::Result TextureStorage11_EGLImage::getSwizzleRenderTarget(
2031     const gl::Context *context,
2032     int mipLevel,
2033     const d3d11::RenderTargetView **outRTV)
2034 {
2035     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2036     ASSERT(outRTV);
2037 
2038     if (!mSwizzleRenderTargets[mipLevel].valid())
2039     {
2040         const TextureHelper11 *swizzleTexture = nullptr;
2041         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
2042 
2043         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2044         rtvDesc.Format =
2045             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
2046         rtvDesc.ViewDimension      = D3D11_RTV_DIMENSION_TEXTURE2D;
2047         rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
2048 
2049         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
2050                                               mSwizzleTexture.get(),
2051                                               &mSwizzleRenderTargets[mipLevel]));
2052     }
2053 
2054     *outRTV = &mSwizzleRenderTargets[mipLevel];
2055     return angle::Result::Continue;
2056 }
2057 
checkForUpdatedRenderTarget(const gl::Context * context)2058 angle::Result TextureStorage11_EGLImage::checkForUpdatedRenderTarget(const gl::Context *context)
2059 {
2060     RenderTarget11 *renderTarget11 = nullptr;
2061     ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
2062 
2063     if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11))
2064     {
2065         clearSRVCache();
2066         mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
2067     }
2068 
2069     return angle::Result::Continue;
2070 }
2071 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2072 angle::Result TextureStorage11_EGLImage::createSRVForSampler(const gl::Context *context,
2073                                                              int baseLevel,
2074                                                              int mipLevels,
2075                                                              DXGI_FORMAT format,
2076                                                              const TextureHelper11 &texture,
2077                                                              d3d11::SharedSRV *outSRV)
2078 {
2079     ASSERT(baseLevel == 0);
2080     ASSERT(mipLevels == 1);
2081     ASSERT(outSRV);
2082 
2083     // Create a new SRV only for the swizzle texture.  Otherwise just return the Image's
2084     // RenderTarget's SRV.
2085     if (texture == mSwizzleTexture)
2086     {
2087         D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2088         srvDesc.Format                    = format;
2089         srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE2D;
2090         srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
2091         srvDesc.Texture2D.MipLevels       = mipLevels;
2092 
2093         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(),
2094                                               outSRV));
2095         outSRV->setLabels("TexStorageEGLImage.SRV", &mTextureLabel);
2096     }
2097     else
2098     {
2099         RenderTarget11 *renderTarget = nullptr;
2100         ANGLE_TRY(getImageRenderTarget(context, &renderTarget));
2101 
2102         ASSERT(texture == renderTarget->getTexture());
2103 
2104         *outSRV = renderTarget->getShaderResourceView(context).makeCopy();
2105     }
2106 
2107     return angle::Result::Continue;
2108 }
2109 
getImageRenderTarget(const gl::Context * context,RenderTarget11 ** outRT) const2110 angle::Result TextureStorage11_EGLImage::getImageRenderTarget(const gl::Context *context,
2111                                                               RenderTarget11 **outRT) const
2112 {
2113     RenderTargetD3D *renderTargetD3D = nullptr;
2114     ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
2115     *outRT = GetAs<RenderTarget11>(renderTargetD3D);
2116     return angle::Result::Continue;
2117 }
2118 
onLabelUpdate()2119 void TextureStorage11_EGLImage::onLabelUpdate()
2120 {
2121     if (mSwizzleTexture.valid())
2122     {
2123         mSwizzleTexture.setKHRDebugLabel(&mTextureLabel);
2124     }
2125 }
2126 
associateImage(Image11 * image,const gl::ImageIndex & index)2127 void TextureStorage11_EGLImage::associateImage(Image11 *image, const gl::ImageIndex &index)
2128 {
2129     ASSERT(index.getLevelIndex() == 0);
2130     mAssociatedImage = image;
2131 }
2132 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2133 void TextureStorage11_EGLImage::verifyAssociatedImageValid(const gl::ImageIndex &index,
2134                                                            Image11 *expectedImage)
2135 {
2136     ASSERT(index.getLevelIndex() == 0 && mAssociatedImage == expectedImage);
2137 }
2138 
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)2139 void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &index,
2140                                                   Image11 *expectedImage)
2141 {
2142     ASSERT(index.getLevelIndex() == 0);
2143     ASSERT(mAssociatedImage == expectedImage);
2144     mAssociatedImage = nullptr;
2145 }
2146 
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)2147 angle::Result TextureStorage11_EGLImage::releaseAssociatedImage(const gl::Context *context,
2148                                                                 const gl::ImageIndex &index,
2149                                                                 Image11 *incomingImage)
2150 {
2151     ASSERT(index.getLevelIndex() == 0);
2152 
2153     if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
2154     {
2155         mAssociatedImage->verifyAssociatedStorageValid(this);
2156 
2157         ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
2158     }
2159 
2160     return angle::Result::Continue;
2161 }
2162 
TextureStorage11_Cube(Renderer11 * renderer,GLenum internalformat,bool renderTarget,int size,int levels,bool hintLevelZeroOnly,const std::string & label)2163 TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer,
2164                                              GLenum internalformat,
2165                                              bool renderTarget,
2166                                              int size,
2167                                              int levels,
2168                                              bool hintLevelZeroOnly,
2169                                              const std::string &label)
2170     : TextureStorage11(
2171           renderer,
2172           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
2173           GetTextureMiscFlags(internalformat,
2174                               renderer->getRenderer11DeviceCaps(),
2175                               renderTarget,
2176                               levels),
2177           internalformat,
2178           label),
2179       mTexture(),
2180       mLevelZeroTexture(),
2181       mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
2182       mSwizzleTexture()
2183 {
2184     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
2185     {
2186         for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
2187         {
2188             mAssociatedImages[face][level] = nullptr;
2189             mRenderTarget[face][level]     = nullptr;
2190         }
2191     }
2192 
2193     for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
2194     {
2195         mLevelZeroRenderTarget[face] = nullptr;
2196     }
2197 
2198     // adjust size if needed for compressed textures
2199     int height = size;
2200     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel);
2201 
2202     mMipLevels     = mTopLevel + levels;
2203     mTextureWidth  = size;
2204     mTextureHeight = size;
2205     mTextureDepth  = 1;
2206 
2207     // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
2208     ASSERT(!mUseLevelZeroTexture || mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
2209 }
2210 
onDestroy(const gl::Context * context)2211 angle::Result TextureStorage11_Cube::onDestroy(const gl::Context *context)
2212 {
2213     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
2214     {
2215         for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
2216         {
2217             if (mAssociatedImages[face][level] != nullptr)
2218             {
2219                 mAssociatedImages[face][level]->verifyAssociatedStorageValid(this);
2220 
2221                 // We must let the Images recover their data before we delete it from the
2222                 // TextureStorage.
2223                 ANGLE_TRY(mAssociatedImages[face][level]->recoverFromAssociatedStorage(context));
2224             }
2225         }
2226     }
2227 
2228     return angle::Result::Continue;
2229 }
2230 
~TextureStorage11_Cube()2231 TextureStorage11_Cube::~TextureStorage11_Cube() {}
2232 
getSubresourceIndex(const gl::Context * context,const gl::ImageIndex & index,UINT * outSubresourceIndex) const2233 angle::Result TextureStorage11_Cube::getSubresourceIndex(const gl::Context *context,
2234                                                          const gl::ImageIndex &index,
2235                                                          UINT *outSubresourceIndex) const
2236 {
2237     UINT arraySlice = index.cubeMapFaceIndex();
2238     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled && mUseLevelZeroTexture &&
2239         index.getLevelIndex() == 0)
2240     {
2241         UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
2242         ASSERT(subresource != std::numeric_limits<UINT>::max());
2243         *outSubresourceIndex = subresource;
2244     }
2245     else
2246     {
2247         UINT mipSlice    = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
2248         UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
2249         ASSERT(subresource != std::numeric_limits<UINT>::max());
2250         *outSubresourceIndex = subresource;
2251     }
2252     return angle::Result::Continue;
2253 }
2254 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)2255 angle::Result TextureStorage11_Cube::copyToStorage(const gl::Context *context,
2256                                                    TextureStorage *destStorage)
2257 {
2258     ASSERT(destStorage);
2259 
2260     TextureStorage11_Cube *dest11 = GetAs<TextureStorage11_Cube>(destStorage);
2261 
2262     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
2263     {
2264         ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
2265 
2266         // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
2267         // corresponding textures in destStorage.
2268         if (mTexture.valid())
2269         {
2270             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
2271 
2272             const TextureHelper11 *destResource = nullptr;
2273             ANGLE_TRY(dest11->getResource(context, &destResource));
2274 
2275             immediateContext->CopyResource(destResource->get(), mTexture.get());
2276         }
2277 
2278         if (mLevelZeroTexture.valid())
2279         {
2280             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
2281 
2282             const TextureHelper11 *destResource = nullptr;
2283             ANGLE_TRY(dest11->getResource(context, &destResource));
2284 
2285             immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
2286         }
2287     }
2288     else
2289     {
2290         const TextureHelper11 *sourceResouce = nullptr;
2291         ANGLE_TRY(getResource(context, &sourceResouce));
2292 
2293         const TextureHelper11 *destResource = nullptr;
2294         ANGLE_TRY(dest11->getResource(context, &destResource));
2295 
2296         ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
2297         immediateContext->CopyResource(destResource->get(), sourceResouce->get());
2298     }
2299 
2300     dest11->markDirty();
2301 
2302     return angle::Result::Continue;
2303 }
2304 
useLevelZeroWorkaroundTexture(const gl::Context * context,bool useLevelZeroTexture)2305 angle::Result TextureStorage11_Cube::useLevelZeroWorkaroundTexture(const gl::Context *context,
2306                                                                    bool useLevelZeroTexture)
2307 {
2308     if (useLevelZeroTexture && mMipLevels > 1)
2309     {
2310         if (!mUseLevelZeroTexture && mTexture.valid())
2311         {
2312             ANGLE_TRY(ensureTextureExists(context, 1));
2313 
2314             // Pull data back from the mipped texture if necessary.
2315             ASSERT(mLevelZeroTexture.valid());
2316             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2317 
2318             for (int face = 0; face < 6; face++)
2319             {
2320                 deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(),
2321                                                      D3D11CalcSubresource(0, face, 1), 0, 0, 0,
2322                                                      mTexture.get(), face * mMipLevels, nullptr);
2323             }
2324         }
2325 
2326         mUseLevelZeroTexture = true;
2327     }
2328     else
2329     {
2330         if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
2331         {
2332             ANGLE_TRY(ensureTextureExists(context, mMipLevels));
2333 
2334             // Pull data back from the level zero texture if necessary.
2335             ASSERT(mTexture.valid());
2336             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
2337 
2338             for (int face = 0; face < 6; face++)
2339             {
2340                 deviceContext->CopySubresourceRegion(mTexture.get(),
2341                                                      D3D11CalcSubresource(0, face, mMipLevels), 0,
2342                                                      0, 0, mLevelZeroTexture.get(), face, nullptr);
2343             }
2344         }
2345 
2346         mUseLevelZeroTexture = false;
2347     }
2348 
2349     return angle::Result::Continue;
2350 }
2351 
associateImage(Image11 * image,const gl::ImageIndex & index)2352 void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index)
2353 {
2354     const GLint level       = index.getLevelIndex();
2355     const GLint layerTarget = index.cubeMapFaceIndex();
2356 
2357     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2358     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2359 
2360     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2361     {
2362         if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount))
2363         {
2364             mAssociatedImages[layerTarget][level] = image;
2365         }
2366     }
2367 }
2368 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2369 void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index,
2370                                                        Image11 *expectedImage)
2371 {
2372     const GLint level       = index.getLevelIndex();
2373     const GLint layerTarget = index.cubeMapFaceIndex();
2374 
2375     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2376     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2377     // This validation check should never return false. It means the Image/TextureStorage
2378     // association is broken.
2379     ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
2380 }
2381 
2382 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)2383 void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
2384 {
2385     const GLint level       = index.getLevelIndex();
2386     const GLint layerTarget = index.cubeMapFaceIndex();
2387 
2388     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2389     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2390     ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
2391     mAssociatedImages[layerTarget][level] = nullptr;
2392 }
2393 
2394 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
2395 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)2396 angle::Result TextureStorage11_Cube::releaseAssociatedImage(const gl::Context *context,
2397                                                             const gl::ImageIndex &index,
2398                                                             Image11 *incomingImage)
2399 {
2400     const GLint level       = index.getLevelIndex();
2401     const GLint layerTarget = index.cubeMapFaceIndex();
2402 
2403     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2404     ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
2405 
2406     if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2407     {
2408         if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount))
2409         {
2410             // No need to let the old Image recover its data, if it is also the incoming Image.
2411             if (mAssociatedImages[layerTarget][level] != nullptr &&
2412                 mAssociatedImages[layerTarget][level] != incomingImage)
2413             {
2414                 // Ensure that the Image is still associated with this TextureStorage.
2415                 mAssociatedImages[layerTarget][level]->verifyAssociatedStorageValid(this);
2416 
2417                 // Force the image to recover from storage before its data is overwritten.
2418                 // This will reset mAssociatedImages[level] to nullptr too.
2419                 ANGLE_TRY(
2420                     mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(context));
2421             }
2422         }
2423     }
2424 
2425     return angle::Result::Continue;
2426 }
2427 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)2428 angle::Result TextureStorage11_Cube::getResource(const gl::Context *context,
2429                                                  const TextureHelper11 **outResource)
2430 {
2431     if (mUseLevelZeroTexture && mMipLevels > 1)
2432     {
2433         ANGLE_TRY(ensureTextureExists(context, 1));
2434         *outResource = &mLevelZeroTexture;
2435     }
2436     else
2437     {
2438         ANGLE_TRY(ensureTextureExists(context, mMipLevels));
2439         *outResource = &mTexture;
2440     }
2441     return angle::Result::Continue;
2442 }
2443 
getMippedResource(const gl::Context * context,const TextureHelper11 ** outResource)2444 angle::Result TextureStorage11_Cube::getMippedResource(const gl::Context *context,
2445                                                        const TextureHelper11 **outResource)
2446 {
2447     // This shouldn't be called unless the zero max LOD workaround is active.
2448     ASSERT(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
2449 
2450     ANGLE_TRY(ensureTextureExists(context, mMipLevels));
2451     *outResource = &mTexture;
2452     return angle::Result::Continue;
2453 }
2454 
ensureTextureExists(const gl::Context * context,int mipLevels)2455 angle::Result TextureStorage11_Cube::ensureTextureExists(const gl::Context *context, int mipLevels)
2456 {
2457     // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
2458     ANGLE_TRY(resolveTexture(context));
2459     bool useLevelZeroTexture = mRenderer->getFeatures().zeroMaxLodWorkaround.enabled
2460                                    ? (mipLevels == 1) && (mMipLevels > 1)
2461                                    : false;
2462     TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
2463 
2464     // if the size is not positive this should be treated as an incomplete texture
2465     // we handle that here by skipping the d3d texture creation
2466     if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
2467     {
2468         ASSERT(mMipLevels > 0);
2469 
2470         D3D11_TEXTURE2D_DESC desc;
2471         desc.Width              = mTextureWidth;
2472         desc.Height             = mTextureHeight;
2473         desc.MipLevels          = mipLevels;
2474         desc.ArraySize          = gl::kCubeFaceCount;
2475         desc.Format             = mFormatInfo.texFormat;
2476         desc.SampleDesc.Count   = 1;
2477         desc.SampleDesc.Quality = 0;
2478         desc.Usage              = D3D11_USAGE_DEFAULT;
2479         desc.BindFlags          = getBindFlags();
2480         desc.CPUAccessFlags     = 0;
2481         desc.MiscFlags          = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags();
2482 
2483         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
2484                                              outputTexture));
2485         outputTexture->setLabels("TexStorageCube.Texture", &mTextureLabel);
2486     }
2487 
2488     return angle::Result::Continue;
2489 }
2490 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const2491 angle::Result TextureStorage11_Cube::findRenderTarget(const gl::Context *context,
2492                                                       const gl::ImageIndex &index,
2493                                                       GLsizei samples,
2494                                                       RenderTargetD3D **outRT) const
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 findMultisampledRenderTarget(context, index, samples, outRT);
2506     }
2507 
2508     if (!mRenderTarget[faceIndex][level])
2509     {
2510         if (mUseLevelZeroTexture)
2511         {
2512             ASSERT(index.getLevelIndex() == 0);
2513             ASSERT(outRT);
2514             *outRT = mLevelZeroRenderTarget[faceIndex].get();
2515             return angle::Result::Continue;
2516         }
2517     }
2518 
2519     ASSERT(outRT);
2520     *outRT = mRenderTarget[faceIndex][level].get();
2521     return angle::Result::Continue;
2522 }
2523 
createRenderTargetSRV(const gl::Context * context,const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const2524 angle::Result TextureStorage11_Cube::createRenderTargetSRV(const gl::Context *context,
2525                                                            const TextureHelper11 &texture,
2526                                                            const gl::ImageIndex &index,
2527                                                            DXGI_FORMAT resourceFormat,
2528                                                            d3d11::SharedSRV *srv) const
2529 {
2530     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2531     srvDesc.Format                         = resourceFormat;
2532     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
2533     srvDesc.Texture2DArray.MipLevels       = 1;
2534     srvDesc.Texture2DArray.FirstArraySlice = index.cubeMapFaceIndex();
2535     srvDesc.Texture2DArray.ArraySize       = 1;
2536 
2537     if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
2538     {
2539         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
2540     }
2541     else
2542     {
2543         // Will be used with Texture2D sampler, not TextureCube
2544         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2545     }
2546 
2547     ANGLE_TRY(
2548         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
2549     return angle::Result::Continue;
2550 }
2551 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)2552 angle::Result TextureStorage11_Cube::getRenderTarget(const gl::Context *context,
2553                                                      const gl::ImageIndex &index,
2554                                                      GLsizei samples,
2555                                                      RenderTargetD3D **outRT)
2556 {
2557     const int faceIndex = index.cubeMapFaceIndex();
2558     const int level     = index.getLevelIndex();
2559 
2560     ASSERT(level >= 0 && level < getLevelCount());
2561     ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::kCubeFaceCount));
2562 
2563     bool needMS = samples > 0;
2564     if (needMS)
2565     {
2566         return getMultisampledRenderTarget(context, index, samples, outRT);
2567     }
2568     else
2569     {
2570         ANGLE_TRY(resolveTexture(context));
2571     }
2572 
2573     Context11 *context11 = GetImplAs<Context11>(context);
2574 
2575     if (!mRenderTarget[faceIndex][level])
2576     {
2577         if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
2578         {
2579             ASSERT(index.getLevelIndex() == 0);
2580             ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
2581         }
2582 
2583         const TextureHelper11 *texture = nullptr;
2584         ANGLE_TRY(getResource(context, &texture));
2585 
2586         if (mUseLevelZeroTexture)
2587         {
2588             if (!mLevelZeroRenderTarget[faceIndex])
2589             {
2590                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2591                 rtvDesc.Format                         = mFormatInfo.rtvFormat;
2592                 rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2593                 rtvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2594                 rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2595                 rtvDesc.Texture2DArray.ArraySize       = 1;
2596 
2597                 d3d11::RenderTargetView rtv;
2598                 ANGLE_TRY(
2599                     mRenderer->allocateResource(context11, rtvDesc, mLevelZeroTexture.get(), &rtv));
2600 
2601                 mLevelZeroRenderTarget[faceIndex].reset(new TextureRenderTarget11(
2602                     std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
2603                     mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
2604                     getLevelHeight(level), 1, 0));
2605             }
2606 
2607             ASSERT(outRT);
2608             *outRT = mLevelZeroRenderTarget[faceIndex].get();
2609             return angle::Result::Continue;
2610         }
2611 
2612         d3d11::SharedSRV srv;
2613         ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
2614         d3d11::SharedSRV blitSRV;
2615         if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
2616         {
2617             ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
2618                                             &blitSRV));
2619         }
2620         else
2621         {
2622             blitSRV = srv.makeCopy();
2623         }
2624 
2625         srv.setLabels("TexStorageCube.RenderTargetSRV", &mTextureLabel);
2626 
2627         if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
2628         {
2629             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2630             rtvDesc.Format                         = mFormatInfo.rtvFormat;
2631             rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2632             rtvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2633             rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2634             rtvDesc.Texture2DArray.ArraySize       = 1;
2635 
2636             d3d11::RenderTargetView rtv;
2637             ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
2638             rtv.setLabels("TexStorageCube.RenderTargetRTV", &mTextureLabel);
2639 
2640             mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
2641                 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
2642                 getLevelWidth(level), getLevelHeight(level), 1, 0));
2643         }
2644         else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
2645         {
2646             D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
2647             dsvDesc.Format                         = mFormatInfo.dsvFormat;
2648             dsvDesc.ViewDimension                  = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
2649             dsvDesc.Flags                          = 0;
2650             dsvDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2651             dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
2652             dsvDesc.Texture2DArray.ArraySize       = 1;
2653 
2654             d3d11::DepthStencilView dsv;
2655             ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
2656             dsv.setLabels("TexStorageCube.RenderTargetDSV", &mTextureLabel);
2657 
2658             mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
2659                 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
2660                 getLevelWidth(level), getLevelHeight(level), 1, 0));
2661         }
2662         else
2663         {
2664             UNREACHABLE();
2665         }
2666     }
2667 
2668     ASSERT(outRT);
2669     *outRT = mRenderTarget[faceIndex][level].get();
2670     return angle::Result::Continue;
2671 }
2672 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2673 angle::Result TextureStorage11_Cube::createSRVForSampler(const gl::Context *context,
2674                                                          int baseLevel,
2675                                                          int mipLevels,
2676                                                          DXGI_FORMAT format,
2677                                                          const TextureHelper11 &texture,
2678                                                          d3d11::SharedSRV *outSRV)
2679 {
2680     ASSERT(outSRV);
2681 
2682     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2683     srvDesc.Format = format;
2684 
2685     // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six
2686     // 2D textures
2687     const GLenum componentType = d3d11::GetComponentType(format);
2688     if (componentType == GL_INT || componentType == GL_UNSIGNED_INT)
2689     {
2690         srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2691         srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
2692         srvDesc.Texture2DArray.MipLevels       = mipLevels;
2693         srvDesc.Texture2DArray.FirstArraySlice = 0;
2694         srvDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2695     }
2696     else
2697     {
2698         srvDesc.ViewDimension               = D3D11_SRV_DIMENSION_TEXTURECUBE;
2699         srvDesc.TextureCube.MipLevels       = mipLevels;
2700         srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
2701     }
2702 
2703     const TextureHelper11 *srvTexture = &texture;
2704 
2705     if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
2706     {
2707         ASSERT(mTopLevel == 0);
2708         ASSERT(baseLevel == 0);
2709         // This code also assumes that the incoming texture equals either mLevelZeroTexture or
2710         // mTexture.
2711 
2712         if (mipLevels == 1 && mMipLevels > 1)
2713         {
2714             // We must use a SRV on the level-zero-only texture.
2715             ANGLE_TRY(ensureTextureExists(context, 1));
2716             srvTexture = &mLevelZeroTexture;
2717         }
2718         else
2719         {
2720             ASSERT(mipLevels == static_cast<int>(mMipLevels));
2721             ASSERT(mTexture.valid() && texture == mTexture);
2722             srvTexture = &mTexture;
2723         }
2724     }
2725 
2726     ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, srvTexture->get(),
2727                                           outSRV));
2728     outSRV->setLabels("TexStorageCube.SRV", &mTextureLabel);
2729 
2730     return angle::Result::Continue;
2731 }
2732 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)2733 angle::Result TextureStorage11_Cube::createSRVForImage(const gl::Context *context,
2734                                                        int level,
2735                                                        DXGI_FORMAT format,
2736                                                        const TextureHelper11 &texture,
2737                                                        d3d11::SharedSRV *outSRV)
2738 {
2739     ASSERT(outSRV);
2740     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
2741     srvDesc.Format                         = format;
2742     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
2743     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
2744     srvDesc.Texture2DArray.MipLevels       = 1;
2745     srvDesc.Texture2DArray.FirstArraySlice = 0;
2746     srvDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2747     ANGLE_TRY(
2748         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
2749     outSRV->setLabels("TexStorageCube.SRVForImage", &mTextureLabel);
2750     return angle::Result::Continue;
2751 }
2752 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)2753 angle::Result TextureStorage11_Cube::createUAVForImage(const gl::Context *context,
2754                                                        int level,
2755                                                        DXGI_FORMAT format,
2756                                                        const TextureHelper11 &texture,
2757                                                        d3d11::SharedUAV *outUAV)
2758 {
2759     ASSERT(outUAV);
2760     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
2761     uavDesc.Format                         = format;
2762     uavDesc.ViewDimension                  = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
2763     uavDesc.Texture2DArray.MipSlice        = mTopLevel + level;
2764     uavDesc.Texture2DArray.FirstArraySlice = 0;
2765     uavDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2766     ANGLE_TRY(
2767         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
2768     outUAV->setLabels("TexStorageCube.UAVForImage", &mTextureLabel);
2769     return angle::Result::Continue;
2770 }
2771 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)2772 angle::Result TextureStorage11_Cube::getSwizzleTexture(const gl::Context *context,
2773                                                        const TextureHelper11 **outTexture)
2774 {
2775     ASSERT(outTexture);
2776 
2777     if (!mSwizzleTexture.valid())
2778     {
2779         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
2780 
2781         D3D11_TEXTURE2D_DESC desc;
2782         desc.Width              = mTextureWidth;
2783         desc.Height             = mTextureHeight;
2784         desc.MipLevels          = mMipLevels;
2785         desc.ArraySize          = gl::kCubeFaceCount;
2786         desc.Format             = format.texFormat;
2787         desc.SampleDesc.Count   = 1;
2788         desc.SampleDesc.Quality = 0;
2789         desc.Usage              = D3D11_USAGE_DEFAULT;
2790         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
2791         desc.CPUAccessFlags     = 0;
2792         desc.MiscFlags          = D3D11_RESOURCE_MISC_TEXTURECUBE;
2793 
2794         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
2795                                              &mSwizzleTexture));
2796         mSwizzleTexture.setLabels("TexStorageCube.SwizzleTexture", &mTextureLabel);
2797     }
2798 
2799     *outTexture = &mSwizzleTexture;
2800     return angle::Result::Continue;
2801 }
2802 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)2803 angle::Result TextureStorage11_Cube::getSwizzleRenderTarget(const gl::Context *context,
2804                                                             int mipLevel,
2805                                                             const d3d11::RenderTargetView **outRTV)
2806 {
2807     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
2808     ASSERT(outRTV);
2809 
2810     if (!mSwizzleRenderTargets[mipLevel].valid())
2811     {
2812         const TextureHelper11 *swizzleTexture = nullptr;
2813         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
2814 
2815         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
2816         rtvDesc.Format =
2817             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
2818         rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
2819         rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
2820         rtvDesc.Texture2DArray.FirstArraySlice = 0;
2821         rtvDesc.Texture2DArray.ArraySize       = gl::kCubeFaceCount;
2822 
2823         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
2824                                               mSwizzleTexture.get(),
2825                                               &mSwizzleRenderTargets[mipLevel]));
2826     }
2827 
2828     *outRTV = &mSwizzleRenderTargets[mipLevel];
2829     return angle::Result::Continue;
2830 }
2831 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)2832 angle::Result TextureStorage11_Cube::ensureDropStencilTexture(const gl::Context *context,
2833                                                               DropStencil *dropStencilOut)
2834 {
2835     if (mDropStencilTexture.valid())
2836     {
2837         *dropStencilOut = DropStencil::ALREADY_EXISTS;
2838         return angle::Result::Continue;
2839     }
2840 
2841     D3D11_TEXTURE2D_DESC dropDesc = {};
2842     dropDesc.ArraySize            = 6;
2843     dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
2844     dropDesc.CPUAccessFlags       = 0;
2845     dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
2846     dropDesc.Height               = mTextureHeight;
2847     dropDesc.MipLevels            = mMipLevels;
2848     dropDesc.MiscFlags            = D3D11_RESOURCE_MISC_TEXTURECUBE;
2849     dropDesc.SampleDesc.Count     = 1;
2850     dropDesc.SampleDesc.Quality   = 0;
2851     dropDesc.Usage                = D3D11_USAGE_DEFAULT;
2852     dropDesc.Width                = mTextureWidth;
2853 
2854     const auto &format =
2855         d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
2856     ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
2857                                          &mDropStencilTexture));
2858     mDropStencilTexture.setLabels("TexStorageCube.DropStencil", &mTextureLabel);
2859 
2860     ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
2861 
2862     *dropStencilOut = DropStencil::CREATED;
2863     return angle::Result::Continue;
2864 }
2865 
resolveTexture(const gl::Context * context)2866 angle::Result TextureStorage11_Cube::resolveTexture(const gl::Context *context)
2867 {
2868     if (mMSTexInfo && mMSTexInfo->msTex && mMSTexInfo->msTextureNeedsResolve)
2869     {
2870         ANGLE_TRY(resolveTextureHelper(context, mTexture));
2871         onStateChange(angle::SubjectMessage::ContentsChanged);
2872     }
2873     return angle::Result::Continue;
2874 }
2875 
onLabelUpdate()2876 void TextureStorage11_Cube::onLabelUpdate()
2877 {
2878     if (mTexture.valid())
2879     {
2880         mTexture.setKHRDebugLabel(&mTextureLabel);
2881     }
2882     if (mLevelZeroTexture.valid())
2883     {
2884         mLevelZeroTexture.setKHRDebugLabel(&mTextureLabel);
2885     }
2886     if (mSwizzleTexture.valid())
2887     {
2888         mSwizzleTexture.setKHRDebugLabel(&mTextureLabel);
2889     }
2890 }
2891 
TextureStorage11_3D(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels,const std::string & label)2892 TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
2893                                          GLenum internalformat,
2894                                          bool renderTarget,
2895                                          GLsizei width,
2896                                          GLsizei height,
2897                                          GLsizei depth,
2898                                          int levels,
2899                                          const std::string &label)
2900     : TextureStorage11(
2901           renderer,
2902           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
2903           GetTextureMiscFlags(internalformat,
2904                               renderer->getRenderer11DeviceCaps(),
2905                               renderTarget,
2906                               levels),
2907           internalformat,
2908           label)
2909 {
2910     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2911     {
2912         mAssociatedImages[i]   = nullptr;
2913         mLevelRenderTargets[i] = nullptr;
2914     }
2915 
2916     // adjust size if needed for compressed textures
2917     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
2918 
2919     mMipLevels     = mTopLevel + levels;
2920     mTextureWidth  = width;
2921     mTextureHeight = height;
2922     mTextureDepth  = depth;
2923 }
2924 
onDestroy(const gl::Context * context)2925 angle::Result TextureStorage11_3D::onDestroy(const gl::Context *context)
2926 {
2927     for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2928     {
2929         if (mAssociatedImages[i] != nullptr)
2930         {
2931             mAssociatedImages[i]->verifyAssociatedStorageValid(this);
2932 
2933             // We must let the Images recover their data before we delete it from the
2934             // TextureStorage.
2935             ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
2936         }
2937     }
2938 
2939     return angle::Result::Continue;
2940 }
2941 
~TextureStorage11_3D()2942 TextureStorage11_3D::~TextureStorage11_3D() {}
2943 
associateImage(Image11 * image,const gl::ImageIndex & index)2944 void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
2945 {
2946     const GLint level = index.getLevelIndex();
2947 
2948     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2949 
2950     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2951     {
2952         mAssociatedImages[level] = image;
2953     }
2954 }
2955 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)2956 void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index,
2957                                                      Image11 *expectedImage)
2958 {
2959     const GLint level = index.getLevelIndex();
2960 
2961     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2962     // This validation check should never return false. It means the Image/TextureStorage
2963     // association is broken.
2964     ASSERT(mAssociatedImages[level] == expectedImage);
2965 }
2966 
2967 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)2968 void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
2969 {
2970     const GLint level = index.getLevelIndex();
2971 
2972     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2973     ASSERT(mAssociatedImages[level] == expectedImage);
2974     mAssociatedImages[level] = nullptr;
2975 }
2976 
2977 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
2978 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)2979 angle::Result TextureStorage11_3D::releaseAssociatedImage(const gl::Context *context,
2980                                                           const gl::ImageIndex &index,
2981                                                           Image11 *incomingImage)
2982 {
2983     const GLint level = index.getLevelIndex();
2984 
2985     ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
2986 
2987     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2988     {
2989         // No need to let the old Image recover its data, if it is also the incoming Image.
2990         if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
2991         {
2992             // Ensure that the Image is still associated with this TextureStorage.
2993             mAssociatedImages[level]->verifyAssociatedStorageValid(this);
2994 
2995             // Force the image to recover from storage before its data is overwritten.
2996             // This will reset mAssociatedImages[level] to nullptr too.
2997             ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
2998         }
2999     }
3000 
3001     return angle::Result::Continue;
3002 }
3003 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3004 angle::Result TextureStorage11_3D::getResource(const gl::Context *context,
3005                                                const TextureHelper11 **outResource)
3006 {
3007     // If the width, height or depth are not positive this should be treated as an incomplete
3008     // texture. We handle that here by skipping the d3d texture creation.
3009     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
3010     {
3011         ASSERT(mMipLevels > 0);
3012 
3013         D3D11_TEXTURE3D_DESC desc;
3014         desc.Width          = mTextureWidth;
3015         desc.Height         = mTextureHeight;
3016         desc.Depth          = mTextureDepth;
3017         desc.MipLevels      = mMipLevels;
3018         desc.Format         = mFormatInfo.texFormat;
3019         desc.Usage          = D3D11_USAGE_DEFAULT;
3020         desc.BindFlags      = getBindFlags();
3021         desc.CPUAccessFlags = 0;
3022         desc.MiscFlags      = getMiscFlags();
3023 
3024         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
3025                                              &mTexture));
3026         mTexture.setLabels("TexStorage3D.Texture", &mTextureLabel);
3027     }
3028 
3029     *outResource = &mTexture;
3030     return angle::Result::Continue;
3031 }
3032 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3033 angle::Result TextureStorage11_3D::createSRVForSampler(const gl::Context *context,
3034                                                        int baseLevel,
3035                                                        int mipLevels,
3036                                                        DXGI_FORMAT format,
3037                                                        const TextureHelper11 &texture,
3038                                                        d3d11::SharedSRV *outSRV)
3039 {
3040     ASSERT(outSRV);
3041 
3042     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3043     srvDesc.Format                    = format;
3044     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE3D;
3045     srvDesc.Texture3D.MostDetailedMip = baseLevel;
3046     srvDesc.Texture3D.MipLevels       = mipLevels;
3047 
3048     ANGLE_TRY(
3049         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3050     outSRV->setLabels("TexStorage3D.SRV", &mTextureLabel);
3051 
3052     return angle::Result::Continue;
3053 }
3054 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3055 angle::Result TextureStorage11_3D::createSRVForImage(const gl::Context *context,
3056                                                      int level,
3057                                                      DXGI_FORMAT format,
3058                                                      const TextureHelper11 &texture,
3059                                                      d3d11::SharedSRV *outSRV)
3060 {
3061     ASSERT(outSRV);
3062     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3063     srvDesc.Format                    = format;
3064     srvDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE3D;
3065     srvDesc.Texture3D.MostDetailedMip = mTopLevel + level;
3066     srvDesc.Texture3D.MipLevels       = 1;
3067     ANGLE_TRY(
3068         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3069     outSRV->setLabels("TexStorage3D.SRVForImage", &mTextureLabel);
3070     return angle::Result::Continue;
3071 }
3072 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)3073 angle::Result TextureStorage11_3D::createUAVForImage(const gl::Context *context,
3074                                                      int level,
3075                                                      DXGI_FORMAT format,
3076                                                      const TextureHelper11 &texture,
3077                                                      d3d11::SharedUAV *outUAV)
3078 {
3079     ASSERT(outUAV);
3080     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
3081     uavDesc.Format                = format;
3082     uavDesc.ViewDimension         = D3D11_UAV_DIMENSION_TEXTURE3D;
3083     uavDesc.Texture3D.MipSlice    = mTopLevel + level;
3084     uavDesc.Texture3D.FirstWSlice = 0;
3085     uavDesc.Texture3D.WSize       = mTextureDepth;
3086     ANGLE_TRY(
3087         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
3088     outUAV->setLabels("TexStorage3D.UAVForImage", &mTextureLabel);
3089     return angle::Result::Continue;
3090 }
3091 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3092 angle::Result TextureStorage11_3D::findRenderTarget(const gl::Context *context,
3093                                                     const gl::ImageIndex &index,
3094                                                     GLsizei samples,
3095                                                     RenderTargetD3D **outRT) const
3096 {
3097     const int mipLevel = index.getLevelIndex();
3098     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3099 
3100     if (!index.hasLayer())
3101     {
3102         ASSERT(outRT);
3103         *outRT = mLevelRenderTargets[mipLevel].get();
3104         return angle::Result::Continue;
3105     }
3106 
3107     const int layer = index.getLayerIndex();
3108 
3109     LevelLayerKey key(mipLevel, layer);
3110     if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
3111     {
3112         ASSERT(outRT);
3113         *outRT = nullptr;
3114         return angle::Result::Continue;
3115     }
3116 
3117     ASSERT(outRT);
3118     *outRT = mLevelLayerRenderTargets.at(key).get();
3119     return angle::Result::Continue;
3120 }
3121 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)3122 angle::Result TextureStorage11_3D::getRenderTarget(const gl::Context *context,
3123                                                    const gl::ImageIndex &index,
3124                                                    GLsizei samples,
3125                                                    RenderTargetD3D **outRT)
3126 {
3127     const int mipLevel = index.getLevelIndex();
3128     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3129 
3130     ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
3131 
3132     Context11 *context11 = GetImplAs<Context11>(context);
3133 
3134     if (!index.hasLayer())
3135     {
3136         if (!mLevelRenderTargets[mipLevel])
3137         {
3138             const TextureHelper11 *texture = nullptr;
3139             ANGLE_TRY(getResource(context, &texture));
3140 
3141             const d3d11::SharedSRV *srv = nullptr;
3142             ANGLE_TRY(getSRVLevel(context, mipLevel, false, &srv));
3143 
3144             const d3d11::SharedSRV *blitSRV = nullptr;
3145             ANGLE_TRY(getSRVLevel(context, mipLevel, true, &blitSRV));
3146 
3147             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3148             rtvDesc.Format                = mFormatInfo.rtvFormat;
3149             rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
3150             rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
3151             rtvDesc.Texture3D.FirstWSlice = 0;
3152             rtvDesc.Texture3D.WSize       = static_cast<UINT>(-1);
3153 
3154             d3d11::RenderTargetView rtv;
3155             ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
3156             rtv.setLabels("TexStorage3D.RTV", &mTextureLabel);
3157 
3158             mLevelRenderTargets[mipLevel].reset(new TextureRenderTarget11(
3159                 std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat,
3160                 getFormatSet(), getLevelWidth(mipLevel), getLevelHeight(mipLevel),
3161                 getLevelDepth(mipLevel), 0));
3162         }
3163 
3164         ASSERT(outRT);
3165         *outRT = mLevelRenderTargets[mipLevel].get();
3166         return angle::Result::Continue;
3167     }
3168 
3169     const int layer = index.getLayerIndex();
3170 
3171     LevelLayerKey key(mipLevel, layer);
3172     if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
3173     {
3174         const TextureHelper11 *texture = nullptr;
3175         ANGLE_TRY(getResource(context, &texture));
3176 
3177         // TODO, what kind of SRV is expected here?
3178         const d3d11::SharedSRV srv;
3179         const d3d11::SharedSRV blitSRV;
3180 
3181         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3182         rtvDesc.Format                = mFormatInfo.rtvFormat;
3183         rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
3184         rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
3185         rtvDesc.Texture3D.FirstWSlice = layer;
3186         rtvDesc.Texture3D.WSize       = 1;
3187 
3188         d3d11::RenderTargetView rtv;
3189         ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
3190         rtv.setLabels("TexStorage3D.LayerRTV", &mTextureLabel);
3191 
3192         mLevelLayerRenderTargets[key].reset(new TextureRenderTarget11(
3193             std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3194             getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
3195     }
3196 
3197     ASSERT(outRT);
3198     *outRT = mLevelLayerRenderTargets[key].get();
3199     return angle::Result::Continue;
3200 }
3201 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)3202 angle::Result TextureStorage11_3D::getSwizzleTexture(const gl::Context *context,
3203                                                      const TextureHelper11 **outTexture)
3204 {
3205     ASSERT(outTexture);
3206 
3207     if (!mSwizzleTexture.valid())
3208     {
3209         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
3210 
3211         D3D11_TEXTURE3D_DESC desc;
3212         desc.Width          = mTextureWidth;
3213         desc.Height         = mTextureHeight;
3214         desc.Depth          = mTextureDepth;
3215         desc.MipLevels      = mMipLevels;
3216         desc.Format         = format.texFormat;
3217         desc.Usage          = D3D11_USAGE_DEFAULT;
3218         desc.BindFlags      = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
3219         desc.CPUAccessFlags = 0;
3220         desc.MiscFlags      = 0;
3221 
3222         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
3223                                              &mSwizzleTexture));
3224         mSwizzleTexture.setLabels("TexStorage3D.SwizzleTexture", &mTextureLabel);
3225     }
3226 
3227     *outTexture = &mSwizzleTexture;
3228     return angle::Result::Continue;
3229 }
3230 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)3231 angle::Result TextureStorage11_3D::getSwizzleRenderTarget(const gl::Context *context,
3232                                                           int mipLevel,
3233                                                           const d3d11::RenderTargetView **outRTV)
3234 {
3235     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3236     ASSERT(outRTV);
3237 
3238     if (!mSwizzleRenderTargets[mipLevel].valid())
3239     {
3240         const TextureHelper11 *swizzleTexture = nullptr;
3241         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
3242 
3243         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3244         rtvDesc.Format =
3245             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
3246         rtvDesc.ViewDimension         = D3D11_RTV_DIMENSION_TEXTURE3D;
3247         rtvDesc.Texture3D.MipSlice    = mTopLevel + mipLevel;
3248         rtvDesc.Texture3D.FirstWSlice = 0;
3249         rtvDesc.Texture3D.WSize       = static_cast<UINT>(-1);
3250 
3251         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3252                                               mSwizzleTexture.get(),
3253                                               &mSwizzleRenderTargets[mipLevel]));
3254         mSwizzleRenderTargets[mipLevel].setLabels("TexStorage3D.SwizzleRTV", &mTextureLabel);
3255     }
3256 
3257     *outRTV = &mSwizzleRenderTargets[mipLevel];
3258     return angle::Result::Continue;
3259 }
3260 
onLabelUpdate()3261 void TextureStorage11_3D::onLabelUpdate()
3262 {
3263     if (mTexture.valid())
3264     {
3265         mTexture.setKHRDebugLabel(&mTextureLabel);
3266     }
3267     if (mSwizzleTexture.valid())
3268     {
3269         mSwizzleTexture.setKHRDebugLabel(&mTextureLabel);
3270     }
3271 }
3272 
TextureStorage11_2DArray(Renderer11 * renderer,GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels,const std::string & label)3273 TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer,
3274                                                    GLenum internalformat,
3275                                                    bool renderTarget,
3276                                                    GLsizei width,
3277                                                    GLsizei height,
3278                                                    GLsizei depth,
3279                                                    int levels,
3280                                                    const std::string &label)
3281     : TextureStorage11(
3282           renderer,
3283           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
3284           GetTextureMiscFlags(internalformat,
3285                               renderer->getRenderer11DeviceCaps(),
3286                               renderTarget,
3287                               levels),
3288           internalformat,
3289           label)
3290 {
3291     // adjust size if needed for compressed textures
3292     d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
3293 
3294     mMipLevels     = mTopLevel + levels;
3295     mTextureWidth  = width;
3296     mTextureHeight = height;
3297     mTextureDepth  = depth;
3298 }
3299 
onDestroy(const gl::Context * context)3300 angle::Result TextureStorage11_2DArray::onDestroy(const gl::Context *context)
3301 {
3302     for (auto iter : mAssociatedImages)
3303     {
3304         if (iter.second)
3305         {
3306             iter.second->verifyAssociatedStorageValid(this);
3307 
3308             // We must let the Images recover their data before we delete it from the
3309             // TextureStorage.
3310             ANGLE_TRY(iter.second->recoverFromAssociatedStorage(context));
3311         }
3312     }
3313     mAssociatedImages.clear();
3314 
3315     return angle::Result::Continue;
3316 }
3317 
~TextureStorage11_2DArray()3318 TextureStorage11_2DArray::~TextureStorage11_2DArray() {}
3319 
associateImage(Image11 * image,const gl::ImageIndex & index)3320 void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
3321 {
3322     const GLint level       = index.getLevelIndex();
3323     const GLint layerTarget = index.getLayerIndex();
3324     const GLint numLayers   = index.getLayerCount();
3325 
3326     ASSERT(0 <= level && level < getLevelCount());
3327 
3328     if (0 <= level && level < getLevelCount())
3329     {
3330         LevelLayerRangeKey key(level, layerTarget, numLayers);
3331         mAssociatedImages[key] = image;
3332     }
3333 }
3334 
verifyAssociatedImageValid(const gl::ImageIndex & index,Image11 * expectedImage)3335 void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index,
3336                                                           Image11 *expectedImage)
3337 {
3338     const GLint level       = index.getLevelIndex();
3339     const GLint layerTarget = index.getLayerIndex();
3340     const GLint numLayers   = index.getLayerCount();
3341 
3342     LevelLayerRangeKey key(level, layerTarget, numLayers);
3343 
3344     // This validation check should never return false. It means the Image/TextureStorage
3345     // association is broken.
3346     bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
3347                      (mAssociatedImages[key] == expectedImage));
3348     ASSERT(retValue);
3349 }
3350 
3351 // disassociateImage allows an Image to end its association with a Storage.
disassociateImage(const gl::ImageIndex & index,Image11 * expectedImage)3352 void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index,
3353                                                  Image11 *expectedImage)
3354 {
3355     const GLint level       = index.getLevelIndex();
3356     const GLint layerTarget = index.getLayerIndex();
3357     const GLint numLayers   = index.getLayerCount();
3358 
3359     LevelLayerRangeKey key(level, layerTarget, numLayers);
3360 
3361     bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
3362                                     (mAssociatedImages[key] == expectedImage));
3363     ASSERT(imageAssociationCorrect);
3364     mAssociatedImages[key] = nullptr;
3365 }
3366 
3367 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
3368 // recover its data before ending the association.
releaseAssociatedImage(const gl::Context * context,const gl::ImageIndex & index,Image11 * incomingImage)3369 angle::Result TextureStorage11_2DArray::releaseAssociatedImage(const gl::Context *context,
3370                                                                const gl::ImageIndex &index,
3371                                                                Image11 *incomingImage)
3372 {
3373     const GLint level       = index.getLevelIndex();
3374     const GLint layerTarget = index.getLayerIndex();
3375     const GLint numLayers   = index.getLayerCount();
3376 
3377     LevelLayerRangeKey key(level, layerTarget, numLayers);
3378 
3379     if (mAssociatedImages.find(key) != mAssociatedImages.end())
3380     {
3381         if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage)
3382         {
3383             // Ensure that the Image is still associated with this TextureStorage.
3384             mAssociatedImages[key]->verifyAssociatedStorageValid(this);
3385 
3386             // Force the image to recover from storage before its data is overwritten.
3387             // This will reset mAssociatedImages[level] to nullptr too.
3388             ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage(context));
3389         }
3390     }
3391 
3392     return angle::Result::Continue;
3393 }
3394 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3395 angle::Result TextureStorage11_2DArray::getResource(const gl::Context *context,
3396                                                     const TextureHelper11 **outResource)
3397 {
3398     // if the width, height or depth is not positive this should be treated as an incomplete texture
3399     // we handle that here by skipping the d3d texture creation
3400     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
3401     {
3402         ASSERT(mMipLevels > 0);
3403 
3404         D3D11_TEXTURE2D_DESC desc;
3405         desc.Width              = mTextureWidth;
3406         desc.Height             = mTextureHeight;
3407         desc.MipLevels          = mMipLevels;
3408         desc.ArraySize          = mTextureDepth;
3409         desc.Format             = mFormatInfo.texFormat;
3410         desc.SampleDesc.Count   = 1;
3411         desc.SampleDesc.Quality = 0;
3412         desc.Usage              = D3D11_USAGE_DEFAULT;
3413         desc.BindFlags          = getBindFlags();
3414         desc.CPUAccessFlags     = 0;
3415         desc.MiscFlags          = getMiscFlags();
3416 
3417         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
3418                                              &mTexture));
3419         mTexture.setLabels("TexStorage2DArray.Texture", &mTextureLabel);
3420     }
3421 
3422     *outResource = &mTexture;
3423     return angle::Result::Continue;
3424 }
3425 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3426 angle::Result TextureStorage11_2DArray::createSRVForSampler(const gl::Context *context,
3427                                                             int baseLevel,
3428                                                             int mipLevels,
3429                                                             DXGI_FORMAT format,
3430                                                             const TextureHelper11 &texture,
3431                                                             d3d11::SharedSRV *outSRV)
3432 {
3433     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3434     srvDesc.Format                         = format;
3435     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3436     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
3437     srvDesc.Texture2DArray.MipLevels       = mipLevels;
3438     srvDesc.Texture2DArray.FirstArraySlice = 0;
3439     srvDesc.Texture2DArray.ArraySize       = mTextureDepth;
3440 
3441     ANGLE_TRY(
3442         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3443     outSRV->setLabels("TexStorage2DArray.SRV", &mTextureLabel);
3444 
3445     return angle::Result::Continue;
3446 }
3447 
createSRVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3448 angle::Result TextureStorage11_2DArray::createSRVForImage(const gl::Context *context,
3449                                                           int level,
3450                                                           DXGI_FORMAT format,
3451                                                           const TextureHelper11 &texture,
3452                                                           d3d11::SharedSRV *outSRV)
3453 {
3454     ASSERT(outSRV);
3455     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3456     srvDesc.Format                         = format;
3457     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3458     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
3459     srvDesc.Texture2DArray.MipLevels       = 1;
3460     srvDesc.Texture2DArray.FirstArraySlice = 0;
3461     srvDesc.Texture2DArray.ArraySize       = mTextureDepth;
3462     ANGLE_TRY(
3463         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3464     outSRV->setLabels("TexStorage2DArray.SRVForImage", &mTextureLabel);
3465     return angle::Result::Continue;
3466 }
3467 
createUAVForImage(const gl::Context * context,int level,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedUAV * outUAV)3468 angle::Result TextureStorage11_2DArray::createUAVForImage(const gl::Context *context,
3469                                                           int level,
3470                                                           DXGI_FORMAT format,
3471                                                           const TextureHelper11 &texture,
3472                                                           d3d11::SharedUAV *outUAV)
3473 {
3474     ASSERT(outUAV);
3475     D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
3476     uavDesc.Format                         = format;
3477     uavDesc.ViewDimension                  = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3478     uavDesc.Texture2DArray.MipSlice        = mTopLevel + level;
3479     uavDesc.Texture2DArray.FirstArraySlice = 0;
3480     uavDesc.Texture2DArray.ArraySize       = mTextureDepth;
3481     ANGLE_TRY(
3482         mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
3483     outUAV->setLabels("TexStorage2DArray.UAVForImage", &mTextureLabel);
3484     return angle::Result::Continue;
3485 }
3486 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3487 angle::Result TextureStorage11_2DArray::findRenderTarget(const gl::Context *context,
3488                                                          const gl::ImageIndex &index,
3489                                                          GLsizei samples,
3490                                                          RenderTargetD3D **outRT) const
3491 {
3492     ASSERT(index.hasLayer());
3493 
3494     const int mipLevel  = index.getLevelIndex();
3495     const int layer     = index.getLayerIndex();
3496     const int numLayers = index.getLayerCount();
3497 
3498     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3499 
3500     LevelLayerRangeKey key(mipLevel, layer, numLayers);
3501     if (mRenderTargets.find(key) == mRenderTargets.end())
3502     {
3503         ASSERT(outRT);
3504         *outRT = nullptr;
3505         return angle::Result::Continue;
3506     }
3507 
3508     ASSERT(outRT);
3509     *outRT = mRenderTargets.at(key).get();
3510     return angle::Result::Continue;
3511 }
3512 
createRenderTargetSRV(const gl::Context * context,const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const3513 angle::Result TextureStorage11_2DArray::createRenderTargetSRV(const gl::Context *context,
3514                                                               const TextureHelper11 &texture,
3515                                                               const gl::ImageIndex &index,
3516                                                               DXGI_FORMAT resourceFormat,
3517                                                               d3d11::SharedSRV *srv) const
3518 {
3519     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3520     srvDesc.Format                         = resourceFormat;
3521     srvDesc.ViewDimension                  = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3522     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
3523     srvDesc.Texture2DArray.MipLevels       = 1;
3524     srvDesc.Texture2DArray.FirstArraySlice = index.getLayerIndex();
3525     srvDesc.Texture2DArray.ArraySize       = index.getLayerCount();
3526 
3527     ANGLE_TRY(
3528         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
3529 
3530     return angle::Result::Continue;
3531 }
3532 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)3533 angle::Result TextureStorage11_2DArray::getRenderTarget(const gl::Context *context,
3534                                                         const gl::ImageIndex &index,
3535                                                         GLsizei samples,
3536                                                         RenderTargetD3D **outRT)
3537 {
3538     ASSERT(index.hasLayer());
3539 
3540     const int mipLevel  = index.getLevelIndex();
3541     const int layer     = index.getLayerIndex();
3542     const int numLayers = index.getLayerCount();
3543 
3544     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3545 
3546     LevelLayerRangeKey key(mipLevel, layer, numLayers);
3547     if (mRenderTargets.find(key) == mRenderTargets.end())
3548     {
3549         const TextureHelper11 *texture = nullptr;
3550         ANGLE_TRY(getResource(context, &texture));
3551         d3d11::SharedSRV srv;
3552         ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
3553         d3d11::SharedSRV blitSRV;
3554         if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
3555         {
3556             ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
3557                                             &blitSRV));
3558         }
3559         else
3560         {
3561             blitSRV = srv.makeCopy();
3562         }
3563 
3564         srv.setLabels("TexStorage2DArray.RenderTargetSRV", &mTextureLabel);
3565 
3566         if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
3567         {
3568             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3569             rtvDesc.Format                         = mFormatInfo.rtvFormat;
3570             rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
3571             rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
3572             rtvDesc.Texture2DArray.FirstArraySlice = layer;
3573             rtvDesc.Texture2DArray.ArraySize       = numLayers;
3574 
3575             d3d11::RenderTargetView rtv;
3576             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3577                                                   texture->get(), &rtv));
3578             rtv.setLabels("TexStorage2DArray.RenderTargetRTV", &mTextureLabel);
3579 
3580             mRenderTargets[key].reset(new TextureRenderTarget11(
3581                 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3582                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
3583         }
3584         else
3585         {
3586             ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
3587 
3588             D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
3589             dsvDesc.Format                         = mFormatInfo.dsvFormat;
3590             dsvDesc.ViewDimension                  = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
3591             dsvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
3592             dsvDesc.Texture2DArray.FirstArraySlice = layer;
3593             dsvDesc.Texture2DArray.ArraySize       = numLayers;
3594             dsvDesc.Flags                          = 0;
3595 
3596             d3d11::DepthStencilView dsv;
3597             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), dsvDesc,
3598                                                   texture->get(), &dsv));
3599             dsv.setLabels("TexStorage2DArray.RenderTargetDSV", &mTextureLabel);
3600 
3601             mRenderTargets[key].reset(new TextureRenderTarget11(
3602                 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
3603                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
3604         }
3605     }
3606 
3607     ASSERT(outRT);
3608     *outRT = mRenderTargets[key].get();
3609     return angle::Result::Continue;
3610 }
3611 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)3612 angle::Result TextureStorage11_2DArray::getSwizzleTexture(const gl::Context *context,
3613                                                           const TextureHelper11 **outTexture)
3614 {
3615     if (!mSwizzleTexture.valid())
3616     {
3617         const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
3618 
3619         D3D11_TEXTURE2D_DESC desc;
3620         desc.Width              = mTextureWidth;
3621         desc.Height             = mTextureHeight;
3622         desc.MipLevels          = mMipLevels;
3623         desc.ArraySize          = mTextureDepth;
3624         desc.Format             = format.texFormat;
3625         desc.SampleDesc.Count   = 1;
3626         desc.SampleDesc.Quality = 0;
3627         desc.Usage              = D3D11_USAGE_DEFAULT;
3628         desc.BindFlags          = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
3629         desc.CPUAccessFlags     = 0;
3630         desc.MiscFlags          = 0;
3631 
3632         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
3633                                              &mSwizzleTexture));
3634         mSwizzleTexture.setLabels("TexStorage2DArray.SwizzleTexture", &mTextureLabel);
3635     }
3636 
3637     *outTexture = &mSwizzleTexture;
3638     return angle::Result::Continue;
3639 }
3640 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)3641 angle::Result TextureStorage11_2DArray::getSwizzleRenderTarget(
3642     const gl::Context *context,
3643     int mipLevel,
3644     const d3d11::RenderTargetView **outRTV)
3645 {
3646     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
3647     ASSERT(outRTV);
3648 
3649     if (!mSwizzleRenderTargets[mipLevel].valid())
3650     {
3651         const TextureHelper11 *swizzleTexture = nullptr;
3652         ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
3653 
3654         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3655         rtvDesc.Format =
3656             mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
3657         rtvDesc.ViewDimension                  = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
3658         rtvDesc.Texture2DArray.MipSlice        = mTopLevel + mipLevel;
3659         rtvDesc.Texture2DArray.FirstArraySlice = 0;
3660         rtvDesc.Texture2DArray.ArraySize       = mTextureDepth;
3661 
3662         ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
3663                                               mSwizzleTexture.get(),
3664                                               &mSwizzleRenderTargets[mipLevel]));
3665     }
3666 
3667     *outRTV = &mSwizzleRenderTargets[mipLevel];
3668     return angle::Result::Continue;
3669 }
3670 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)3671 angle::Result TextureStorage11_2DArray::ensureDropStencilTexture(const gl::Context *context,
3672                                                                  DropStencil *dropStencilOut)
3673 {
3674     if (mDropStencilTexture.valid())
3675     {
3676         *dropStencilOut = DropStencil::ALREADY_EXISTS;
3677         return angle::Result::Continue;
3678     }
3679 
3680     D3D11_TEXTURE2D_DESC dropDesc = {};
3681     dropDesc.ArraySize            = mTextureDepth;
3682     dropDesc.BindFlags            = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
3683     dropDesc.CPUAccessFlags       = 0;
3684     dropDesc.Format               = DXGI_FORMAT_R32_TYPELESS;
3685     dropDesc.Height               = mTextureHeight;
3686     dropDesc.MipLevels            = mMipLevels;
3687     dropDesc.MiscFlags            = 0;
3688     dropDesc.SampleDesc.Count     = 1;
3689     dropDesc.SampleDesc.Quality   = 0;
3690     dropDesc.Usage                = D3D11_USAGE_DEFAULT;
3691     dropDesc.Width                = mTextureWidth;
3692 
3693     const auto &format =
3694         d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
3695     ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
3696                                          &mDropStencilTexture));
3697     mDropStencilTexture.setLabels("TexStorage2DArray.DropStencil", &mTextureLabel);
3698 
3699     std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
3700 
3701     ANGLE_TRY(initDropStencilTexture(
3702         context, gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
3703 
3704     *dropStencilOut = DropStencil::CREATED;
3705     return angle::Result::Continue;
3706 }
3707 
onLabelUpdate()3708 void TextureStorage11_2DArray::onLabelUpdate()
3709 {
3710     if (mTexture.valid())
3711     {
3712         mTexture.setKHRDebugLabel(&mTextureLabel);
3713     }
3714     if (mSwizzleTexture.valid())
3715     {
3716         mSwizzleTexture.setKHRDebugLabel(&mTextureLabel);
3717     }
3718 }
3719 
TextureStorage11_2DMultisample(Renderer11 * renderer,GLenum internalformat,GLsizei width,GLsizei height,int levels,int samples,bool fixedSampleLocations,const std::string & label)3720 TextureStorage11_2DMultisample::TextureStorage11_2DMultisample(Renderer11 *renderer,
3721                                                                GLenum internalformat,
3722                                                                GLsizei width,
3723                                                                GLsizei height,
3724                                                                int levels,
3725                                                                int samples,
3726                                                                bool fixedSampleLocations,
3727                                                                const std::string &label)
3728     : TextureStorage11ImmutableBase(
3729           renderer,
3730           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true),
3731           GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels),
3732           internalformat,
3733           label),
3734       mTexture(),
3735       mRenderTarget(nullptr)
3736 {
3737     // There are no multisampled compressed formats, so there's no need to adjust texture size
3738     // according to block size.
3739     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockWidth <= 1);
3740     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockHeight <= 1);
3741 
3742     mMipLevels            = 1;
3743     mTextureWidth         = width;
3744     mTextureHeight        = height;
3745     mTextureDepth         = 1;
3746     mSamples              = samples;
3747     mFixedSampleLocations = fixedSampleLocations;
3748 }
3749 
onDestroy(const gl::Context * context)3750 angle::Result TextureStorage11_2DMultisample::onDestroy(const gl::Context *context)
3751 {
3752     mRenderTarget.reset();
3753     return angle::Result::Continue;
3754 }
3755 
~TextureStorage11_2DMultisample()3756 TextureStorage11_2DMultisample::~TextureStorage11_2DMultisample() {}
3757 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)3758 angle::Result TextureStorage11_2DMultisample::copyToStorage(const gl::Context *context,
3759                                                             TextureStorage *destStorage)
3760 {
3761     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3762     return angle::Result::Stop;
3763 }
3764 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3765 angle::Result TextureStorage11_2DMultisample::getResource(const gl::Context *context,
3766                                                           const TextureHelper11 **outResource)
3767 {
3768     ANGLE_TRY(ensureTextureExists(context, 1));
3769 
3770     *outResource = &mTexture;
3771     return angle::Result::Continue;
3772 }
3773 
ensureTextureExists(const gl::Context * context,int mipLevels)3774 angle::Result TextureStorage11_2DMultisample::ensureTextureExists(const gl::Context *context,
3775                                                                   int mipLevels)
3776 {
3777     // For Multisampled textures, mipLevels always equals 1.
3778     ASSERT(mipLevels == 1);
3779 
3780     // if the width or height is not positive this should be treated as an incomplete texture
3781     // we handle that here by skipping the d3d texture creation
3782     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
3783     {
3784         D3D11_TEXTURE2D_DESC desc;
3785         ZeroMemory(&desc, sizeof(desc));
3786         desc.Width          = mTextureWidth;  // Compressed texture size constraints?
3787         desc.Height         = mTextureHeight;
3788         desc.MipLevels      = mipLevels;
3789         desc.ArraySize      = 1;
3790         desc.Format         = mFormatInfo.texFormat;
3791         desc.Usage          = D3D11_USAGE_DEFAULT;
3792         desc.BindFlags      = getBindFlags() & ~D3D11_BIND_UNORDERED_ACCESS;
3793         desc.CPUAccessFlags = 0;
3794         desc.MiscFlags      = getMiscFlags();
3795 
3796         const gl::TextureCaps &textureCaps =
3797             mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
3798         GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
3799         desc.SampleDesc.Count   = (supportedSamples == 0) ? 1 : supportedSamples;
3800         desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples);
3801 
3802         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
3803                                              &mTexture));
3804         mTexture.setLabels("TexStorage2DMS.Texture", &mTextureLabel);
3805     }
3806 
3807     return angle::Result::Continue;
3808 }
3809 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const3810 angle::Result TextureStorage11_2DMultisample::findRenderTarget(const gl::Context *context,
3811                                                                const gl::ImageIndex &index,
3812                                                                GLsizei samples,
3813                                                                RenderTargetD3D **outRT) const
3814 {
3815     ASSERT(!index.hasLayer());
3816 
3817     const int level = index.getLevelIndex();
3818     ASSERT(level == 0);
3819 
3820     ASSERT(outRT);
3821     *outRT = mRenderTarget.get();
3822     return angle::Result::Continue;
3823 }
3824 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)3825 angle::Result TextureStorage11_2DMultisample::getRenderTarget(const gl::Context *context,
3826                                                               const gl::ImageIndex &index,
3827                                                               GLsizei samples,
3828                                                               RenderTargetD3D **outRT)
3829 {
3830     ASSERT(!index.hasLayer());
3831 
3832     const int level = index.getLevelIndex();
3833     ASSERT(level == 0);
3834 
3835     ASSERT(outRT);
3836     if (mRenderTarget)
3837     {
3838         *outRT = mRenderTarget.get();
3839         return angle::Result::Continue;
3840     }
3841 
3842     const TextureHelper11 *texture = nullptr;
3843     ANGLE_TRY(getResource(context, &texture));
3844 
3845     const d3d11::SharedSRV *srv = nullptr;
3846     ANGLE_TRY(getSRVLevel(context, level, false, &srv));
3847 
3848     const d3d11::SharedSRV *blitSRV = nullptr;
3849     ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
3850 
3851     Context11 *context11 = GetImplAs<Context11>(context);
3852 
3853     if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
3854     {
3855         D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
3856         rtvDesc.Format        = mFormatInfo.rtvFormat;
3857         rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
3858 
3859         d3d11::RenderTargetView rtv;
3860         ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
3861 
3862         mRenderTarget.reset(new TextureRenderTarget11(
3863             std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
3864             getLevelWidth(level), getLevelHeight(level), 1, mSamples));
3865 
3866         *outRT = mRenderTarget.get();
3867         return angle::Result::Continue;
3868     }
3869 
3870     ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
3871 
3872     D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
3873     dsvDesc.Format        = mFormatInfo.dsvFormat;
3874     dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
3875     dsvDesc.Flags         = 0;
3876 
3877     d3d11::DepthStencilView dsv;
3878     ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
3879 
3880     mRenderTarget.reset(new TextureRenderTarget11(
3881         std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
3882         getLevelWidth(level), getLevelHeight(level), 1, mSamples));
3883 
3884     *outRT = mRenderTarget.get();
3885     return angle::Result::Continue;
3886 }
3887 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)3888 angle::Result TextureStorage11_2DMultisample::createSRVForSampler(const gl::Context *context,
3889                                                                   int baseLevel,
3890                                                                   int mipLevels,
3891                                                                   DXGI_FORMAT format,
3892                                                                   const TextureHelper11 &texture,
3893                                                                   d3d11::SharedSRV *outSRV)
3894 {
3895     ASSERT(outSRV);
3896 
3897     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
3898     srvDesc.Format        = format;
3899     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3900 
3901     ANGLE_TRY(
3902         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
3903     outSRV->setLabels("TexStorage2DMS.SRV", &mTextureLabel);
3904     return angle::Result::Continue;
3905 }
3906 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)3907 angle::Result TextureStorage11_2DMultisample::getSwizzleTexture(const gl::Context *context,
3908                                                                 const TextureHelper11 **outTexture)
3909 {
3910     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3911     return angle::Result::Stop;
3912 }
3913 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)3914 angle::Result TextureStorage11_2DMultisample::getSwizzleRenderTarget(
3915     const gl::Context *context,
3916     int mipLevel,
3917     const d3d11::RenderTargetView **outRTV)
3918 {
3919     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3920     return angle::Result::Stop;
3921 }
3922 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)3923 angle::Result TextureStorage11_2DMultisample::ensureDropStencilTexture(const gl::Context *context,
3924                                                                        DropStencil *dropStencilOut)
3925 {
3926     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3927     return angle::Result::Stop;
3928 }
3929 
onLabelUpdate()3930 void TextureStorage11_2DMultisample::onLabelUpdate()
3931 {
3932     if (mTexture.valid())
3933     {
3934         mTexture.setKHRDebugLabel(&mTextureLabel);
3935     }
3936 }
3937 
TextureStorage11_2DMultisampleArray(Renderer11 * renderer,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,int levels,int samples,bool fixedSampleLocations,const std::string & label)3938 TextureStorage11_2DMultisampleArray::TextureStorage11_2DMultisampleArray(Renderer11 *renderer,
3939                                                                          GLenum internalformat,
3940                                                                          GLsizei width,
3941                                                                          GLsizei height,
3942                                                                          GLsizei depth,
3943                                                                          int levels,
3944                                                                          int samples,
3945                                                                          bool fixedSampleLocations,
3946                                                                          const std::string &label)
3947     : TextureStorage11ImmutableBase(
3948           renderer,
3949           GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true),
3950           GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels),
3951           internalformat,
3952           label),
3953       mTexture()
3954 {
3955     // There are no multisampled compressed formats, so there's no need to adjust texture size
3956     // according to block size.
3957     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockWidth <= 1);
3958     ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockHeight <= 1);
3959 
3960     mMipLevels            = 1;
3961     mTextureWidth         = width;
3962     mTextureHeight        = height;
3963     mTextureDepth         = depth;
3964     mSamples              = samples;
3965     mFixedSampleLocations = fixedSampleLocations;
3966 }
3967 
onDestroy(const gl::Context * context)3968 angle::Result TextureStorage11_2DMultisampleArray::onDestroy(const gl::Context *context)
3969 {
3970     return angle::Result::Continue;
3971 }
3972 
~TextureStorage11_2DMultisampleArray()3973 TextureStorage11_2DMultisampleArray::~TextureStorage11_2DMultisampleArray() {}
3974 
copyToStorage(const gl::Context * context,TextureStorage * destStorage)3975 angle::Result TextureStorage11_2DMultisampleArray::copyToStorage(const gl::Context *context,
3976                                                                  TextureStorage *destStorage)
3977 {
3978     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
3979     return angle::Result::Stop;
3980 }
3981 
getResource(const gl::Context * context,const TextureHelper11 ** outResource)3982 angle::Result TextureStorage11_2DMultisampleArray::getResource(const gl::Context *context,
3983                                                                const TextureHelper11 **outResource)
3984 {
3985     ANGLE_TRY(ensureTextureExists(context, 1));
3986 
3987     *outResource = &mTexture;
3988     return angle::Result::Continue;
3989 }
3990 
ensureTextureExists(const gl::Context * context,int mipLevels)3991 angle::Result TextureStorage11_2DMultisampleArray::ensureTextureExists(const gl::Context *context,
3992                                                                        int mipLevels)
3993 {
3994     // For multisampled textures, mipLevels always equals 1.
3995     ASSERT(mipLevels == 1);
3996 
3997     // if the width or height is not positive this should be treated as an incomplete texture
3998     // we handle that here by skipping the d3d texture creation
3999     if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
4000     {
4001         D3D11_TEXTURE2D_DESC desc;
4002         ZeroMemory(&desc, sizeof(desc));
4003         desc.Width          = mTextureWidth;
4004         desc.Height         = mTextureHeight;
4005         desc.MipLevels      = mipLevels;
4006         desc.ArraySize      = mTextureDepth;
4007         desc.Format         = mFormatInfo.texFormat;
4008         desc.Usage          = D3D11_USAGE_DEFAULT;
4009         desc.BindFlags      = getBindFlags() & ~D3D11_BIND_UNORDERED_ACCESS;
4010         desc.CPUAccessFlags = 0;
4011         desc.MiscFlags      = getMiscFlags();
4012 
4013         const gl::TextureCaps &textureCaps =
4014             mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
4015         GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
4016         desc.SampleDesc.Count   = (supportedSamples == 0) ? 1 : supportedSamples;
4017         desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples);
4018 
4019         ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
4020                                              &mTexture));
4021         mTexture.setLabels("TexStorage2DMSArray.Texture", &mTextureLabel);
4022     }
4023 
4024     return angle::Result::Continue;
4025 }
4026 
findRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT) const4027 angle::Result TextureStorage11_2DMultisampleArray::findRenderTarget(const gl::Context *context,
4028                                                                     const gl::ImageIndex &index,
4029                                                                     GLsizei samples,
4030                                                                     RenderTargetD3D **outRT) const
4031 {
4032     ASSERT(index.hasLayer());
4033 
4034     const int mipLevel = index.getLevelIndex();
4035     ASSERT(mipLevel == 0);
4036     const int layer     = index.getLayerIndex();
4037     const int numLayers = index.getLayerCount();
4038 
4039     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
4040 
4041     TextureStorage11_2DArray::LevelLayerRangeKey key(mipLevel, layer, numLayers);
4042     if (mRenderTargets.find(key) == mRenderTargets.end())
4043     {
4044         ASSERT(outRT);
4045         *outRT = nullptr;
4046         return angle::Result::Continue;
4047     }
4048 
4049     ASSERT(outRT);
4050     *outRT = mRenderTargets.at(key).get();
4051     return angle::Result::Continue;
4052 }
4053 
createRenderTargetSRV(const gl::Context * context,const TextureHelper11 & texture,const gl::ImageIndex & index,DXGI_FORMAT resourceFormat,d3d11::SharedSRV * srv) const4054 angle::Result TextureStorage11_2DMultisampleArray::createRenderTargetSRV(
4055     const gl::Context *context,
4056     const TextureHelper11 &texture,
4057     const gl::ImageIndex &index,
4058     DXGI_FORMAT resourceFormat,
4059     d3d11::SharedSRV *srv) const
4060 {
4061     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
4062     srvDesc.Format                           = resourceFormat;
4063     srvDesc.ViewDimension                    = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
4064     srvDesc.Texture2DMSArray.FirstArraySlice = index.getLayerIndex();
4065     srvDesc.Texture2DMSArray.ArraySize       = index.getLayerCount();
4066 
4067     ANGLE_TRY(
4068         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
4069 
4070     return angle::Result::Continue;
4071 }
4072 
getRenderTarget(const gl::Context * context,const gl::ImageIndex & index,GLsizei samples,RenderTargetD3D ** outRT)4073 angle::Result TextureStorage11_2DMultisampleArray::getRenderTarget(const gl::Context *context,
4074                                                                    const gl::ImageIndex &index,
4075                                                                    GLsizei samples,
4076                                                                    RenderTargetD3D **outRT)
4077 {
4078     ASSERT(index.hasLayer());
4079 
4080     const int mipLevel = index.getLevelIndex();
4081     ASSERT(mipLevel == 0);
4082     const int layer     = index.getLayerIndex();
4083     const int numLayers = index.getLayerCount();
4084 
4085     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
4086 
4087     TextureStorage11_2DArray::LevelLayerRangeKey key(mipLevel, layer, numLayers);
4088     if (mRenderTargets.find(key) == mRenderTargets.end())
4089     {
4090         const TextureHelper11 *texture = nullptr;
4091         ANGLE_TRY(getResource(context, &texture));
4092         d3d11::SharedSRV srv;
4093         ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
4094         d3d11::SharedSRV blitSRV;
4095         if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
4096         {
4097             ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
4098                                             &blitSRV));
4099         }
4100         else
4101         {
4102             blitSRV = srv.makeCopy();
4103         }
4104 
4105         srv.setLabels("TexStorage2DMSArray.RenderTargetSRV", &mTextureLabel);
4106 
4107         if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
4108         {
4109             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
4110             rtvDesc.Format                           = mFormatInfo.rtvFormat;
4111             rtvDesc.ViewDimension                    = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4112             rtvDesc.Texture2DMSArray.FirstArraySlice = layer;
4113             rtvDesc.Texture2DMSArray.ArraySize       = numLayers;
4114 
4115             d3d11::RenderTargetView rtv;
4116             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
4117                                                   texture->get(), &rtv));
4118             rtv.setLabels("TexStorage2DMSArray.RenderTargetRTV", &mTextureLabel);
4119 
4120             mRenderTargets[key].reset(new TextureRenderTarget11(
4121                 std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
4122                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, mSamples));
4123         }
4124         else
4125         {
4126             ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
4127 
4128             D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
4129             dsvDesc.Format                           = mFormatInfo.dsvFormat;
4130             dsvDesc.ViewDimension                    = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4131             dsvDesc.Texture2DMSArray.FirstArraySlice = layer;
4132             dsvDesc.Texture2DMSArray.ArraySize       = numLayers;
4133             dsvDesc.Flags                            = 0;
4134 
4135             d3d11::DepthStencilView dsv;
4136             ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), dsvDesc,
4137                                                   texture->get(), &dsv));
4138             dsv.setLabels("TexStorage2DMSArray.RenderTargetDSV", &mTextureLabel);
4139 
4140             mRenderTargets[key].reset(new TextureRenderTarget11(
4141                 std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
4142                 getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, mSamples));
4143         }
4144     }
4145 
4146     ASSERT(outRT);
4147     *outRT = mRenderTargets[key].get();
4148     return angle::Result::Continue;
4149 }
4150 
createSRVForSampler(const gl::Context * context,int baseLevel,int mipLevels,DXGI_FORMAT format,const TextureHelper11 & texture,d3d11::SharedSRV * outSRV)4151 angle::Result TextureStorage11_2DMultisampleArray::createSRVForSampler(
4152     const gl::Context *context,
4153     int baseLevel,
4154     int mipLevels,
4155     DXGI_FORMAT format,
4156     const TextureHelper11 &texture,
4157     d3d11::SharedSRV *outSRV)
4158 {
4159     ASSERT(outSRV);
4160 
4161     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
4162     srvDesc.Format                           = format;
4163     srvDesc.ViewDimension                    = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
4164     srvDesc.Texture2DMSArray.FirstArraySlice = 0;
4165     srvDesc.Texture2DMSArray.ArraySize       = mTextureDepth;
4166 
4167     ANGLE_TRY(
4168         mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
4169     outSRV->setLabels("TexStorage2DMSArray.SRV", &mTextureLabel);
4170     return angle::Result::Continue;
4171 }
4172 
getSwizzleTexture(const gl::Context * context,const TextureHelper11 ** outTexture)4173 angle::Result TextureStorage11_2DMultisampleArray::getSwizzleTexture(
4174     const gl::Context *context,
4175     const TextureHelper11 **outTexture)
4176 {
4177     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
4178     return angle::Result::Stop;
4179 }
4180 
getSwizzleRenderTarget(const gl::Context * context,int mipLevel,const d3d11::RenderTargetView ** outRTV)4181 angle::Result TextureStorage11_2DMultisampleArray::getSwizzleRenderTarget(
4182     const gl::Context *context,
4183     int mipLevel,
4184     const d3d11::RenderTargetView **outRTV)
4185 {
4186     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
4187     return angle::Result::Stop;
4188 }
4189 
ensureDropStencilTexture(const gl::Context * context,DropStencil * dropStencilOut)4190 angle::Result TextureStorage11_2DMultisampleArray::ensureDropStencilTexture(
4191     const gl::Context *context,
4192     DropStencil *dropStencilOut)
4193 {
4194     ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
4195     return angle::Result::Stop;
4196 }
4197 
onLabelUpdate()4198 void TextureStorage11_2DMultisampleArray::onLabelUpdate()
4199 {
4200     if (mTexture.valid())
4201     {
4202         mTexture.setKHRDebugLabel(&mTextureLabel);
4203     }
4204 }
4205 
4206 }  // namespace rx
4207