/*
 * Copyright 2020 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/d3d/GrD3DBackendContext.h"
#include "include/gpu/d3d/GrD3DTypes.h"

#include "src/core/SkCompressedDataUtils.h"
#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrStencilSettings.h"
#include "src/gpu/d3d/GrD3DCaps.h"
#include "src/gpu/d3d/GrD3DGpu.h"
#include "src/gpu/d3d/GrD3DRenderTarget.h"
#include "src/gpu/d3d/GrD3DTexture.h"
#include "src/gpu/d3d/GrD3DUtil.h"

GrD3DCaps::GrD3DCaps(const GrContextOptions& contextOptions, IDXGIAdapter1* adapter,
                     ID3D12Device* device)
        : INHERITED(contextOptions) {
    /**************************************************************************
     * GrCaps fields
     **************************************************************************/
    fMipmapSupport = true;   // always available in Direct3D
    fNPOTTextureTileSupport = true;  // available in feature level 10_0 and up
    fReuseScratchTextures = true; //TODO: figure this out
    fGpuTracingSupport = false; //TODO: figure this out
    fOversizedStencilSupport = false; //TODO: figure this out
    fDrawInstancedSupport = true;
    fNativeDrawIndirectSupport = true;

    fSemaphoreSupport = true;
    fFenceSyncSupport = true;
    // TODO: implement these
    fCrossContextTextureSupport = false;
    fHalfFloatVertexAttributeSupport = false;

    // We always copy in/out of a transfer buffer so it's trivial to support row bytes.
    fReadPixelsRowBytesSupport = true;
    fWritePixelsRowBytesSupport = true;

    // TODO: implement these
    fTransferFromBufferToTextureSupport = false;
    fTransferFromSurfaceToBufferSupport = false;

    fMaxRenderTargetSize = 16384;  // minimum required by feature level 11_0
    fMaxTextureSize = 16384;       // minimum required by feature level 11_0

    // TODO: implement
    fDynamicStateArrayGeometryProcessorTextureSupport = false;

    fShaderCaps.reset(new GrShaderCaps(contextOptions));

    this->init(contextOptions, adapter, device);
}

bool GrD3DCaps::canCopyTexture(DXGI_FORMAT dstFormat, int dstSampleCnt,
                               DXGI_FORMAT srcFormat, int srcSampleCnt) const {
    if ((dstSampleCnt > 1 || srcSampleCnt > 1) && dstSampleCnt != srcSampleCnt) {
        return false;
    }

    return srcFormat == dstFormat;
}

bool GrD3DCaps::canCopyAsResolve(DXGI_FORMAT dstFormat, int dstSampleCnt,
                                 DXGI_FORMAT srcFormat, int srcSampleCnt) const {
    // The src surface must be multisampled.
    if (srcSampleCnt <= 1) {
        return false;
    }

    // The dst must not be multisampled.
    if (dstSampleCnt > 1) {
        return false;
    }

    // Surfaces must have the same format.
    if (srcFormat != dstFormat) {
        return false;
    }

    return true;
}

bool GrD3DCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
                                 const SkIRect& srcRect, const SkIPoint& dstPoint) const {
    if (src->isProtected() == GrProtected::kYes && dst->isProtected() != GrProtected::kYes) {
        return false;
    }

    int dstSampleCnt = 0;
    int srcSampleCnt = 0;
    if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
        dstSampleCnt = rtProxy->numSamples();
    }
    if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
        srcSampleCnt = rtProxy->numSamples();
    }
    SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
    SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));

    DXGI_FORMAT dstFormat, srcFormat;
    SkAssertResult(dst->backendFormat().asDxgiFormat(&dstFormat));
    SkAssertResult(src->backendFormat().asDxgiFormat(&srcFormat));

    return this->canCopyTexture(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt) ||
           this->canCopyAsResolve(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt);
}

void GrD3DCaps::init(const GrContextOptions& contextOptions, IDXGIAdapter1* adapter,
                     ID3D12Device* device) {
    D3D_FEATURE_LEVEL featureLevels[] = {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_12_0,
        D3D_FEATURE_LEVEL_12_1,
    };
    D3D12_FEATURE_DATA_FEATURE_LEVELS flDesc = {};
    flDesc.NumFeatureLevels = _countof(featureLevels);
    flDesc.pFeatureLevelsRequested = featureLevels;
    GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &flDesc,
                                                     sizeof(flDesc)));
    // This had better be true
    SkASSERT(flDesc.MaxSupportedFeatureLevel >= D3D_FEATURE_LEVEL_11_0);

    DXGI_ADAPTER_DESC adapterDesc;
    GR_D3D_CALL_ERRCHECK(adapter->GetDesc(&adapterDesc));

    D3D12_FEATURE_DATA_D3D12_OPTIONS optionsDesc;
    GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &optionsDesc,
                                                     sizeof(optionsDesc)));


    // See https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-support
    if (D3D12_RESOURCE_BINDING_TIER_1 == optionsDesc.ResourceBindingTier) {
        fMaxPerStageShaderResourceViews = 128;
        if (D3D_FEATURE_LEVEL_11_0 == flDesc.MaxSupportedFeatureLevel) {
            fMaxPerStageUnorderedAccessViews = 8;
        } else {
            fMaxPerStageUnorderedAccessViews = 64;
        }
    } else {
        // The doc above says "full heap", but practically it seems like it should be
        // limited by the maximum number of samplers in a heap
        fMaxPerStageUnorderedAccessViews = 2032;
        fMaxPerStageShaderResourceViews = 2032;
    }

    this->initGrCaps(optionsDesc, device);
    this->initShaderCaps(adapterDesc.VendorId, optionsDesc);

    this->initFormatTable(adapterDesc, device);
    this->initStencilFormat(device);

    if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
        this->applyDriverCorrectnessWorkarounds(adapterDesc.VendorId);
    }

    this->finishInitialization(contextOptions);
}

void GrD3DCaps::initGrCaps(const D3D12_FEATURE_DATA_D3D12_OPTIONS& optionsDesc,
                           ID3D12Device* device) {
    // We assume a minimum of Shader Model 5.1, which allows at most 32 vertex inputs.
    fMaxVertexAttributes = 32;

    // Can use standard sample locations
    fSampleLocationsSupport = true;

    D3D12_FEATURE_DATA_D3D12_OPTIONS2 options2Desc;
    if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS2, &options2Desc,
                                              sizeof(options2Desc))) &&
        options2Desc.ProgrammableSamplePositionsTier !=
                D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) {
        // We "disable" multisample by colocating all samples at pixel center.
        fMultisampleDisableSupport = true;
    }

    // TODO: It's not clear if this is supported or not.
    fMixedSamplesSupport = false;

    if (D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED !=
            optionsDesc.ConservativeRasterizationTier) {
        fConservativeRasterSupport = true;
    }

    fWireframeSupport = true;

    // Feature level 11_0 and up support up to 16K in texture dimension
    fMaxTextureSize = 16384;
    // There's no specific cap for RT size, so use texture size
    fMaxRenderTargetSize = fMaxTextureSize;
    if (fDriverBugWorkarounds.max_texture_size_limit_4096) {
        fMaxTextureSize = std::min(fMaxTextureSize, 4096);
    }
    // Our render targets are always created with textures as the color
    // attachment, hence this min:
    fMaxRenderTargetSize = fMaxTextureSize;

    fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;

    // Assuming since we will always map in the end to upload the data we might as well just map
    // from the get go. There is no hard data to suggest this is faster or slower.
    fBufferMapThreshold = 0;

    fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag | kAsyncRead_MapFlag;

    fOversizedStencilSupport = true;

    fTwoSidedStencilRefsAndMasksMustMatch = true;

    // Advanced blend modes don't appear to be supported.
}

void GrD3DCaps::initShaderCaps(int vendorID, const D3D12_FEATURE_DATA_D3D12_OPTIONS& optionsDesc) {
    GrShaderCaps* shaderCaps = fShaderCaps.get();
    shaderCaps->fVersionDeclString = "#version 330\n";

    // Shader Model 5 supports all of the following:
    shaderCaps->fUsesPrecisionModifiers = true;
    shaderCaps->fFlatInterpolationSupport = true;
    // Flat interpolation appears to be slow on Qualcomm GPUs. This was tested in GL and is assumed
    // to be true with D3D as well.
    shaderCaps->fPreferFlatInterpolation = kQualcomm_D3DVendor != vendorID;

    shaderCaps->fSampleMaskSupport = true;

    shaderCaps->fShaderDerivativeSupport = true;

    shaderCaps->fGeometryShaderSupport = shaderCaps->fGSInvocationsSupport = true;

    shaderCaps->fDualSourceBlendingSupport = true;

    shaderCaps->fIntegerSupport = true;
    shaderCaps->fVertexIDSupport = true;
    shaderCaps->fFPManipulationSupport = true;

    shaderCaps->fFloatIs32Bits = true;
    shaderCaps->fHalfIs32Bits =
        D3D12_SHADER_MIN_PRECISION_SUPPORT_NONE == optionsDesc.MinPrecisionSupport;

    // See https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-support
    // The maximum number of samplers in a shader-visible descriptor heap is 2048, but
    // 16 of those are reserved for the driver.
    shaderCaps->fMaxFragmentSamplers =
        (D3D12_RESOURCE_BINDING_TIER_1 == optionsDesc.ResourceBindingTier) ? 16 : 2032;
}

void GrD3DCaps::applyDriverCorrectnessWorkarounds(int vendorID) {
    // Nothing yet.
}


bool stencil_format_supported(ID3D12Device* device, DXGI_FORMAT format) {
    D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupportDesc;
    formatSupportDesc.Format = format;
    GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
                                                     &formatSupportDesc,
                                                     sizeof(formatSupportDesc)));
    return SkToBool(D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL & formatSupportDesc.Support1);
}

void GrD3DCaps::initStencilFormat(ID3D12Device* device) {
    if (stencil_format_supported(device, DXGI_FORMAT_D24_UNORM_S8_UINT)) {
        fPreferredStencilFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
    } else {
        SkASSERT(stencil_format_supported(device, DXGI_FORMAT_D32_FLOAT_S8X24_UINT));
        fPreferredStencilFormat = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
    }
}

// These are all the valid DXGI_FORMATs that we support in Skia. They are roughly ordered from most
// frequently used to least to improve look up times in arrays.
static constexpr DXGI_FORMAT kDxgiFormats[] = {
    DXGI_FORMAT_R8G8B8A8_UNORM,
    DXGI_FORMAT_R8_UNORM,
    DXGI_FORMAT_B8G8R8A8_UNORM,
    DXGI_FORMAT_B5G6R5_UNORM,
    DXGI_FORMAT_R16G16B16A16_FLOAT,
    DXGI_FORMAT_R16_FLOAT,
    DXGI_FORMAT_R8G8_UNORM,
    DXGI_FORMAT_R10G10B10A2_UNORM,
    DXGI_FORMAT_B4G4R4A4_UNORM,
    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
    DXGI_FORMAT_BC1_UNORM,
    DXGI_FORMAT_R16_UNORM,
    DXGI_FORMAT_R16G16_UNORM,
    DXGI_FORMAT_R16G16B16A16_UNORM,
    DXGI_FORMAT_R16G16_FLOAT
};

void GrD3DCaps::setColorType(GrColorType colorType, std::initializer_list<DXGI_FORMAT> formats) {
#ifdef SK_DEBUG
    for (size_t i = 0; i < kNumDxgiFormats; ++i) {
        const auto& formatInfo = fFormatTable[i];
        for (int j = 0; j < formatInfo.fColorTypeInfoCount; ++j) {
            const auto& ctInfo = formatInfo.fColorTypeInfos[j];
            if (ctInfo.fColorType == colorType &&
                !SkToBool(ctInfo.fFlags & ColorTypeInfo::kWrappedOnly_Flag)) {
                bool found = false;
                for (auto it = formats.begin(); it != formats.end(); ++it) {
                    if (kDxgiFormats[i] == *it) {
                        found = true;
                    }
                }
                SkASSERT(found);
            }
        }
    }
#endif
    int idx = static_cast<int>(colorType);
    for (auto it = formats.begin(); it != formats.end(); ++it) {
        const auto& info = this->getFormatInfo(*it);
        for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
            if (info.fColorTypeInfos[i].fColorType == colorType) {
                fColorTypeToFormatTable[idx] = *it;
                return;
            }
        }
    }
}

const GrD3DCaps::FormatInfo& GrD3DCaps::getFormatInfo(DXGI_FORMAT format) const {
    GrD3DCaps* nonConstThis = const_cast<GrD3DCaps*>(this);
    return nonConstThis->getFormatInfo(format);
}

GrD3DCaps::FormatInfo& GrD3DCaps::getFormatInfo(DXGI_FORMAT format) {
    static_assert(SK_ARRAY_COUNT(kDxgiFormats) == GrD3DCaps::kNumDxgiFormats,
                  "Size of DXGI_FORMATs array must match static value in header");
    for (size_t i = 0; i < SK_ARRAY_COUNT(kDxgiFormats); ++i) {
        if (kDxgiFormats[i] == format) {
            return fFormatTable[i];
        }
    }
    static FormatInfo kInvalidFormat;
    return kInvalidFormat;
}

void GrD3DCaps::initFormatTable(const DXGI_ADAPTER_DESC& adapterDesc, ID3D12Device* device) {
    static_assert(SK_ARRAY_COUNT(kDxgiFormats) == GrD3DCaps::kNumDxgiFormats,
                  "Size of DXGI_FORMATs array must match static value in header");

    std::fill_n(fColorTypeToFormatTable, kGrColorTypeCnt, DXGI_FORMAT_UNKNOWN);

    // Go through all the formats and init their support surface and data GrColorTypes.
    // Format: DXGI_FORMAT_R8G8B8A8_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kRGBA_8888;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 2;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R8G8B8A8_UNORM, Surface: kRGBA_8888
            {
                constexpr GrColorType ct = GrColorType::kRGBA_8888;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
            // Format: DXGI_FORMAT_R8G8B8A8_UNORM, Surface: kRGB_888x
            {
                constexpr GrColorType ct = GrColorType::kRGB_888x;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
                ctInfo.fReadSwizzle = GrSwizzle("rgb1");
            }
        }
    }

    // Format: DXGI_FORMAT_R8_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R8_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kR_8;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 2;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R8_UNORM, Surface: kAlpha_8
            {
                constexpr GrColorType ct = GrColorType::kAlpha_8;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
                ctInfo.fReadSwizzle = GrSwizzle("000r");
                ctInfo.fWriteSwizzle = GrSwizzle("a000");
            }
            // Format: DXGI_FORMAT_R8_UNORM, Surface: kGray_8
            {
                constexpr GrColorType ct = GrColorType::kGray_8;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
                ctInfo.fReadSwizzle = GrSwizzle("rrr1");
            }
        }
    }
    // Format: DXGI_FORMAT_B8G8R8A8_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_B8G8R8A8_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kBGRA_8888;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_B8G8R8A8_UNORM, Surface: kBGRA_8888
            {
                constexpr GrColorType ct = GrColorType::kBGRA_8888;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
        }
    }
    // Format: DXGI_FORMAT_B5G6R5_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_B5G6R5_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kBGR_565;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_B5G6R5_UNORM, Surface: kBGR_565
            {
                constexpr GrColorType ct = GrColorType::kBGR_565;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
        }
    }
    // Format: DXGI_FORMAT_R16G16B16A16_FLOAT
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R16G16B16A16_FLOAT;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kRGBA_F16;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 2;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R16G16B16A16_FLOAT, Surface: GrColorType::kRGBA_F16
            {
                constexpr GrColorType ct = GrColorType::kRGBA_F16;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
            // Format: DXGI_FORMAT_R16G16B16A16_FLOAT, Surface: GrColorType::kRGBA_F16_Clamped
            {
                constexpr GrColorType ct = GrColorType::kRGBA_F16_Clamped;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
        }
    }
    // Format: DXGI_FORMAT_R16_FLOAT
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R16_FLOAT;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kR_F16;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R16_FLOAT, Surface: kAlpha_F16
            {
                constexpr GrColorType ct = GrColorType::kAlpha_F16;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
                ctInfo.fReadSwizzle = GrSwizzle("000r");
                ctInfo.fWriteSwizzle = GrSwizzle("a000");
            }
        }
    }
    // Format: DXGI_FORMAT_R8G8_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R8G8_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kRG_88;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R8G8_UNORM, Surface: kRG_88
            {
                constexpr GrColorType ct = GrColorType::kRG_88;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
        }
    }
    // Format: DXGI_FORMAT_R10G10B10A2_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R10G10B10A2_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kRGBA_1010102;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R10G10B10A2_UNORM, Surface: kRGBA_1010102
            {
                constexpr GrColorType ct = GrColorType::kRGBA_1010102;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
        }
    }
    // Format: DXGI_FORMAT_B4G4R4A4_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_B4G4R4A4_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kBGRA_4444;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_B4G4R4A4_UNORM, Surface: kABGR_4444
            {
                constexpr GrColorType ct = GrColorType::kABGR_4444;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
                ctInfo.fReadSwizzle = GrSwizzle("argb");
                ctInfo.fWriteSwizzle = GrSwizzle("gbar");
            }
        }
    }
    // Format: DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kRGBA_8888_SRGB;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, Surface: kRGBA_8888_SRGB
            {
                constexpr GrColorType ct = GrColorType::kRGBA_8888_SRGB;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
        }
    }
    // Format: DXGI_FORMAT_R16_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R16_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kR_16;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R16_UNORM, Surface: kAlpha_16
            {
                constexpr GrColorType ct = GrColorType::kAlpha_16;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
                ctInfo.fReadSwizzle = GrSwizzle("000r");
                ctInfo.fWriteSwizzle = GrSwizzle("a000");
            }
        }
    }
    // Format: DXGI_FORMAT_R16G16_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R16G16_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kRG_1616;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R16G16_UNORM, Surface: kRG_1616
            {
                constexpr GrColorType ct = GrColorType::kRG_1616;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
        }
    }
    // Format: DXGI_FORMAT_R16G16B16A16_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R16G16B16A16_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kRGBA_16161616;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R16G16B16A16_UNORM, Surface: kRGBA_16161616
            {
                constexpr GrColorType ct = GrColorType::kRGBA_16161616;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
        }
    }
    // Format: DXGI_FORMAT_R16G16_FLOAT
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_R16G16_FLOAT;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        info.fFormatColorType = GrColorType::kRG_F16;
        if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
            info.fColorTypeInfoCount = 1;
            info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
            int ctIdx = 0;
            // Format: DXGI_FORMAT_R16G16_FLOAT, Surface: kRG_F16
            {
                constexpr GrColorType ct = GrColorType::kRG_F16;
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
                ctInfo.fColorType = ct;
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
            }
        }
    }

    // Format: DXGI_FORMAT_BC1_UNORM
    {
        constexpr DXGI_FORMAT format = DXGI_FORMAT_BC1_UNORM;
        auto& info = this->getFormatInfo(format);
        info.init(adapterDesc, device, format);
        // No supported GrColorTypes.
    }

    ////////////////////////////////////////////////////////////////////////////
    // Map GrColorTypes (used for creating GrSurfaces) to DXGI_FORMATs. The order in which the
    // formats are passed into the setColorType function indicates the priority in selecting which
    // format we use for a given GrcolorType.

    this->setColorType(GrColorType::kAlpha_8, { DXGI_FORMAT_R8_UNORM });
    this->setColorType(GrColorType::kBGR_565, { DXGI_FORMAT_B5G6R5_UNORM });
    this->setColorType(GrColorType::kABGR_4444, { DXGI_FORMAT_B4G4R4A4_UNORM });
    this->setColorType(GrColorType::kRGBA_8888, { DXGI_FORMAT_R8G8B8A8_UNORM });
    this->setColorType(GrColorType::kRGBA_8888_SRGB, { DXGI_FORMAT_R8G8B8A8_UNORM_SRGB });
    this->setColorType(GrColorType::kRGB_888x, { DXGI_FORMAT_R8G8B8A8_UNORM });
    this->setColorType(GrColorType::kRG_88, { DXGI_FORMAT_R8G8_UNORM });
    this->setColorType(GrColorType::kBGRA_8888, { DXGI_FORMAT_B8G8R8A8_UNORM });
    this->setColorType(GrColorType::kRGBA_1010102, { DXGI_FORMAT_R10G10B10A2_UNORM });
    this->setColorType(GrColorType::kGray_8, { DXGI_FORMAT_R8_UNORM });
    this->setColorType(GrColorType::kAlpha_F16, { DXGI_FORMAT_R16_FLOAT });
    this->setColorType(GrColorType::kRGBA_F16, { DXGI_FORMAT_R16G16B16A16_FLOAT });
    this->setColorType(GrColorType::kRGBA_F16_Clamped, { DXGI_FORMAT_R16G16B16A16_FLOAT });
    this->setColorType(GrColorType::kAlpha_16, { DXGI_FORMAT_R16_UNORM });
    this->setColorType(GrColorType::kRG_1616, { DXGI_FORMAT_R16G16_UNORM });
    this->setColorType(GrColorType::kRGBA_16161616, { DXGI_FORMAT_R16G16B16A16_UNORM });
    this->setColorType(GrColorType::kRG_F16, { DXGI_FORMAT_R16G16_FLOAT });
}

void GrD3DCaps::FormatInfo::InitFormatFlags(const D3D12_FEATURE_DATA_FORMAT_SUPPORT& formatSupport,
                                            uint16_t* flags) {
    if (SkToBool(D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE & formatSupport.Support1)) {
        *flags = *flags | kTexturable_Flag;

        // Ganesh assumes that all renderable surfaces are also texturable
        if (SkToBool(D3D12_FORMAT_SUPPORT1_RENDER_TARGET & formatSupport.Support1) &&
            SkToBool(D3D12_FORMAT_SUPPORT1_BLENDABLE & formatSupport.Support1)) {
            *flags = *flags | kRenderable_Flag;
        }
    }

    if (SkToBool(D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET & formatSupport.Support1)) {
        *flags = *flags | kMSAA_Flag;
    }

    if (SkToBool(D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE & formatSupport.Support1)) {
        *flags = *flags | kResolve_Flag;
    }

    if (SkToBool(D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW & formatSupport.Support1)) {
        *flags = *flags | kUnorderedAccess_Flag;
    }
}

static bool multisample_count_supported(ID3D12Device* device, DXGI_FORMAT format, int sampleCount) {
    D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msqLevels;
    msqLevels.Format = format;
    msqLevels.SampleCount = sampleCount;
    msqLevels.Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE;
    GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
                                                     &msqLevels, sizeof(msqLevels)));

    return msqLevels.NumQualityLevels > 0;
}

void GrD3DCaps::FormatInfo::initSampleCounts(const DXGI_ADAPTER_DESC& adapterDesc,
                                             ID3D12Device* device, DXGI_FORMAT format) {
    if (multisample_count_supported(device, format, 1)) {
        fColorSampleCounts.push_back(1);
    }
    // TODO: test these
    //if (kImagination_D3DVendor == adapterDesc.VendorId) {
    //    // MSAA does not work on imagination
    //    return;
    //}
    //if (kIntel_D3DVendor == adapterDesc.VendorId) {
    //    // MSAA doesn't work well on Intel GPUs chromium:527565, chromium:983926
    //    return;
    //}
    if (multisample_count_supported(device, format, 2)) {
        fColorSampleCounts.push_back(2);
    }
    if (multisample_count_supported(device, format, 4)) {
        fColorSampleCounts.push_back(4);
    }
    if (multisample_count_supported(device, format, 8)) {
        fColorSampleCounts.push_back(8);
    }
    if (multisample_count_supported(device, format, 16)) {
        fColorSampleCounts.push_back(16);
    }
    // Standard sample locations are not defined for more than 16 samples, and we don't need more
    // than 16. Omit 32 and 64.
}

void GrD3DCaps::FormatInfo::init(const DXGI_ADAPTER_DESC& adapterDesc, ID3D12Device* device,
                                 DXGI_FORMAT format) {
    D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupportDesc;
    formatSupportDesc.Format = format;
    GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
                                                     &formatSupportDesc,
                                                     sizeof(formatSupportDesc)));

    InitFormatFlags(formatSupportDesc, &fFlags);
    if (fFlags & kRenderable_Flag) {
        this->initSampleCounts(adapterDesc, device, format);
    }
}

bool GrD3DCaps::isFormatSRGB(const GrBackendFormat& format) const {
    DXGI_FORMAT dxgiFormat;
    if (!format.asDxgiFormat(&dxgiFormat)) {
        return false;
    }

    switch (dxgiFormat) {
        case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
            return true;
        default:
            return false;
    }
}

bool GrD3DCaps::isFormatTexturable(const GrBackendFormat& format) const {
    DXGI_FORMAT dxgiFormat;
    if (!format.asDxgiFormat(&dxgiFormat)) {
        return false;
    }

    return this->isFormatTexturable(dxgiFormat);
}

bool GrD3DCaps::isFormatTexturable(DXGI_FORMAT format) const {
    const FormatInfo& info = this->getFormatInfo(format);
    return SkToBool(FormatInfo::kTexturable_Flag & info.fFlags);
}

bool GrD3DCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
                                             int sampleCount) const {
    DXGI_FORMAT dxgiFormat;
    if (!format.asDxgiFormat(&dxgiFormat)) {
        return false;
    }
    if (!this->isFormatRenderable(dxgiFormat, sampleCount)) {
        return false;
    }
    const auto& info = this->getFormatInfo(dxgiFormat);
    if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
        return false;
    }
    return true;
}

bool GrD3DCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
    DXGI_FORMAT dxgiFormat;
    if (!format.asDxgiFormat(&dxgiFormat)) {
        return false;
    }
    return this->isFormatRenderable(dxgiFormat, sampleCount);
}

bool GrD3DCaps::isFormatRenderable(DXGI_FORMAT format, int sampleCount) const {
    return sampleCount <= this->maxRenderTargetSampleCount(format);
}

bool GrD3DCaps::isFormatUnorderedAccessible(DXGI_FORMAT format) const {
    const FormatInfo& info = this->getFormatInfo(format);
    return SkToBool(FormatInfo::kUnorderedAccess_Flag & info.fFlags);
}

int GrD3DCaps::getRenderTargetSampleCount(int requestedCount,
                                         const GrBackendFormat& format) const {
    DXGI_FORMAT dxgiFormat;
    if (!format.asDxgiFormat(&dxgiFormat)) {
        return 0;
    }

    return this->getRenderTargetSampleCount(requestedCount, dxgiFormat);
}

int GrD3DCaps::getRenderTargetSampleCount(int requestedCount, DXGI_FORMAT format) const {
    requestedCount = std::max(1, requestedCount);

    const FormatInfo& info = this->getFormatInfo(format);

    int count = info.fColorSampleCounts.count();

    if (!count) {
        return 0;
    }

    if (1 == requestedCount) {
        SkASSERT(info.fColorSampleCounts.count() && info.fColorSampleCounts[0] == 1);
        return 1;
    }

    for (int i = 0; i < count; ++i) {
        if (info.fColorSampleCounts[i] >= requestedCount) {
            return info.fColorSampleCounts[i];
        }
    }
    return 0;
}

int GrD3DCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
    DXGI_FORMAT dxgiFormat;
    if (!format.asDxgiFormat(&dxgiFormat)) {
        return 0;
    }
    return this->maxRenderTargetSampleCount(dxgiFormat);
}

int GrD3DCaps::maxRenderTargetSampleCount(DXGI_FORMAT format) const {
    const FormatInfo& info = this->getFormatInfo(format);

    const auto& table = info.fColorSampleCounts;
    if (!table.count()) {
        return 0;
    }
    return table[table.count() - 1];
}

GrColorType GrD3DCaps::getFormatColorType(DXGI_FORMAT format) const {
    const FormatInfo& info = this->getFormatInfo(format);
    return info.fFormatColorType;
}

GrCaps::SupportedWrite GrD3DCaps::supportedWritePixelsColorType(
        GrColorType surfaceColorType, const GrBackendFormat& surfaceFormat,
        GrColorType srcColorType) const {
    DXGI_FORMAT dxgiFormat;
    if (!surfaceFormat.asDxgiFormat(&dxgiFormat)) {
        return { GrColorType::kUnknown, 0 };
    }

    // TODO: this seems to be pretty constrictive, confirm
    // Any buffer data needs to be aligned to 512 bytes and that of a single texel.
    size_t offsetAlignment = GrAlignTo(GrDxgiFormatBytesPerBlock(dxgiFormat),
                                       D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);

    const auto& info = this->getFormatInfo(dxgiFormat);
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
        const auto& ctInfo = info.fColorTypeInfos[i];
        if (ctInfo.fColorType == surfaceColorType) {
            return { surfaceColorType, offsetAlignment };
        }
    }
    return { GrColorType::kUnknown, 0 };
}

GrCaps::SurfaceReadPixelsSupport GrD3DCaps::surfaceSupportsReadPixels(
        const GrSurface* surface) const {
    if (surface->isProtected()) {
        return SurfaceReadPixelsSupport::kUnsupported;
    }
    if (auto tex = static_cast<const GrD3DTexture*>(surface->asTexture())) {
        // We can't directly read from a compressed format
        if (GrDxgiFormatIsCompressed(tex->dxgiFormat())) {
            return SurfaceReadPixelsSupport::kCopyToTexture2D;
        }
        return SurfaceReadPixelsSupport::kSupported;
    } else if (auto rt = static_cast<const GrD3DRenderTarget*>(surface->asRenderTarget())) {
        if (rt->numSamples() > 1) {
            return SurfaceReadPixelsSupport::kCopyToTexture2D;
        }
        return SurfaceReadPixelsSupport::kSupported;
    }
    return SurfaceReadPixelsSupport::kUnsupported;
}

bool GrD3DCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
    if (auto rt = surface->asRenderTarget()) {
        return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
    }
    return true;
}

bool GrD3DCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
                                                  const GrBackendFormat& format) const {
    DXGI_FORMAT dxgiFormat;
    if (!format.asDxgiFormat(&dxgiFormat)) {
        return false;
    }

    const auto& info = this->getFormatInfo(dxgiFormat);
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
        if (info.fColorTypeInfos[i].fColorType == ct) {
            return true;
        }
    }
    return false;
}

GrBackendFormat GrD3DCaps::onGetDefaultBackendFormat(GrColorType ct) const {
    DXGI_FORMAT format = this->getFormatFromColorType(ct);
    if (format == DXGI_FORMAT_UNKNOWN) {
        return {};
    }
    return GrBackendFormat::MakeDxgi(format);
}

GrBackendFormat GrD3DCaps::getBackendFormatFromCompressionType(
    SkImage::CompressionType compressionType) const {
    switch (compressionType) {
        case SkImage::CompressionType::kBC1_RGBA8_UNORM:
            if (this->isFormatTexturable(DXGI_FORMAT_BC1_UNORM)) {
                return GrBackendFormat::MakeDxgi(DXGI_FORMAT_BC1_UNORM);
            }
            return {};
        default:
            return {};
    }

    SkUNREACHABLE;
}

GrSwizzle GrD3DCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
    DXGI_FORMAT dxgiFormat;
    SkAssertResult(format.asDxgiFormat(&dxgiFormat));
    const auto& info = this->getFormatInfo(dxgiFormat);
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
        const auto& ctInfo = info.fColorTypeInfos[i];
        if (ctInfo.fColorType == colorType) {
            return ctInfo.fReadSwizzle;
        }
    }
    SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.", colorType, dxgiFormat);
    return {};
}

GrSwizzle GrD3DCaps::getWriteSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
    DXGI_FORMAT dxgiFormat;
    SkAssertResult(format.asDxgiFormat(&dxgiFormat));
    const auto& info = this->getFormatInfo(dxgiFormat);
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
        const auto& ctInfo = info.fColorTypeInfos[i];
        if (ctInfo.fColorType == colorType) {
            return ctInfo.fWriteSwizzle;
        }
    }
    SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.", colorType, dxgiFormat);
    return {};
}

uint64_t GrD3DCaps::computeFormatKey(const GrBackendFormat& format) const {
    DXGI_FORMAT dxgiFormat;
    SkAssertResult(format.asDxgiFormat(&dxgiFormat));

    return (uint64_t)dxgiFormat;
}

GrCaps::SupportedRead GrD3DCaps::onSupportedReadPixelsColorType(
        GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
        GrColorType dstColorType) const {
    DXGI_FORMAT dxgiFormat;
    if (!srcBackendFormat.asDxgiFormat(&dxgiFormat)) {
        return { GrColorType::kUnknown, 0 };
    }

    SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
    if (compression != SkImage::CompressionType::kNone) {
        return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
                                                        : GrColorType::kRGBA_8888, 0 };
    }

    // Any subresource buffer data we copy to needs to be aligned to 256 bytes.
    size_t offsetAlignment = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;

    const auto& info = this->getFormatInfo(dxgiFormat);
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
        const auto& ctInfo = info.fColorTypeInfos[i];
        if (ctInfo.fColorType == srcColorType) {
            return { srcColorType, offsetAlignment };
        }
    }
    return { GrColorType::kUnknown, 0 };
}

void GrD3DCaps::addExtraSamplerKey(GrProcessorKeyBuilder* b,
                                   GrSamplerState samplerState,
                                   const GrBackendFormat& format) const {
    // TODO
}

/**
 * TODO: Determine what goes in the ProgramDesc
 */
GrProgramDesc GrD3DCaps::makeDesc(GrRenderTarget* rt,
                                  const GrProgramInfo& programInfo,
                                  ProgramDescOverrideFlags overrideFlags) const {
    SkASSERT(overrideFlags == ProgramDescOverrideFlags::kNone);
    GrProgramDesc desc;
    GrProgramDesc::Build(&desc, programInfo, *this);

    GrProcessorKeyBuilder b(desc.key());

    GrD3DRenderTarget* d3dRT = (GrD3DRenderTarget*) rt;
    d3dRT->genKey(&b);

    GrStencilSettings stencil = programInfo.nonGLStencilSettings();
    stencil.genKey(&b, false);

    programInfo.pipeline().genKey(&b, *this);
    // The num samples is already added in the render target key so we don't need to add it here.
    SkASSERT(programInfo.numRasterSamples() == rt->numSamples());

    // D3D requires the full primitive type as part of its key
    b.add32(programInfo.primitiveTypeKey());

    SkASSERT(!this->mixedSamplesSupport());

    b.flush();
    return desc;
}

#if GR_TEST_UTILS
std::vector<GrCaps::TestFormatColorTypeCombination> GrD3DCaps::getTestingCombinations() const {
    std::vector<GrCaps::TestFormatColorTypeCombination> combos = {
        {GrColorType::kAlpha_8,        GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8_UNORM)           },
        {GrColorType::kBGR_565,        GrBackendFormat::MakeDxgi(DXGI_FORMAT_B5G6R5_UNORM)       },
        {GrColorType::kABGR_4444,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_B4G4R4A4_UNORM)     },
        {GrColorType::kRGBA_8888,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8G8B8A8_UNORM)     },
        {GrColorType::kRGBA_8888_SRGB, GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)},
        {GrColorType::kRGB_888x,       GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8G8B8A8_UNORM)     },
        {GrColorType::kRG_88,          GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8G8_UNORM)         },
        {GrColorType::kBGRA_8888,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_B8G8R8A8_UNORM)     },
        {GrColorType::kRGBA_1010102,   GrBackendFormat::MakeDxgi(DXGI_FORMAT_R10G10B10A2_UNORM)  },
        {GrColorType::kGray_8,         GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8_UNORM)           },
        {GrColorType::kAlpha_F16,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16_FLOAT)          },
        {GrColorType::kRGBA_F16,       GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16B16A16_FLOAT) },
        {GrColorType::kRGBA_F16_Clamped, GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16B16A16_FLOAT)},
        {GrColorType::kAlpha_16,       GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16_UNORM)          },
        {GrColorType::kRG_1616,        GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16_UNORM)       },
        {GrColorType::kRGBA_16161616,  GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16B16A16_UNORM) },
        {GrColorType::kRG_F16,         GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16_FLOAT)       },
        {GrColorType::kRGBA_8888,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_BC1_UNORM)          },
    };

    return combos;
}
#endif
