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
ComputeMippedMemoryUsage(unsigned int width,unsigned int height,unsigned int depth,uint64_t pixelSize,unsigned int mipLevels)26 uint64_t ComputeMippedMemoryUsage(unsigned int width,
27 unsigned int height,
28 unsigned int depth,
29 uint64_t pixelSize,
30 unsigned int mipLevels)
31 {
32 uint64_t sizeSum = 0;
33
34 for (unsigned int level = 0; level < mipLevels; ++level)
35 {
36 unsigned int mipWidth = std::max(width >> level, 1u);
37 unsigned int mipHeight = std::max(height >> level, 1u);
38 unsigned int mipDepth = std::max(depth >> level, 1u);
39 sizeSum += static_cast<uint64_t>(mipWidth * mipHeight * mipDepth) * pixelSize;
40 }
41
42 return sizeSum;
43 }
44
ComputeMemoryUsage(const D3D11_TEXTURE2D_DESC * desc)45 uint64_t ComputeMemoryUsage(const D3D11_TEXTURE2D_DESC *desc)
46 {
47 ASSERT(desc);
48 uint64_t pixelBytes =
49 static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes);
50 return ComputeMippedMemoryUsage(desc->Width, desc->Height, 1, pixelBytes, desc->MipLevels);
51 }
52
ComputeMemoryUsage(const D3D11_TEXTURE3D_DESC * desc)53 uint64_t ComputeMemoryUsage(const D3D11_TEXTURE3D_DESC *desc)
54 {
55 ASSERT(desc);
56 uint64_t pixelBytes =
57 static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes);
58 return ComputeMippedMemoryUsage(desc->Width, desc->Height, desc->Depth, pixelBytes,
59 desc->MipLevels);
60 }
61
ComputeMemoryUsage(const D3D11_BUFFER_DESC * desc)62 uint64_t ComputeMemoryUsage(const D3D11_BUFFER_DESC *desc)
63 {
64 ASSERT(desc);
65 return static_cast<uint64_t>(desc->ByteWidth);
66 }
67
68 template <typename T>
ComputeMemoryUsage(const T * desc)69 uint64_t ComputeMemoryUsage(const T *desc)
70 {
71 return 0;
72 }
73
74 template <ResourceType ResourceT>
ComputeGenericMemoryUsage(ID3D11DeviceChild * genericResource)75 uint64_t ComputeGenericMemoryUsage(ID3D11DeviceChild *genericResource)
76 {
77 auto *typedResource = static_cast<GetD3D11Type<ResourceT> *>(genericResource);
78 GetDescType<ResourceT> desc;
79 typedResource->GetDesc(&desc);
80 return ComputeMemoryUsage(&desc);
81 }
82
ComputeGenericMemoryUsage(ResourceType resourceType,ID3D11DeviceChild * resource)83 uint64_t ComputeGenericMemoryUsage(ResourceType resourceType, ID3D11DeviceChild *resource)
84 {
85 switch (resourceType)
86 {
87 case ResourceType::Texture2D:
88 return ComputeGenericMemoryUsage<ResourceType::Texture2D>(resource);
89 case ResourceType::Texture3D:
90 return ComputeGenericMemoryUsage<ResourceType::Texture3D>(resource);
91 case ResourceType::Buffer:
92 return ComputeGenericMemoryUsage<ResourceType::Buffer>(resource);
93
94 default:
95 return 0;
96 }
97 }
98
CreateResource(ID3D11Device * device,const D3D11_BLEND_DESC * desc,void *,ID3D11BlendState ** blendState)99 HRESULT CreateResource(ID3D11Device *device,
100 const D3D11_BLEND_DESC *desc,
101 void * /*initData*/,
102 ID3D11BlendState **blendState)
103 {
104 return device->CreateBlendState(desc, blendState);
105 }
106
CreateResource(ID3D11Device * device,const D3D11_BUFFER_DESC * desc,const D3D11_SUBRESOURCE_DATA * initData,ID3D11Buffer ** buffer)107 HRESULT CreateResource(ID3D11Device *device,
108 const D3D11_BUFFER_DESC *desc,
109 const D3D11_SUBRESOURCE_DATA *initData,
110 ID3D11Buffer **buffer)
111 {
112 return device->CreateBuffer(desc, initData, buffer);
113 }
114
CreateResource(ID3D11Device * device,const ShaderData * desc,void *,ID3D11ComputeShader ** resourceOut)115 HRESULT CreateResource(ID3D11Device *device,
116 const ShaderData *desc,
117 void * /*initData*/,
118 ID3D11ComputeShader **resourceOut)
119 {
120 return device->CreateComputeShader(desc->get(), desc->size(), nullptr, resourceOut);
121 }
122
CreateResource(ID3D11Device * device,const D3D11_DEPTH_STENCIL_DESC * desc,void *,ID3D11DepthStencilState ** resourceOut)123 HRESULT CreateResource(ID3D11Device *device,
124 const D3D11_DEPTH_STENCIL_DESC *desc,
125 void * /*initData*/,
126 ID3D11DepthStencilState **resourceOut)
127 {
128 return device->CreateDepthStencilState(desc, resourceOut);
129 }
130
CreateResource(ID3D11Device * device,const D3D11_DEPTH_STENCIL_VIEW_DESC * desc,ID3D11Resource * resource,ID3D11DepthStencilView ** resourceOut)131 HRESULT CreateResource(ID3D11Device *device,
132 const D3D11_DEPTH_STENCIL_VIEW_DESC *desc,
133 ID3D11Resource *resource,
134 ID3D11DepthStencilView **resourceOut)
135 {
136 return device->CreateDepthStencilView(resource, desc, resourceOut);
137 }
138
CreateResource(ID3D11Device * device,const ShaderData * desc,const std::vector<D3D11_SO_DECLARATION_ENTRY> * initData,ID3D11GeometryShader ** resourceOut)139 HRESULT CreateResource(ID3D11Device *device,
140 const ShaderData *desc,
141 const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
142 ID3D11GeometryShader **resourceOut)
143 {
144 if (initData)
145 {
146 return device->CreateGeometryShaderWithStreamOutput(
147 desc->get(), desc->size(), initData->data(), static_cast<UINT>(initData->size()),
148 nullptr, 0, 0, nullptr, resourceOut);
149 }
150 else
151 {
152 return device->CreateGeometryShader(desc->get(), desc->size(), nullptr, resourceOut);
153 }
154 }
155
CreateResource(ID3D11Device * device,const InputElementArray * desc,const ShaderData * initData,ID3D11InputLayout ** resourceOut)156 HRESULT CreateResource(ID3D11Device *device,
157 const InputElementArray *desc,
158 const ShaderData *initData,
159 ID3D11InputLayout **resourceOut)
160 {
161 return device->CreateInputLayout(desc->get(), static_cast<UINT>(desc->size()), initData->get(),
162 initData->size(), resourceOut);
163 }
164
CreateResource(ID3D11Device * device,const ShaderData * desc,void *,ID3D11PixelShader ** resourceOut)165 HRESULT CreateResource(ID3D11Device *device,
166 const ShaderData *desc,
167 void * /*initData*/,
168 ID3D11PixelShader **resourceOut)
169 {
170 return device->CreatePixelShader(desc->get(), desc->size(), nullptr, resourceOut);
171 }
172
CreateResource(ID3D11Device * device,const D3D11_QUERY_DESC * desc,void *,ID3D11Query ** resourceOut)173 HRESULT CreateResource(ID3D11Device *device,
174 const D3D11_QUERY_DESC *desc,
175 void * /*initData*/,
176 ID3D11Query **resourceOut)
177 {
178 return device->CreateQuery(desc, resourceOut);
179 }
180
CreateResource(ID3D11Device * device,const D3D11_RASTERIZER_DESC * desc,void *,ID3D11RasterizerState ** rasterizerState)181 HRESULT CreateResource(ID3D11Device *device,
182 const D3D11_RASTERIZER_DESC *desc,
183 void * /*initData*/,
184 ID3D11RasterizerState **rasterizerState)
185 {
186 return device->CreateRasterizerState(desc, rasterizerState);
187 }
188
CreateResource(ID3D11Device * device,const D3D11_RENDER_TARGET_VIEW_DESC * desc,ID3D11Resource * resource,ID3D11RenderTargetView ** renderTargetView)189 HRESULT CreateResource(ID3D11Device *device,
190 const D3D11_RENDER_TARGET_VIEW_DESC *desc,
191 ID3D11Resource *resource,
192 ID3D11RenderTargetView **renderTargetView)
193 {
194 return device->CreateRenderTargetView(resource, desc, renderTargetView);
195 }
196
CreateResource(ID3D11Device * device,const D3D11_SAMPLER_DESC * desc,void *,ID3D11SamplerState ** resourceOut)197 HRESULT CreateResource(ID3D11Device *device,
198 const D3D11_SAMPLER_DESC *desc,
199 void * /*initData*/,
200 ID3D11SamplerState **resourceOut)
201 {
202 return device->CreateSamplerState(desc, resourceOut);
203 }
204
CreateResource(ID3D11Device * device,const D3D11_SHADER_RESOURCE_VIEW_DESC * desc,ID3D11Resource * resource,ID3D11ShaderResourceView ** resourceOut)205 HRESULT CreateResource(ID3D11Device *device,
206 const D3D11_SHADER_RESOURCE_VIEW_DESC *desc,
207 ID3D11Resource *resource,
208 ID3D11ShaderResourceView **resourceOut)
209 {
210 return device->CreateShaderResourceView(resource, desc, resourceOut);
211 }
212
CreateResource(ID3D11Device * device,const D3D11_TEXTURE2D_DESC * desc,const D3D11_SUBRESOURCE_DATA * initData,ID3D11Texture2D ** texture)213 HRESULT CreateResource(ID3D11Device *device,
214 const D3D11_TEXTURE2D_DESC *desc,
215 const D3D11_SUBRESOURCE_DATA *initData,
216 ID3D11Texture2D **texture)
217 {
218 return device->CreateTexture2D(desc, initData, texture);
219 }
220
CreateResource(ID3D11Device * device,const D3D11_TEXTURE3D_DESC * desc,const D3D11_SUBRESOURCE_DATA * initData,ID3D11Texture3D ** texture)221 HRESULT CreateResource(ID3D11Device *device,
222 const D3D11_TEXTURE3D_DESC *desc,
223 const D3D11_SUBRESOURCE_DATA *initData,
224 ID3D11Texture3D **texture)
225 {
226 return device->CreateTexture3D(desc, initData, texture);
227 }
228
CreateResource(ID3D11Device * device,const ShaderData * desc,void *,ID3D11VertexShader ** resourceOut)229 HRESULT CreateResource(ID3D11Device *device,
230 const ShaderData *desc,
231 void * /*initData*/,
232 ID3D11VertexShader **resourceOut)
233 {
234 return device->CreateVertexShader(desc->get(), desc->size(), nullptr, resourceOut);
235 }
236
GetTypedDepthStencilFormat(DXGI_FORMAT dxgiFormat)237 DXGI_FORMAT GetTypedDepthStencilFormat(DXGI_FORMAT dxgiFormat)
238 {
239 switch (dxgiFormat)
240 {
241 case DXGI_FORMAT_R16_TYPELESS:
242 return DXGI_FORMAT_D16_UNORM;
243 case DXGI_FORMAT_R24G8_TYPELESS:
244 return DXGI_FORMAT_D24_UNORM_S8_UINT;
245 case DXGI_FORMAT_R32_TYPELESS:
246 return DXGI_FORMAT_D32_FLOAT;
247 case DXGI_FORMAT_R32G8X24_TYPELESS:
248 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
249 default:
250 return dxgiFormat;
251 }
252 }
253
254 template <typename DescT, typename ResourceT>
ClearResource(Renderer11 * renderer,const DescT * desc,ResourceT * texture)255 gl::Error ClearResource(Renderer11 *renderer, const DescT *desc, ResourceT *texture)
256 {
257 // No-op.
258 return gl::NoError();
259 }
260
261 template <>
ClearResource(Renderer11 * renderer,const D3D11_TEXTURE2D_DESC * desc,ID3D11Texture2D * texture)262 gl::Error ClearResource(Renderer11 *renderer,
263 const D3D11_TEXTURE2D_DESC *desc,
264 ID3D11Texture2D *texture)
265 {
266 ID3D11DeviceContext *context = renderer->getDeviceContext();
267
268 if ((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) != 0)
269 {
270 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
271 dsvDesc.Flags = 0;
272 dsvDesc.Format = GetTypedDepthStencilFormat(desc->Format);
273
274 const auto &format = d3d11_angle::GetFormat(dsvDesc.Format);
275 UINT clearFlags = (format.depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
276 (format.stencilBits > 0 ? D3D11_CLEAR_STENCIL : 0);
277
278 // Must process each mip level individually.
279 for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
280 {
281 if (desc->SampleDesc.Count == 0)
282 {
283 dsvDesc.Texture2D.MipSlice = mipLevel;
284 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
285 }
286 else
287 {
288 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
289 }
290
291 d3d11::DepthStencilView dsv;
292 ANGLE_TRY(renderer->allocateResource(dsvDesc, texture, &dsv));
293
294 context->ClearDepthStencilView(dsv.get(), clearFlags, kDebugDepthInitValue,
295 kDebugStencilInitValue);
296 }
297 }
298 else
299 {
300 ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
301 d3d11::RenderTargetView rtv;
302 ANGLE_TRY(renderer->allocateResourceNoDesc(texture, &rtv));
303
304 context->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
305 }
306
307 return gl::NoError();
308 }
309
310 template <>
ClearResource(Renderer11 * renderer,const D3D11_TEXTURE3D_DESC * desc,ID3D11Texture3D * texture)311 gl::Error ClearResource(Renderer11 *renderer,
312 const D3D11_TEXTURE3D_DESC *desc,
313 ID3D11Texture3D *texture)
314 {
315 ID3D11DeviceContext *context = renderer->getDeviceContext();
316
317 ASSERT((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) == 0);
318 ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
319
320 d3d11::RenderTargetView rtv;
321 ANGLE_TRY(renderer->allocateResourceNoDesc(texture, &rtv));
322
323 context->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
324 return gl::NoError();
325 }
326
327 #define ANGLE_RESOURCE_STRINGIFY_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) #RESTYPE,
328
329 constexpr std::array<const char *, NumResourceTypes> kResourceTypeNames = {
330 {ANGLE_RESOURCE_TYPE_OP(Stringify, ANGLE_RESOURCE_STRINGIFY_OP)}};
331 static_assert(kResourceTypeNames[NumResourceTypes - 1] != nullptr,
332 "All members must be initialized.");
333
334 } // anonymous namespace
335
336 // ResourceManager11 Implementation.
ResourceManager11()337 ResourceManager11::ResourceManager11()
338 : mInitializeAllocations(false),
339 mAllocatedResourceCounts({{}}),
340 mAllocatedResourceDeviceMemory({{}})
341 {
342 }
343
~ResourceManager11()344 ResourceManager11::~ResourceManager11()
345 {
346 for (size_t count : mAllocatedResourceCounts)
347 {
348 ASSERT(count == 0);
349 }
350
351 for (uint64_t memorySize : mAllocatedResourceDeviceMemory)
352 {
353 ASSERT(memorySize == 0);
354 }
355 }
356
357 template <typename T>
allocate(Renderer11 * renderer,const GetDescFromD3D11<T> * desc,GetInitDataFromD3D11<T> * initData,Resource11<T> * resourceOut)358 gl::Error ResourceManager11::allocate(Renderer11 *renderer,
359 const GetDescFromD3D11<T> *desc,
360 GetInitDataFromD3D11<T> *initData,
361 Resource11<T> *resourceOut)
362 {
363 ID3D11Device *device = renderer->getDevice();
364 T *resource = nullptr;
365
366 GetInitDataFromD3D11<T> *shadowInitData = initData;
367 if (!shadowInitData && mInitializeAllocations)
368 {
369 shadowInitData = createInitDataIfNeeded<T>(desc);
370 }
371
372 HRESULT hr = CreateResource(device, desc, shadowInitData, &resource);
373 if (FAILED(hr))
374 {
375 ASSERT(!resource);
376 if (d3d11::isDeviceLostError(hr))
377 {
378 renderer->notifyDeviceLost();
379 }
380 return gl::OutOfMemory() << "Error allocating "
381 << std::string(kResourceTypeNames[ResourceTypeIndex<T>()]) << ". "
382 << gl::FmtHR(hr);
383 }
384
385 if (!shadowInitData && mInitializeAllocations)
386 {
387 ANGLE_TRY(ClearResource(renderer, desc, resource));
388 }
389
390 ASSERT(resource);
391 incrResource(GetResourceTypeFromD3D11<T>(), ComputeMemoryUsage(desc));
392 *resourceOut = std::move(Resource11<T>(resource, this));
393 return gl::NoError();
394 }
395
incrResource(ResourceType resourceType,uint64_t memorySize)396 void ResourceManager11::incrResource(ResourceType resourceType, uint64_t memorySize)
397 {
398 size_t typeIndex = ResourceTypeIndex(resourceType);
399
400 mAllocatedResourceCounts[typeIndex]++;
401 mAllocatedResourceDeviceMemory[typeIndex] += memorySize;
402
403 // This checks for integer overflow.
404 ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
405 ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
406 }
407
decrResource(ResourceType resourceType,uint64_t memorySize)408 void ResourceManager11::decrResource(ResourceType resourceType, uint64_t memorySize)
409 {
410 size_t typeIndex = ResourceTypeIndex(resourceType);
411
412 ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
413 mAllocatedResourceCounts[typeIndex]--;
414 ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
415 mAllocatedResourceDeviceMemory[typeIndex] -= memorySize;
416 }
417
onReleaseGeneric(ResourceType resourceType,ID3D11DeviceChild * resource)418 void ResourceManager11::onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource)
419 {
420 ASSERT(resource);
421 decrResource(resourceType, ComputeGenericMemoryUsage(resourceType, resource));
422 }
423
424 template <>
createInitDataIfNeeded(const D3D11_TEXTURE2D_DESC * desc)425 const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture2D>(
426 const D3D11_TEXTURE2D_DESC *desc)
427 {
428 ASSERT(desc);
429
430 if ((desc->BindFlags & (D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_RENDER_TARGET)) != 0)
431 {
432 // This will be done using ClearView methods.
433 return nullptr;
434 }
435
436 size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
437 if (mZeroMemory.size() < requiredSize)
438 {
439 mZeroMemory.resize(requiredSize);
440 mZeroMemory.fill(kDebugInitTextureDataValue);
441 }
442
443 const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
444
445 UINT subresourceCount = desc->MipLevels * desc->ArraySize;
446 if (mShadowInitData.size() < subresourceCount)
447 {
448 mShadowInitData.resize(subresourceCount);
449 }
450
451 for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
452 {
453 for (UINT arrayIndex = 0; arrayIndex < desc->ArraySize; ++arrayIndex)
454 {
455 UINT subresourceIndex = D3D11CalcSubresource(mipLevel, arrayIndex, desc->MipLevels);
456 D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
457
458 UINT levelWidth = std::max(desc->Width >> mipLevel, 1u);
459 UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
460
461 data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes;
462 data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
463 data->pSysMem = mZeroMemory.data();
464 }
465 }
466
467 return mShadowInitData.data();
468 }
469
470 template <>
createInitDataIfNeeded(const D3D11_TEXTURE3D_DESC * desc)471 const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture3D>(
472 const D3D11_TEXTURE3D_DESC *desc)
473 {
474 ASSERT(desc);
475
476 if ((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0)
477 {
478 // This will be done using ClearView methods.
479 return nullptr;
480 }
481
482 size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
483 if (mZeroMemory.size() < requiredSize)
484 {
485 mZeroMemory.resize(requiredSize);
486 mZeroMemory.fill(kDebugInitTextureDataValue);
487 }
488
489 const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
490
491 UINT subresourceCount = desc->MipLevels;
492 if (mShadowInitData.size() < subresourceCount)
493 {
494 mShadowInitData.resize(subresourceCount);
495 }
496
497 for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
498 {
499 UINT subresourceIndex = D3D11CalcSubresource(mipLevel, 0, desc->MipLevels);
500 D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
501
502 UINT levelWidth = std::max(desc->Width >> mipLevel, 1u);
503 UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
504
505 data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes;
506 data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
507 data->pSysMem = mZeroMemory.data();
508 }
509
510 return mShadowInitData.data();
511 }
512
513 template <typename T>
createInitDataIfNeeded(const GetDescFromD3D11<T> * desc)514 GetInitDataFromD3D11<T> *ResourceManager11::createInitDataIfNeeded(const GetDescFromD3D11<T> *desc)
515 {
516 // No-op.
517 return nullptr;
518 }
519
setAllocationsInitialized(bool initialize)520 void ResourceManager11::setAllocationsInitialized(bool initialize)
521 {
522 mInitializeAllocations = initialize;
523 }
524
525 #define ANGLE_INSTANTIATE_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
526 \
527 template \
528 gl::Error \
529 ResourceManager11::allocate(Renderer11 *, const DESCTYPE *, INITDATATYPE *, \
530 Resource11<D3D11TYPE> *);
531
532 ANGLE_RESOURCE_TYPE_OP(Instantitate, ANGLE_INSTANTIATE_OP)
533 } // namespace rx
534