Proper texture object creation for block compressed formats after v11.5

Hello,

I’m trying to create a texture object for block compressed formats with CUDA 12.2.
CUDA introduced dedicated enum members for block compressed texture formats in CUDA 11.5 (e.g. CUarray_format_enum::CU_AD_FORMAT_BC1_UNORM).

I could create a CUDA mipmapped array for 32x32, 6 mipmap levels:

int32_t width = 32;
int32_t height = 32;
int32_t numMipmapLevels = 6;

CUDA_ARRAY3D_DESCRIPTOR arrayDesc = {};
arrayDesc.Format = CU_AD_FORMAT_BC1_UNORM;
arrayDesc.Width = width;
arrayDesc.Height = height;
arrayDesc.Depth = 0;
arrayDesc.NumChannels = 4;

CUmipmappedArray mipmappedArray;
CUDADRV_CHECK(cuMipmappedArrayCreate(&mipmappedArray, &arrayDesc, numMipmapLevels));

std::vector<CUarray> arrays(numMipmapLevels);
for (int mipLevel = 0; mipLevel < numMipmapLevels; ++mipLevel) {
    CUDADRV_CHECK(cuMipmappedArrayGetLevel(&arrays[mipLevel], mipmappedArray, mipLevel));
}

but I couldn’t create a texture object from that array:

CUDA_RESOURCE_DESC resDesc = {};
resDesc.resType = CU_RESOURCE_TYPE_MIPMAPPED_ARRAY;
resDesc.res.mipmap.hMipmappedArray = mipmappedArray;

CUDA_RESOURCE_VIEW_DESC resViewDesc = {};
resViewDesc.format = CU_RES_VIEW_FORMAT_UNSIGNED_BC1;
resViewDesc.width = width;
resViewDesc.height = height;
resViewDesc.depth = 0;
resViewDesc.firstMipmapLevel = 0;
resViewDesc.lastMipmapLevel = numMipmapLevels - 1;

CUDA_TEXTURE_DESC texDesc = {};
texDesc.maxMipmapLevelClamp = static_cast<float>(numMipmapLevels - 1);
CUtexObject texObj;
CUDADRV_CHECK(cuTexObjectCreate(&texObj, &resDesc, &texDesc, &resViewDesc));

The error is:

CUDA API Error
    Function: cuTexObjectCreate
    Error   : CUDA_ERROR_INVALID_VALUE(1)
    Desc    : invalid argument

What is the proper way to create a texture object using a dedicated enum value for block compressed texture?

The descriptions on cudaCreateTextureObject and cuTexObjectCreate seem to say something related:

  • cudaResourceViewDesc::format specifies how the data contained in the CUDA array or CUDA mipmapped array should be interpreted. Note that this can incur a change in size of the texture data. If the resource view format is a block compressed format, then the underlying CUDA array or CUDA mipmapped array has to have a 32-bit unsigned integer format with 2 or 4 channels, depending on the block compressed format. For ex., BC1 and BC4 require the underlying CUDA array to have a 32-bit unsigned int with 2 channels. The other BC formats require the underlying resource to have the same 32-bit unsigned int format but with 4 channels.

but this description seems outdated because the same has been here since even before CUDA 11.5.

I uploaded the above repro:

Thanks,

You might want to double check the number of channels. There seems to be a mismatch between requirements and actual usage.

That description seems outdated.
I have the error at cuMipmappedArrayCreate when specifying 2 for BC1 format.
I’m talking about new usage after CUDA 11.5.

From a different part of the official docs:

CU_AD_FORMAT_BC1_UNORM = 0x91
4 channel unsigned normalized block-compressed (BC1 compression) format

So it looks like you were on the right track. I do not use the CUDA driver API (I was the very first user of the CUDA runtime, ca. 2006 and refuse to go back), so you will have to wait for someone familiar with the driver API. I could not find anything relevant in an internet search.

Is there any sample code for BC textures, or even non-official samples?

this may be of interest

Thanks for the link, but this is old unfortunately.

As I wrote in the first post, as you know, CUDA 11.5 added the dedicated enum for BC textures. It should change the way to create a texture object and I hope it also fixes some mip-map issues that has been in CUDA for a long time.