• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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