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