direct3d12

What is subresource in Direct 3D 12?


I'm having trouble with understanding what subresource is in Direct 3D 12.

So far, I thought it as user defines subresource. Just like allocating one huge array and dividing parts of the array to interpret as a particular object. (eg. using first 2 bytes ([0]~[1]) as object A and next 2 bytes as object B ([2]~[3])) Referred to "region" in case of ID3D12GraphicsCommandList::CopyBufferRegion. Descriptors seem to work in this manner as well (from here to there is a particular object).

However, this subresource confuses me when it comes to texture.

I thought resource creation has nothing to do with subresource because there was no argument such as UINT NumSubresources (eg. D3D12_HEAP_PROPERTIES or D3D12_RESOURCE_DESC in ID3D12Device::CreateCommittedResource) until I needed to get the size and row pitch of texture by ID3D12Device::GetCopyableFootprints. And GetCopyableFootprints requires UINT NumSubresources.

I couldn't find example that uses other than 0 FirstSubresource, 1 NumSubresources, 0 BaseOffset.

Q. If assuming there is a ID3D12Resource that has 2 subresource textures, how do I get number of subresources, or start offset of each subresource if subresource count is more than 1, in this ID3D12Resource?

Q. How do I create ID3D12Resource that has 2 subresource textures (committedresource)?

Q. What exactly is subresource?


Solution

  • A subresource for Direct3D 11 and Direct3D 12 refers to a single chunk of a complex texture resource (Direct3D 9 and earlier called them surfaces). Here are some examples:

    subresource count resource
    1 1D or 2D texture with no mipmaps
    m 1D or 2D texture with m miplevels
    n 1D or 2D texture array of n textures with no mipmaps
    n*m 1D or 2D texture array of n textures with m miplevels
    1 3D volume texture of depth d and no miplevels
    m 3D volume texture of depth d with m miplevels

    UPDATE: For 3D volume textures, the actual number of textures in a given slice depends on the depth at that mip-level because of the 3D mipchains. There is just ONE sub resource for each miplevel and all the images in a slice must be continuous in memory.

    Here's some pseudo-code:

    size_t index = 0;
    if (Dimension == DIMENSION_TEXTURE3D)
    {
        size_t w = desc.Width;
        size_t h = desc.Height;
        size_t d = desc.Depth;
    
        for (size_t level = 0; level < desc.MipLevels; ++level)
        {
            // Here is a subresource containing d images
            // of w,h size.
            // Each scanline of the image is RowPitch bytes            
            // Each 2D image is SlicePitch bytes
            // Exact byte count depends on the DXGI Format
    
            // There are d*SlicePitch bytes of data in this subresource
    
            ++index;
    
            if (h > 1)
               h >>= 1;
    
            if (w > 1)
                w >>= 1;
    
            if (d > 1)
                d >>= 1;
        }
    }
    else
    {
        // DIMENSION_TEXTURE1D or DIMENSION_TEXTURE2D
        for (size_t item = 0; item < desc.ArraySize; ++item)
        {
            size_t w = desc.Width;
            size_t h = desc.Height;
    
            for (size_t level = 0; level < desc.MipLevels; ++level)
            {
                // Here is a subresource containing an image
                // of w,h size.
                // Each scanline of the image is RowPitch bytes
                // Exact byte count depends on the DXGI Format
                ++index;
    
                if (h > 1)
                    h >>= 1;
    
                if (w > 1)
                    w >>= 1;
            }
        }
    }
    
    // At this point index is the NumSubresources count
    // for the whole resource.
    

    A simple calculation for the total number of subresources from the description is given by:

    UINT ArraySize = (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D)
        ? DepthOrArraySize : 1u;
    UINT numSubresources = MipLevels * ArraySize * PlaneCount;
    

    For planar formats, you must also multiply by the number of planes in the format given from D3D12_FEATURE_DATA_FORMAT_INFO.PlaneCount via CheckFeatureSupport. Unless you are using video formats or depth/stencil formats, they are not planar (i.e. PlaneCount above is 1). For Direct3D 11, PlaneCount is always 1 (it implements video planar formats is a more hacky way).

    For lots of example code of working with Direct3D subresources, see DirectXTex on GitHub.