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?
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
viaCheckFeatureSupport
. 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.