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