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 ©Area)
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 ®ion)
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