tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ResourceManager11.cpp (19000B)


      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 
     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 
     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 
     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 
     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>
     74 uint64_t ComputeMemoryUsage(const T *desc)
     75 {
     76    return 0;
     77 }
     78 
     79 template <ResourceType ResourceT>
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    273 template <typename DescT, typename ResourceT>
    274 angle::Result ClearResource(d3d::Context *context,
    275                            Renderer11 *renderer,
    276                            const DescT *desc,
    277                            ResourceT *texture)
    278 {
    279    // No-op.
    280    return angle::Result::Continue;
    281 }
    282 
    283 template <>
    284 angle::Result ClearResource(d3d::Context *context,
    285                            Renderer11 *renderer,
    286                            const D3D11_TEXTURE2D_DESC *desc,
    287                            ID3D11Texture2D *texture)
    288 {
    289    ID3D11DeviceContext *deviceContext = renderer->getDeviceContext();
    290 
    291    if ((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) != 0)
    292    {
    293        D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
    294        dsvDesc.Flags  = 0;
    295        dsvDesc.Format = GetTypedDepthStencilFormat(desc->Format);
    296 
    297        const auto &format = d3d11_angle::GetFormat(dsvDesc.Format);
    298        UINT clearFlags    = (format.depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
    299                          (format.stencilBits > 0 ? D3D11_CLEAR_STENCIL : 0);
    300 
    301        // Must process each mip level individually.
    302        for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
    303        {
    304            if (desc->SampleDesc.Count == 0)
    305            {
    306                dsvDesc.Texture2D.MipSlice = mipLevel;
    307                dsvDesc.ViewDimension      = D3D11_DSV_DIMENSION_TEXTURE2D;
    308            }
    309            else
    310            {
    311                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
    312            }
    313 
    314            d3d11::DepthStencilView dsv;
    315            ANGLE_TRY(renderer->allocateResource(context, dsvDesc, texture, &dsv));
    316 
    317            deviceContext->ClearDepthStencilView(dsv.get(), clearFlags, kDebugDepthInitValue,
    318                                                 kDebugStencilInitValue);
    319        }
    320    }
    321    else
    322    {
    323        ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
    324        d3d11::RenderTargetView rtv;
    325        ANGLE_TRY(renderer->allocateResourceNoDesc(context, texture, &rtv));
    326 
    327        deviceContext->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
    328    }
    329 
    330    return angle::Result::Continue;
    331 }
    332 
    333 template <>
    334 angle::Result ClearResource(d3d::Context *context,
    335                            Renderer11 *renderer,
    336                            const D3D11_TEXTURE3D_DESC *desc,
    337                            ID3D11Texture3D *texture)
    338 {
    339    ID3D11DeviceContext *deviceContext = renderer->getDeviceContext();
    340 
    341    ASSERT((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) == 0);
    342    ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
    343 
    344    d3d11::RenderTargetView rtv;
    345    ANGLE_TRY(renderer->allocateResourceNoDesc(context, texture, &rtv));
    346 
    347    deviceContext->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
    348    return angle::Result::Continue;
    349 }
    350 
    351 #define ANGLE_RESOURCE_STRINGIFY_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
    352    "Error allocating " #RESTYPE,
    353 
    354 constexpr std::array<const char *, NumResourceTypes> kResourceTypeErrors = {
    355    {ANGLE_RESOURCE_TYPE_OP(Stringify, ANGLE_RESOURCE_STRINGIFY_OP)}};
    356 static_assert(kResourceTypeErrors[NumResourceTypes - 1] != nullptr,
    357              "All members must be initialized.");
    358 
    359 }  // anonymous namespace
    360 
    361 // ResourceManager11 Implementation.
    362 ResourceManager11::ResourceManager11() : mInitializeAllocations(false)
    363 {
    364    for (auto &count : mAllocatedResourceCounts)
    365    {
    366        count = 0;
    367    }
    368    for (auto &memorySize : mAllocatedResourceDeviceMemory)
    369    {
    370        memorySize = 0;
    371    }
    372 }
    373 
    374 ResourceManager11::~ResourceManager11()
    375 {
    376    for (size_t count : mAllocatedResourceCounts)
    377    {
    378        ASSERT(count == 0);
    379    }
    380 
    381    for (uint64_t memorySize : mAllocatedResourceDeviceMemory)
    382    {
    383        ASSERT(memorySize == 0);
    384    }
    385 }
    386 
    387 template <typename T>
    388 angle::Result ResourceManager11::allocate(d3d::Context *context,
    389                                          Renderer11 *renderer,
    390                                          const GetDescFromD3D11<T> *desc,
    391                                          GetInitDataFromD3D11<T> *initData,
    392                                          Resource11<T> *resourceOut)
    393 {
    394    ID3D11Device *device = renderer->getDevice();
    395    T *resource          = nullptr;
    396 
    397    GetInitDataFromD3D11<T> *shadowInitData = initData;
    398    if (!shadowInitData && mInitializeAllocations)
    399    {
    400        shadowInitData = createInitDataIfNeeded<T>(desc);
    401    }
    402 
    403    HRESULT hr = CreateResource(device, desc, shadowInitData, &resource);
    404    ANGLE_TRY_HR(context, hr, kResourceTypeErrors[ResourceTypeIndex<T>()]);
    405 
    406    if (!shadowInitData && mInitializeAllocations)
    407    {
    408        ANGLE_TRY(ClearResource(context, renderer, desc, resource));
    409    }
    410 
    411    ASSERT(resource);
    412    incrResource(GetResourceTypeFromD3D11<T>(), ComputeMemoryUsage(desc));
    413    *resourceOut = std::move(Resource11<T>(resource, this));
    414    return angle::Result::Continue;
    415 }
    416 
    417 void ResourceManager11::incrResource(ResourceType resourceType, uint64_t memorySize)
    418 {
    419    size_t typeIndex = ResourceTypeIndex(resourceType);
    420 
    421    mAllocatedResourceCounts[typeIndex]++;
    422    mAllocatedResourceDeviceMemory[typeIndex] += memorySize;
    423 
    424    // This checks for integer overflow.
    425    ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
    426    ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
    427 }
    428 
    429 void ResourceManager11::decrResource(ResourceType resourceType, uint64_t memorySize)
    430 {
    431    size_t typeIndex = ResourceTypeIndex(resourceType);
    432 
    433    ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
    434    mAllocatedResourceCounts[typeIndex]--;
    435    ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
    436    mAllocatedResourceDeviceMemory[typeIndex] -= memorySize;
    437 }
    438 
    439 void ResourceManager11::onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource)
    440 {
    441    ASSERT(resource);
    442    decrResource(resourceType, ComputeGenericMemoryUsage(resourceType, resource));
    443 }
    444 
    445 template <>
    446 const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture2D>(
    447    const D3D11_TEXTURE2D_DESC *desc)
    448 {
    449    ASSERT(desc);
    450 
    451    if ((desc->BindFlags & (D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_RENDER_TARGET)) != 0)
    452    {
    453        // This will be done using ClearView methods.
    454        return nullptr;
    455    }
    456 
    457    size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
    458    if (mZeroMemory.size() < requiredSize)
    459    {
    460        if (!mZeroMemory.resize(requiredSize))
    461        {
    462            ERR() << "Failed to allocate D3D texture initialization data.";
    463            return nullptr;
    464        }
    465        mZeroMemory.fill(kDebugInitTextureDataValue);
    466    }
    467 
    468    const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
    469 
    470    UINT subresourceCount = desc->MipLevels * desc->ArraySize;
    471    if (mShadowInitData.size() < subresourceCount)
    472    {
    473        mShadowInitData.resize(subresourceCount);
    474    }
    475 
    476    for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
    477    {
    478        for (UINT arrayIndex = 0; arrayIndex < desc->ArraySize; ++arrayIndex)
    479        {
    480            UINT subresourceIndex = D3D11CalcSubresource(mipLevel, arrayIndex, desc->MipLevels);
    481            D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
    482 
    483            UINT levelWidth  = std::max(desc->Width >> mipLevel, 1u);
    484            UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
    485 
    486            data->SysMemPitch      = levelWidth * formatSizeInfo.pixelBytes;
    487            data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
    488            data->pSysMem          = mZeroMemory.data();
    489        }
    490    }
    491 
    492    return mShadowInitData.data();
    493 }
    494 
    495 template <>
    496 const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture3D>(
    497    const D3D11_TEXTURE3D_DESC *desc)
    498 {
    499    ASSERT(desc);
    500 
    501    if ((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0)
    502    {
    503        // This will be done using ClearView methods.
    504        return nullptr;
    505    }
    506 
    507    size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
    508    if (mZeroMemory.size() < requiredSize)
    509    {
    510        if (!mZeroMemory.resize(requiredSize))
    511        {
    512            ERR() << "Failed to allocate D3D texture initialization data.";
    513            return nullptr;
    514        }
    515        mZeroMemory.fill(kDebugInitTextureDataValue);
    516    }
    517 
    518    const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
    519 
    520    UINT subresourceCount = desc->MipLevels;
    521    if (mShadowInitData.size() < subresourceCount)
    522    {
    523        mShadowInitData.resize(subresourceCount);
    524    }
    525 
    526    for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
    527    {
    528        UINT subresourceIndex        = D3D11CalcSubresource(mipLevel, 0, desc->MipLevels);
    529        D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
    530 
    531        UINT levelWidth  = std::max(desc->Width >> mipLevel, 1u);
    532        UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
    533 
    534        data->SysMemPitch      = levelWidth * formatSizeInfo.pixelBytes;
    535        data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
    536        data->pSysMem          = mZeroMemory.data();
    537    }
    538 
    539    return mShadowInitData.data();
    540 }
    541 
    542 template <typename T>
    543 GetInitDataFromD3D11<T> *ResourceManager11::createInitDataIfNeeded(const GetDescFromD3D11<T> *desc)
    544 {
    545    // No-op.
    546    return nullptr;
    547 }
    548 
    549 void ResourceManager11::setAllocationsInitialized(bool initialize)
    550 {
    551    mInitializeAllocations = initialize;
    552 }
    553 
    554 #define ANGLE_INSTANTIATE_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
    555                                                                               \
    556    template angle::Result ResourceManager11::allocate(                        \
    557        d3d::Context *, Renderer11 *, const DESCTYPE *, INITDATATYPE *, Resource11<D3D11TYPE> *);
    558 
    559 ANGLE_RESOURCE_TYPE_OP(Instantitate, ANGLE_INSTANTIATE_OP)
    560 }  // namespace rx