1 //
2 // Copyright 2017 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 // ResourceManager11:
7 // Centralized point of allocation for all D3D11 Resources.
8
9 #include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
10
11 #include "common/debug.h"
12 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
13 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
14
15 namespace rx
16 {
17
18 namespace
19 {
20
21 constexpr uint8_t kDebugInitTextureDataValue = 0x48;
22 constexpr FLOAT kDebugColorInitClearValue[4] = {0.3f, 0.5f, 0.7f, 0.5f};
23 constexpr FLOAT kDebugDepthInitValue = 0.2f;
24 constexpr UINT8 kDebugStencilInitValue = 3;
25
26 // A hard limit on buffer size. This works around a problem in the NVIDIA drivers where buffer sizes
27 // close to MAX_UINT would give undefined results. The limit of MAX_UINT/2 should be generous enough
28 // for almost any demanding application.
29 constexpr UINT kMaximumBufferSizeHardLimit = std::numeric_limits<UINT>::max() >> 1;
30
ComputeMippedMemoryUsage(unsigned int width,unsigned int height,unsigned int depth,uint64_t pixelSize,unsigned int mipLevels)31 uint64_t ComputeMippedMemoryUsage(unsigned int width,
32 unsigned int height,
33 unsigned int depth,
34 uint64_t pixelSize,
35 unsigned int mipLevels)
36 {
37 uint64_t sizeSum = 0;
38
39 for (unsigned int level = 0; level < mipLevels; ++level)
40 {
41 unsigned int mipWidth = std::max(width >> level, 1u);
42 unsigned int mipHeight = std::max(height >> level, 1u);
43 unsigned int mipDepth = std::max(depth >> level, 1u);
44 sizeSum += static_cast<uint64_t>(mipWidth * mipHeight * mipDepth) * pixelSize;
45 }
46
47 return sizeSum;
48 }
49
ComputeMemoryUsage(const D3D11_TEXTURE2D_DESC * desc)50 uint64_t ComputeMemoryUsage(const D3D11_TEXTURE2D_DESC *desc)
51 {
52 ASSERT(desc);
53 uint64_t pixelBytes =
54 static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes);
55 return ComputeMippedMemoryUsage(desc->Width, desc->Height, 1, pixelBytes, desc->MipLevels);
56 }
57
ComputeMemoryUsage(const D3D11_TEXTURE3D_DESC * desc)58 uint64_t ComputeMemoryUsage(const D3D11_TEXTURE3D_DESC *desc)
59 {
60 ASSERT(desc);
61 uint64_t pixelBytes =
62 static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes);
63 return ComputeMippedMemoryUsage(desc->Width, desc->Height, desc->Depth, pixelBytes,
64 desc->MipLevels);
65 }
66
ComputeMemoryUsage(const D3D11_BUFFER_DESC * desc)67 uint64_t ComputeMemoryUsage(const D3D11_BUFFER_DESC *desc)
68 {
69 ASSERT(desc);
70 return static_cast<uint64_t>(desc->ByteWidth);
71 }
72
73 template <typename T>
ComputeMemoryUsage(const T * desc)74 uint64_t ComputeMemoryUsage(const T *desc)
75 {
76 return 0;
77 }
78
79 template <ResourceType ResourceT>
ComputeGenericMemoryUsage(ID3D11DeviceChild * genericResource)80 uint64_t ComputeGenericMemoryUsage(ID3D11DeviceChild *genericResource)
81 {
82 auto *typedResource = static_cast<GetD3D11Type<ResourceT> *>(genericResource);
83 GetDescType<ResourceT> desc;
84 typedResource->GetDesc(&desc);
85 return ComputeMemoryUsage(&desc);
86 }
87
ComputeGenericMemoryUsage(ResourceType resourceType,ID3D11DeviceChild * resource)88 uint64_t ComputeGenericMemoryUsage(ResourceType resourceType, ID3D11DeviceChild *resource)
89 {
90 switch (resourceType)
91 {
92 case ResourceType::Texture2D:
93 return ComputeGenericMemoryUsage<ResourceType::Texture2D>(resource);
94 case ResourceType::Texture3D:
95 return ComputeGenericMemoryUsage<ResourceType::Texture3D>(resource);
96 case ResourceType::Buffer:
97 return ComputeGenericMemoryUsage<ResourceType::Buffer>(resource);
98
99 default:
100 return 0;
101 }
102 }
103
CreateResource(ID3D11Device * device,const D3D11_BLEND_DESC * desc,void *,ID3D11BlendState ** blendState)104 HRESULT CreateResource(ID3D11Device *device,
105 const D3D11_BLEND_DESC *desc,
106 void * /*initData*/,
107 ID3D11BlendState **blendState)
108 {
109 return device->CreateBlendState(desc, blendState);
110 }
111
CreateResource(ID3D11Device * device,const D3D11_BUFFER_DESC * desc,const D3D11_SUBRESOURCE_DATA * initData,ID3D11Buffer ** buffer)112 HRESULT CreateResource(ID3D11Device *device,
113 const D3D11_BUFFER_DESC *desc,
114 const D3D11_SUBRESOURCE_DATA *initData,
115 ID3D11Buffer **buffer)
116 {
117 // Force buffers to be limited to a fixed max size.
118 if (desc->ByteWidth > kMaximumBufferSizeHardLimit)
119 {
120 return E_OUTOFMEMORY;
121 }
122
123 return device->CreateBuffer(desc, initData, buffer);
124 }
125
CreateResource(ID3D11Device * device,const ShaderData * desc,void *,ID3D11ComputeShader ** resourceOut)126 HRESULT CreateResource(ID3D11Device *device,
127 const ShaderData *desc,
128 void * /*initData*/,
129 ID3D11ComputeShader **resourceOut)
130 {
131 return device->CreateComputeShader(desc->get(), desc->size(), nullptr, resourceOut);
132 }
133
CreateResource(ID3D11Device * device,const D3D11_DEPTH_STENCIL_DESC * desc,void *,ID3D11DepthStencilState ** resourceOut)134 HRESULT CreateResource(ID3D11Device *device,
135 const D3D11_DEPTH_STENCIL_DESC *desc,
136 void * /*initData*/,
137 ID3D11DepthStencilState **resourceOut)
138 {
139 return device->CreateDepthStencilState(desc, resourceOut);
140 }
141
CreateResource(ID3D11Device * device,const D3D11_DEPTH_STENCIL_VIEW_DESC * desc,ID3D11Resource * resource,ID3D11DepthStencilView ** resourceOut)142 HRESULT CreateResource(ID3D11Device *device,
143 const D3D11_DEPTH_STENCIL_VIEW_DESC *desc,
144 ID3D11Resource *resource,
145 ID3D11DepthStencilView **resourceOut)
146 {
147 return device->CreateDepthStencilView(resource, desc, resourceOut);
148 }
149
CreateResource(ID3D11Device * device,const ShaderData * desc,const std::vector<D3D11_SO_DECLARATION_ENTRY> * initData,ID3D11GeometryShader ** resourceOut)150 HRESULT CreateResource(ID3D11Device *device,
151 const ShaderData *desc,
152 const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
153 ID3D11GeometryShader **resourceOut)
154 {
155 if (initData)
156 {
157 return device->CreateGeometryShaderWithStreamOutput(
158 desc->get(), desc->size(), initData->data(), static_cast<UINT>(initData->size()),
159 nullptr, 0, 0, nullptr, resourceOut);
160 }
161 else
162 {
163 return device->CreateGeometryShader(desc->get(), desc->size(), nullptr, resourceOut);
164 }
165 }
166
CreateResource(ID3D11Device * device,const InputElementArray * desc,const ShaderData * initData,ID3D11InputLayout ** resourceOut)167 HRESULT CreateResource(ID3D11Device *device,
168 const InputElementArray *desc,
169 const ShaderData *initData,
170 ID3D11InputLayout **resourceOut)
171 {
172 return device->CreateInputLayout(desc->get(), static_cast<UINT>(desc->size()), initData->get(),
173 initData->size(), resourceOut);
174 }
175
CreateResource(ID3D11Device * device,const ShaderData * desc,void *,ID3D11PixelShader ** resourceOut)176 HRESULT CreateResource(ID3D11Device *device,
177 const ShaderData *desc,
178 void * /*initData*/,
179 ID3D11PixelShader **resourceOut)
180 {
181 return device->CreatePixelShader(desc->get(), desc->size(), nullptr, resourceOut);
182 }
183
CreateResource(ID3D11Device * device,const D3D11_QUERY_DESC * desc,void *,ID3D11Query ** resourceOut)184 HRESULT CreateResource(ID3D11Device *device,
185 const D3D11_QUERY_DESC *desc,
186 void * /*initData*/,
187 ID3D11Query **resourceOut)
188 {
189 return device->CreateQuery(desc, resourceOut);
190 }
191
CreateResource(ID3D11Device * device,const D3D11_RASTERIZER_DESC * desc,void *,ID3D11RasterizerState ** rasterizerState)192 HRESULT CreateResource(ID3D11Device *device,
193 const D3D11_RASTERIZER_DESC *desc,
194 void * /*initData*/,
195 ID3D11RasterizerState **rasterizerState)
196 {
197 return device->CreateRasterizerState(desc, rasterizerState);
198 }
199
CreateResource(ID3D11Device * device,const D3D11_RENDER_TARGET_VIEW_DESC * desc,ID3D11Resource * resource,ID3D11RenderTargetView ** renderTargetView)200 HRESULT CreateResource(ID3D11Device *device,
201 const D3D11_RENDER_TARGET_VIEW_DESC *desc,
202 ID3D11Resource *resource,
203 ID3D11RenderTargetView **renderTargetView)
204 {
205 return device->CreateRenderTargetView(resource, desc, renderTargetView);
206 }
207
CreateResource(ID3D11Device * device,const D3D11_SAMPLER_DESC * desc,void *,ID3D11SamplerState ** resourceOut)208 HRESULT CreateResource(ID3D11Device *device,
209 const D3D11_SAMPLER_DESC *desc,
210 void * /*initData*/,
211 ID3D11SamplerState **resourceOut)
212 {
213 return device->CreateSamplerState(desc, resourceOut);
214 }
215
CreateResource(ID3D11Device * device,const D3D11_SHADER_RESOURCE_VIEW_DESC * desc,ID3D11Resource * resource,ID3D11ShaderResourceView ** resourceOut)216 HRESULT CreateResource(ID3D11Device *device,
217 const D3D11_SHADER_RESOURCE_VIEW_DESC *desc,
218 ID3D11Resource *resource,
219 ID3D11ShaderResourceView **resourceOut)
220 {
221 return device->CreateShaderResourceView(resource, desc, resourceOut);
222 }
223
CreateResource(ID3D11Device * device,const D3D11_UNORDERED_ACCESS_VIEW_DESC * desc,ID3D11Resource * resource,ID3D11UnorderedAccessView ** resourceOut)224 HRESULT CreateResource(ID3D11Device *device,
225 const D3D11_UNORDERED_ACCESS_VIEW_DESC *desc,
226 ID3D11Resource *resource,
227 ID3D11UnorderedAccessView **resourceOut)
228 {
229 return device->CreateUnorderedAccessView(resource, desc, resourceOut);
230 }
231
CreateResource(ID3D11Device * device,const D3D11_TEXTURE2D_DESC * desc,const D3D11_SUBRESOURCE_DATA * initData,ID3D11Texture2D ** texture)232 HRESULT CreateResource(ID3D11Device *device,
233 const D3D11_TEXTURE2D_DESC *desc,
234 const D3D11_SUBRESOURCE_DATA *initData,
235 ID3D11Texture2D **texture)
236 {
237 return device->CreateTexture2D(desc, initData, texture);
238 }
239
CreateResource(ID3D11Device * device,const D3D11_TEXTURE3D_DESC * desc,const D3D11_SUBRESOURCE_DATA * initData,ID3D11Texture3D ** texture)240 HRESULT CreateResource(ID3D11Device *device,
241 const D3D11_TEXTURE3D_DESC *desc,
242 const D3D11_SUBRESOURCE_DATA *initData,
243 ID3D11Texture3D **texture)
244 {
245 return device->CreateTexture3D(desc, initData, texture);
246 }
247
CreateResource(ID3D11Device * device,const ShaderData * desc,void *,ID3D11VertexShader ** resourceOut)248 HRESULT CreateResource(ID3D11Device *device,
249 const ShaderData *desc,
250 void * /*initData*/,
251 ID3D11VertexShader **resourceOut)
252 {
253 return device->CreateVertexShader(desc->get(), desc->size(), nullptr, resourceOut);
254 }
255
GetTypedDepthStencilFormat(DXGI_FORMAT dxgiFormat)256 DXGI_FORMAT GetTypedDepthStencilFormat(DXGI_FORMAT dxgiFormat)
257 {
258 switch (dxgiFormat)
259 {
260 case DXGI_FORMAT_R16_TYPELESS:
261 return DXGI_FORMAT_D16_UNORM;
262 case DXGI_FORMAT_R24G8_TYPELESS:
263 return DXGI_FORMAT_D24_UNORM_S8_UINT;
264 case DXGI_FORMAT_R32_TYPELESS:
265 return DXGI_FORMAT_D32_FLOAT;
266 case DXGI_FORMAT_R32G8X24_TYPELESS:
267 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
268 default:
269 return dxgiFormat;
270 }
271 }
272
GetTypedColorFormatForClearing(DXGI_FORMAT dxgiFormat)273 DXGI_FORMAT GetTypedColorFormatForClearing(DXGI_FORMAT dxgiFormat)
274 {
275 switch (dxgiFormat)
276 {
277 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
278 return DXGI_FORMAT_R32G32B32A32_FLOAT;
279 case DXGI_FORMAT_R32G32B32_TYPELESS:
280 return DXGI_FORMAT_R32G32B32_FLOAT;
281 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
282 return DXGI_FORMAT_R16G16B16A16_FLOAT;
283 case DXGI_FORMAT_R32G32_TYPELESS:
284 return DXGI_FORMAT_R32G32_FLOAT;
285 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
286 return DXGI_FORMAT_R10G10B10A2_UNORM;
287 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
288 return DXGI_FORMAT_R8G8B8A8_UNORM;
289 case DXGI_FORMAT_R16G16_TYPELESS:
290 return DXGI_FORMAT_R16G16_FLOAT;
291 case DXGI_FORMAT_R32_TYPELESS:
292 return DXGI_FORMAT_R32_FLOAT;
293 case DXGI_FORMAT_R8G8_TYPELESS:
294 return DXGI_FORMAT_R8G8_UNORM;
295 case DXGI_FORMAT_R16_TYPELESS:
296 return DXGI_FORMAT_R16_FLOAT;
297 case DXGI_FORMAT_R8_TYPELESS:
298 return DXGI_FORMAT_R8_UNORM;
299 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
300 return DXGI_FORMAT_B8G8R8A8_UNORM;
301 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
302 return DXGI_FORMAT_B8G8R8X8_UNORM;
303 case DXGI_FORMAT_BC1_TYPELESS:
304 case DXGI_FORMAT_BC2_TYPELESS:
305 case DXGI_FORMAT_BC3_TYPELESS:
306 case DXGI_FORMAT_BC4_TYPELESS:
307 case DXGI_FORMAT_BC5_TYPELESS:
308 case DXGI_FORMAT_BC6H_TYPELESS:
309 case DXGI_FORMAT_BC7_TYPELESS:
310 case DXGI_FORMAT_R32G8X24_TYPELESS:
311 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
312 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
313 case DXGI_FORMAT_R24G8_TYPELESS:
314 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
315 case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
316 UNREACHABLE();
317 [[fallthrough]];
318 default:
319 return dxgiFormat;
320 }
321 }
322
323 template <typename DescT, typename ResourceT>
ClearResource(d3d::Context * context,Renderer11 * renderer,const DescT * desc,ResourceT * texture)324 angle::Result ClearResource(d3d::Context *context,
325 Renderer11 *renderer,
326 const DescT *desc,
327 ResourceT *texture)
328 {
329 // No-op.
330 return angle::Result::Continue;
331 }
332
333 template <>
ClearResource(d3d::Context * context,Renderer11 * renderer,const D3D11_TEXTURE2D_DESC * desc,ID3D11Texture2D * texture)334 angle::Result ClearResource(d3d::Context *context,
335 Renderer11 *renderer,
336 const D3D11_TEXTURE2D_DESC *desc,
337 ID3D11Texture2D *texture)
338 {
339 ID3D11DeviceContext *deviceContext = renderer->getDeviceContext();
340
341 if ((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) != 0)
342 {
343 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
344 dsvDesc.Flags = 0;
345 dsvDesc.Format = GetTypedDepthStencilFormat(desc->Format);
346
347 const auto &format = d3d11_angle::GetFormat(dsvDesc.Format);
348 UINT clearFlags = (format.depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
349 (format.stencilBits > 0 ? D3D11_CLEAR_STENCIL : 0);
350
351 // Must process each mip level individually.
352 for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
353 {
354 if (desc->SampleDesc.Count == 0)
355 {
356 dsvDesc.Texture2D.MipSlice = mipLevel;
357 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
358 }
359 else
360 {
361 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
362 }
363
364 d3d11::DepthStencilView dsv;
365 ANGLE_TRY(renderer->allocateResource(context, dsvDesc, texture, &dsv));
366
367 deviceContext->ClearDepthStencilView(dsv.get(), clearFlags, kDebugDepthInitValue,
368 kDebugStencilInitValue);
369 }
370 }
371 else
372 {
373 ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
374 DXGI_FORMAT formatForClearing = GetTypedColorFormatForClearing(desc->Format);
375 if (formatForClearing != desc->Format || desc->MipLevels > 1)
376 {
377 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
378 rtvDesc.Format = formatForClearing;
379 if (desc->SampleDesc.Count <= 1)
380 {
381 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
382 }
383 else
384 {
385 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
386 ASSERT(desc->MipLevels == 1);
387 }
388 for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
389 {
390 d3d11::RenderTargetView rtv;
391 if (rtvDesc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2D)
392 {
393 rtvDesc.Texture2D.MipSlice = mipLevel;
394 }
395 ANGLE_TRY(renderer->allocateResource(context, rtvDesc, texture, &rtv));
396 deviceContext->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
397 }
398 }
399 else
400 {
401 d3d11::RenderTargetView rtv;
402 ANGLE_TRY(renderer->allocateResourceNoDesc(context, texture, &rtv));
403 deviceContext->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
404 }
405 }
406
407 return angle::Result::Continue;
408 }
409
410 template <>
ClearResource(d3d::Context * context,Renderer11 * renderer,const D3D11_TEXTURE3D_DESC * desc,ID3D11Texture3D * texture)411 angle::Result ClearResource(d3d::Context *context,
412 Renderer11 *renderer,
413 const D3D11_TEXTURE3D_DESC *desc,
414 ID3D11Texture3D *texture)
415 {
416 ID3D11DeviceContext *deviceContext = renderer->getDeviceContext();
417
418 ASSERT((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) == 0);
419 ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
420
421 DXGI_FORMAT formatForClearing = GetTypedColorFormatForClearing(desc->Format);
422 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
423 rtvDesc.Format = formatForClearing;
424 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
425 rtvDesc.Texture3D.WSize = 1;
426 UINT depth = desc->Depth;
427 for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
428 {
429 rtvDesc.Texture3D.MipSlice = mipLevel;
430 for (UINT w = 0; w < depth; ++w)
431 {
432 rtvDesc.Texture3D.FirstWSlice = w;
433 d3d11::RenderTargetView rtv;
434 ANGLE_TRY(renderer->allocateResource(context, rtvDesc, texture, &rtv));
435 deviceContext->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
436 }
437 depth /= 2;
438 }
439
440 return angle::Result::Continue;
441 }
442
443 #define ANGLE_RESOURCE_STRINGIFY_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
444 "Error allocating " #RESTYPE,
445
446 constexpr std::array<const char *, NumResourceTypes> kResourceTypeErrors = {
447 {ANGLE_RESOURCE_TYPE_OP(Stringify, ANGLE_RESOURCE_STRINGIFY_OP)}};
448 static_assert(kResourceTypeErrors[NumResourceTypes - 1] != nullptr,
449 "All members must be initialized.");
450
451 } // anonymous namespace
452
453 // ResourceManager11 Implementation.
ResourceManager11()454 ResourceManager11::ResourceManager11() : mInitializeAllocations(false)
455 {
456 for (auto &count : mAllocatedResourceCounts)
457 {
458 count = 0;
459 }
460 for (auto &memorySize : mAllocatedResourceDeviceMemory)
461 {
462 memorySize = 0;
463 }
464 }
465
~ResourceManager11()466 ResourceManager11::~ResourceManager11()
467 {
468 for (size_t count : mAllocatedResourceCounts)
469 {
470 ASSERT(count == 0);
471 }
472
473 for (uint64_t memorySize : mAllocatedResourceDeviceMemory)
474 {
475 ASSERT(memorySize == 0);
476 }
477 }
478
479 template <typename T>
allocate(d3d::Context * context,Renderer11 * renderer,const GetDescFromD3D11<T> * desc,GetInitDataFromD3D11<T> * initData,Resource11<T> * resourceOut)480 angle::Result ResourceManager11::allocate(d3d::Context *context,
481 Renderer11 *renderer,
482 const GetDescFromD3D11<T> *desc,
483 GetInitDataFromD3D11<T> *initData,
484 Resource11<T> *resourceOut)
485 {
486 ID3D11Device *device = renderer->getDevice();
487 T *resource = nullptr;
488
489 GetInitDataFromD3D11<T> *shadowInitData = initData;
490 if (!shadowInitData && mInitializeAllocations)
491 {
492 shadowInitData = createInitDataIfNeeded<T>(desc);
493 }
494
495 HRESULT hr = CreateResource(device, desc, shadowInitData, &resource);
496 ANGLE_TRY_HR(context, hr, kResourceTypeErrors[ResourceTypeIndex<T>()]);
497
498 if (!shadowInitData && mInitializeAllocations)
499 {
500 ANGLE_TRY(ClearResource(context, renderer, desc, resource));
501 }
502
503 ASSERT(resource);
504 incrResource(GetResourceTypeFromD3D11<T>(), ComputeMemoryUsage(desc));
505 *resourceOut = std::move(Resource11<T>(resource, this));
506 return angle::Result::Continue;
507 }
508
incrResource(ResourceType resourceType,uint64_t memorySize)509 void ResourceManager11::incrResource(ResourceType resourceType, uint64_t memorySize)
510 {
511 size_t typeIndex = ResourceTypeIndex(resourceType);
512
513 mAllocatedResourceCounts[typeIndex]++;
514 mAllocatedResourceDeviceMemory[typeIndex] += memorySize;
515
516 // This checks for integer overflow.
517 ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
518 ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
519 }
520
decrResource(ResourceType resourceType,uint64_t memorySize)521 void ResourceManager11::decrResource(ResourceType resourceType, uint64_t memorySize)
522 {
523 size_t typeIndex = ResourceTypeIndex(resourceType);
524
525 ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
526 mAllocatedResourceCounts[typeIndex]--;
527 ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
528 mAllocatedResourceDeviceMemory[typeIndex] -= memorySize;
529 }
530
onReleaseGeneric(ResourceType resourceType,ID3D11DeviceChild * resource)531 void ResourceManager11::onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource)
532 {
533 ASSERT(resource);
534 decrResource(resourceType, ComputeGenericMemoryUsage(resourceType, resource));
535 }
536
537 template <>
createInitDataIfNeeded(const D3D11_TEXTURE2D_DESC * desc)538 const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture2D>(
539 const D3D11_TEXTURE2D_DESC *desc)
540 {
541 ASSERT(desc);
542
543 if ((desc->BindFlags & (D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_RENDER_TARGET)) != 0)
544 {
545 // This will be done using ClearView methods.
546 return nullptr;
547 }
548
549 size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
550 if (mZeroMemory.size() < requiredSize)
551 {
552 if (!mZeroMemory.resize(requiredSize))
553 {
554 ERR() << "Failed to allocate D3D texture initialization data.";
555 return nullptr;
556 }
557 mZeroMemory.fill(kDebugInitTextureDataValue);
558 }
559
560 const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
561
562 UINT subresourceCount = desc->MipLevels * desc->ArraySize;
563 if (mShadowInitData.size() < subresourceCount)
564 {
565 mShadowInitData.resize(subresourceCount);
566 }
567
568 for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
569 {
570 for (UINT arrayIndex = 0; arrayIndex < desc->ArraySize; ++arrayIndex)
571 {
572 UINT subresourceIndex = D3D11CalcSubresource(mipLevel, arrayIndex, desc->MipLevels);
573 D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
574
575 UINT levelWidth = std::max(desc->Width >> mipLevel, 1u);
576 UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
577
578 data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes;
579 data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
580 data->pSysMem = mZeroMemory.data();
581 }
582 }
583
584 return mShadowInitData.data();
585 }
586
587 template <>
createInitDataIfNeeded(const D3D11_TEXTURE3D_DESC * desc)588 const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture3D>(
589 const D3D11_TEXTURE3D_DESC *desc)
590 {
591 ASSERT(desc);
592
593 if ((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0)
594 {
595 // This will be done using ClearView methods.
596 return nullptr;
597 }
598
599 size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
600 if (mZeroMemory.size() < requiredSize)
601 {
602 if (!mZeroMemory.resize(requiredSize))
603 {
604 ERR() << "Failed to allocate D3D texture initialization data.";
605 return nullptr;
606 }
607 mZeroMemory.fill(kDebugInitTextureDataValue);
608 }
609
610 const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
611
612 UINT subresourceCount = desc->MipLevels;
613 if (mShadowInitData.size() < subresourceCount)
614 {
615 mShadowInitData.resize(subresourceCount);
616 }
617
618 for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
619 {
620 UINT subresourceIndex = D3D11CalcSubresource(mipLevel, 0, desc->MipLevels);
621 D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
622
623 UINT levelWidth = std::max(desc->Width >> mipLevel, 1u);
624 UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
625
626 data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes;
627 data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
628 data->pSysMem = mZeroMemory.data();
629 }
630
631 return mShadowInitData.data();
632 }
633
634 template <typename T>
createInitDataIfNeeded(const GetDescFromD3D11<T> * desc)635 GetInitDataFromD3D11<T> *ResourceManager11::createInitDataIfNeeded(const GetDescFromD3D11<T> *desc)
636 {
637 // No-op.
638 return nullptr;
639 }
640
setAllocationsInitialized(bool initialize)641 void ResourceManager11::setAllocationsInitialized(bool initialize)
642 {
643 mInitializeAllocations = initialize;
644 }
645
646 #define ANGLE_INSTANTIATE_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
647 \
648 template angle::Result ResourceManager11::allocate( \
649 d3d::Context *, Renderer11 *, const DESCTYPE *, INITDATATYPE *, Resource11<D3D11TYPE> *);
650
651 ANGLE_RESOURCE_TYPE_OP(Instantitate, ANGLE_INSTANTIATE_OP)
652 } // namespace rx
653