SWDEV-555889 - Support mipmap on rocr (#2082)

* SWDEV-555889 - Support mipmap on rocr

Support mipmap in hip-rt on rocr backend.
Enable all mipmap tests in Windows.
Some other minor improvement.

Add some SRD logs that will be removed finally.

* Add sampler.mipFilter to fix sampler issues on mipmap in rocr.
Fix format issues of view of leveled image and  mipmap image in blit kernel in rocr.
Enabled disabled mipmap tests.

* Rewrite view logic

* Set word4.f.PITCH = 0 for mipmap SRD on navi31 to fix unstable test issues.
Reset last error in nagative tests.

* Remove SRD dump log from hip-rt
Let Rocr mipmap log be in condition.

* minor format chang

* Exclude mipmap tests for mi200+ which don't support mipmap.
このコミットが含まれているのは:
Tao Sang
2026-01-21 12:10:29 -05:00
committed by GitHub
コミット 163e44d0a8
29個のファイルの変更224行の追加142行の削除
+2 -1
ファイルの表示
@@ -503,9 +503,10 @@ hsa_status_t hsa_ext_image_destroy_v2(hsa_agent_t agent, hsa_ext_image_t image)
hsa_status_t hsa_ext_image_mipmap_array_get_level(hsa_agent_t agent,
const hsa_ext_image_t* mipmap_array,
uint32_t mip_level,
const hsa_ext_image_descriptor_v2_t* image_descriptor,
hsa_ext_image_t* level_view) {
return rocr::core::Runtime::runtime_singleton_->extensions_.image_api
.hsa_ext_image_mipmap_array_get_level_fn(agent, mipmap_array, mip_level,
.hsa_ext_image_mipmap_array_get_level_fn(agent, mipmap_array, mip_level, image_descriptor,
level_view);
}
+7 -5
ファイルの表示
@@ -266,7 +266,7 @@ hsa_status_t hsa_ext_sampler_create(hsa_agent_t agent,
}
hsa_ext_sampler_descriptor_v2_t sampler_descriptor_v2 = {
sampler_descriptor->coordinate_mode,
sampler_descriptor->filter_mode,
sampler_descriptor->filter_mode, HSA_EXT_SAMPLER_FILTER_MODE_NONE,
{sampler_descriptor->address_mode,
sampler_descriptor->address_mode, sampler_descriptor->address_mode}
};
@@ -566,13 +566,15 @@ hsa_status_t hsa_ext_image_destroy_v2(hsa_agent_t agent, hsa_ext_image_t image)
// per-level view retrieval implementation
hsa_status_t HSA_API hsa_ext_image_mipmap_array_get_level(hsa_agent_t agent,
const hsa_ext_image_t* mipmapped_array,
uint32_t mip_level,
hsa_ext_image_t* level_image_out) {
const hsa_ext_image_t* mipmapped_array,
uint32_t mip_level,
const hsa_ext_image_descriptor_v2_t* image_descriptor,
hsa_ext_image_t* level_image_out) {
TRY;
if (!mipmapped_array || !level_image_out) { return HSA_STATUS_ERROR_INVALID_ARGUMENT; }
return ImageRuntime::instance()->GetMipmapArrayLevelHandle(agent, *mipmapped_array, mip_level, *level_image_out);
return ImageRuntime::instance()->GetMipmapArrayLevelHandle(agent, *mipmapped_array, mip_level,
image_descriptor, *level_image_out);
CATCH;
}
+16 -2
ファイルの表示
@@ -483,7 +483,17 @@ hsa_status_t ImageManagerAi::PopulateSamplerSrd(Sampler& sampler) const {
}
word2.bits.XY_MIN_FILTER = word2.bits.XY_MAG_FILTER;
word2.bits.Z_FILTER = SQ_TEX_Z_FILTER_NONE;
word2.bits.MIP_FILTER = SQ_TEX_MIP_FILTER_NONE;
switch (sampler_descriptor.mipmap_filter_mode) {
case HSA_EXT_SAMPLER_FILTER_MODE_NEAREST:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_POINT);
break;
case HSA_EXT_SAMPLER_FILTER_MODE_LINEAR:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_LINEAR);
break;
default:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_NONE);
}
word3.u32All = 0;
@@ -999,6 +1009,8 @@ hsa_status_t ImageManagerAi::PopulateMipLevelSrd(
MipmappedArray& level_view,
const MipmappedArray& mipmap_array,
uint32_t mip_level) const {
// Copy entire parent structure (srd is a fixed array, so it's deep-copied automatically)
level_view = mipmap_array;
// SRD already copied from parent, just modify BASE_LEVEL/LAST_LEVEL fields
uint32_t* srd_words = reinterpret_cast<uint32_t*>(level_view.srd);
@@ -1010,7 +1022,9 @@ hsa_status_t ImageManagerAi::PopulateMipLevelSrd(
word3->f.base_level = mip_level;
word3->f.last_level = mip_level;
debug_print("Set SRD mip selection: BASE_LEVEL=%u, LAST_LEVEL=%u", mip_level, mip_level);
if (core::Runtime::runtime_singleton_->flag().image_print_srd()) {
debug_print("Set SRD mip selection: BASE_LEVEL=%u, LAST_LEVEL=%u", mip_level, mip_level);
}
return HSA_STATUS_SUCCESS;
}
+17 -4
ファイルの表示
@@ -601,7 +601,17 @@ hsa_status_t ImageManagerGfx11::PopulateSamplerSrd(Sampler& sampler) const {
}
word2.bits.XY_MIN_FILTER = word2.bits.XY_MAG_FILTER;
word2.bits.Z_FILTER = SQ_TEX_Z_FILTER_NONE;
word2.bits.MIP_FILTER = SQ_TEX_MIP_FILTER_NONE;
switch (sampler_descriptor.mipmap_filter_mode) {
case HSA_EXT_SAMPLER_FILTER_MODE_NEAREST:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_POINT);
break;
case HSA_EXT_SAMPLER_FILTER_MODE_LINEAR:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_LINEAR);
break;
default:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_NONE);
}
word3.u32All = 0;
@@ -924,9 +934,8 @@ hsa_status_t ImageManagerGfx11::PopulateMipmapSrd(MipmappedArray& mipmap) const
// For 1d, 2d and 2d-msaa in gfx11 this is pitch-1
if (!mipmap_array && !mipmap_3d) {
word4.f.PITCH = out.pitch - 1;
word4.f.PITCH = 0; // mipmap dosesn't support custom pitch, so set it as 0
}
word5.val = 0;
word6.val = 0;
word7.val = 0;
@@ -1199,6 +1208,8 @@ hsa_status_t ImageManagerGfx11::PopulateMipLevelSrd(
MipmappedArray& level_view,
const MipmappedArray& mipmap_array,
uint32_t mip_level) const {
// Copy entire parent structure (srd is a fixed array, so it's deep-copied automatically)
level_view = mipmap_array;
// SRD already copied from parent, just modify BASE_LEVEL/LAST_LEVEL fields
uint32_t* srd_words = reinterpret_cast<uint32_t*>(level_view.srd);
@@ -1210,7 +1221,9 @@ hsa_status_t ImageManagerGfx11::PopulateMipLevelSrd(
word3->f.BASE_LEVEL = mip_level;
word3->f.LAST_LEVEL = mip_level;
debug_print("Set SRD mip selection: BASE_LEVEL=%u, LAST_LEVEL=%u", mip_level, mip_level);
if (core::Runtime::runtime_singleton_->flag().image_print_srd()) {
debug_print("Set SRD mip selection: BASE_LEVEL=%u, LAST_LEVEL=%u", mip_level, mip_level);
}
return HSA_STATUS_SUCCESS;
}
+17 -3
ファイルの表示
@@ -637,7 +637,17 @@ hsa_status_t ImageManagerGfx12::PopulateSamplerSrd(Sampler& sampler) const {
}
word2.bits.XY_MIN_FILTER = word2.bits.XY_MAG_FILTER;
word2.bits.Z_FILTER = SQ_TEX_Z_FILTER_NONE;
word2.bits.MIP_FILTER = SQ_TEX_MIP_FILTER_NONE;
switch (sampler_descriptor.mipmap_filter_mode) {
case HSA_EXT_SAMPLER_FILTER_MODE_NEAREST:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_POINT);
break;
case HSA_EXT_SAMPLER_FILTER_MODE_LINEAR:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_LINEAR);
break;
default:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_NONE);
}
word3.u32All = 0;
@@ -1051,7 +1061,7 @@ hsa_status_t ImageManagerGfx12::PopulateMipmapSrd(MipmappedArray& mipmap) const
// For 1d, 2d and 2d-msaa, fields DEPTH+PITCH_MSB encode pitch-1
if (!mipmap_array && !mipmap_3d) {
uint32_t encPitch = out.pitch - 1;
uint32_t encPitch = 0; // mipmap dosesn't support custom pitch, so set it as 0
word4.f.DEPTH = encPitch & 0x3fff; // first 14 bits
word4.f.PITCH_MSB = (encPitch >> 14) & 0x3; // last 2 bits
} else {
@@ -1358,6 +1368,8 @@ hsa_status_t ImageManagerGfx12::PopulateMipLevelSrd(
MipmappedArray& level_view,
const MipmappedArray& mipmap_array,
uint32_t mip_level) const {
// Copy entire parent structure (srd is a fixed array, so it's deep-copied automatically)
level_view = mipmap_array;
// SRD already copied from parent, just modify BASE_LEVEL/LAST_LEVEL fields
uint32_t* srd_words = reinterpret_cast<uint32_t*>(level_view.srd);
@@ -1370,7 +1382,9 @@ hsa_status_t ImageManagerGfx12::PopulateMipLevelSrd(
word1->f.BASE_LEVEL = mip_level;
word3->f.LAST_LEVEL = mip_level;
debug_print("Set SRD mip selection: BASE_LEVEL=%u, LAST_LEVEL=%u", mip_level, mip_level);
if (core::Runtime::runtime_singleton_->flag().image_print_srd()) {
debug_print("Set SRD mip selection: BASE_LEVEL=%u, LAST_LEVEL=%u", mip_level, mip_level);
}
return HSA_STATUS_SUCCESS;
}
+17 -3
ファイルの表示
@@ -594,7 +594,17 @@ hsa_status_t ImageManagerNv::PopulateSamplerSrd(Sampler& sampler) const {
}
word2.bits.XY_MIN_FILTER = word2.bits.XY_MAG_FILTER;
word2.bits.Z_FILTER = SQ_TEX_Z_FILTER_NONE;
word2.bits.MIP_FILTER = SQ_TEX_MIP_FILTER_NONE;
switch (sampler_descriptor.mipmap_filter_mode) {
case HSA_EXT_SAMPLER_FILTER_MODE_NEAREST:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_POINT);
break;
case HSA_EXT_SAMPLER_FILTER_MODE_LINEAR:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_LINEAR);
break;
default:
word2.bits.MIP_FILTER = static_cast<int>(SQ_TEX_MIP_FILTER_NONE);
}
word3.u32All = 0;
@@ -923,7 +933,7 @@ hsa_status_t ImageManagerNv::PopulateMipmapSrd(MipmappedArray& mipmap) const {
uint32_t minor_ver = MinorVerFromDevID(chip_id_);
// For 1d, 2d and 2d-msaa in gfx1030 and beyond this is pitch-1
if ((minor_ver >= 3) && !mipmap_array && !mipmap_3d)
word4.f.PITCH = out.pitch - 1;
word4.f.PITCH = 0; // mipmap dosesn't support custom pitch, so set it as 0
word5.val = 0;
word5.f.MAX_MIP = mipmap.num_levels - 1;
@@ -1119,6 +1129,8 @@ hsa_status_t ImageManagerNv::PopulateMipLevelSrd(
MipmappedArray& level_view,
const MipmappedArray& mipmap_array,
uint32_t mip_level) const {
// Copy entire parent structure (srd is a fixed array, so it's deep-copied automatically)
level_view = mipmap_array;
// SRD already copied from parent, just modify BASE_LEVEL/LAST_LEVEL fields
uint32_t* srd_words = reinterpret_cast<uint32_t*>(level_view.srd);
@@ -1130,7 +1142,9 @@ hsa_status_t ImageManagerNv::PopulateMipLevelSrd(
word3->f.BASE_LEVEL = mip_level;
word3->f.LAST_LEVEL = mip_level;
debug_print("Set SRD mip selection: BASE_LEVEL=%u, LAST_LEVEL=%u", mip_level, mip_level);
if (core::Runtime::runtime_singleton_->flag().image_print_srd()) {
debug_print("Set SRD mip selection: BASE_LEVEL=%u, LAST_LEVEL=%u", mip_level, mip_level);
}
return HSA_STATUS_SUCCESS;
}
+38 -25
ファイルの表示
@@ -771,8 +771,6 @@ hsa_status_t ImageRuntime::CreateMipmapArrayHandle(
mipmap_array->tile_mode = Image::TileMode::TILED;
}
debug_print("Tile mode = %u (0: LINEAR, 1: TILED)", mipmap_array->tile_mode);
// Initialize the mipmapped array object
mipmap_array->component = component;
mipmap_array->data = const_cast<void*>(image_data);
@@ -782,15 +780,18 @@ hsa_status_t ImageRuntime::CreateMipmapArrayHandle(
mipmap_array->flags = 0;
manager->PopulateMipmapSrd(*mipmap_array);
debug_print("Populating mipmapped array SRD...");
if (core::Runtime::runtime_singleton_->flag().image_print_srd())
mipmap_array->printSRD();
manager->printSRDDetailed(mipmap_array->srd);
// assert(mipmap_array->size == required_size);
image_handle.handle = mipmap_array->Convert();
debug_print("output handle = %lu", image_handle.handle);
if (core::Runtime::runtime_singleton_->flag().image_print_srd()) {
debug_print("Tile mode = %u (0: LINEAR, 1: TILED)", mipmap_array->tile_mode);
debug_print("Populating mipmapped array SRD...");
mipmap_array->printSRD();
manager->printSRDDetailed(mipmap_array->srd);
debug_print("output handle = %lu", image_handle.handle);
}
return HSA_STATUS_SUCCESS;
}
@@ -809,7 +810,12 @@ hsa_status_t ImageRuntime::DestroyMipmapArrayHandle(
hsa_status_t ImageRuntime::GetMipmapArrayLevelHandle(
hsa_agent_t component, const hsa_ext_image_t& mipmapped_array,
uint32_t mip_level, hsa_ext_image_t& level_image_out) {
uint32_t mip_level, const hsa_ext_image_descriptor_v2_t* image_descriptor,
hsa_ext_image_t& level_image_out) {
ImageManager * manager = image_manager(component);
if (!manager) {
return HSA_STATUS_ERROR_OUT_OF_RESOURCES;
}
level_image_out.handle = 0;
@@ -837,35 +843,42 @@ hsa_status_t ImageRuntime::GetMipmapArrayLevelHandle(
return HSA_STATUS_ERROR_INVALID_ARGUMENT;
}
debug_print("Creating mip level %u view for %u level mipmap\n",
if (core::Runtime::runtime_singleton_->flag().image_print_srd()) {
debug_print("Creating mip level %u view for %u level mipmap\n",
mip_level, array->num_levels);
}
// Create a view that references the parent mipmap array
MipmappedArray* level_view = MipmappedArray::Create(component);
if (!level_view) return HSA_STATUS_ERROR_OUT_OF_RESOURCES;
// Copy entire parent structure (srd is a fixed array, so it's deep-copied automatically)
*level_view = *array;
// Modify SRD to select only the specific mip level
ImageManager* manager = image_manager(component);
if (!manager) {
MipmappedArray::Destroy(level_view);
return HSA_STATUS_ERROR_OUT_OF_RESOURCES;
auto format = image_descriptor ? &image_descriptor->format : nullptr;
if (format &&
(array->desc.format.channel_type != format->channel_type ||
array->desc.format.channel_order != format->channel_order)) {
MipmappedArray tempArray = *array;
tempArray.desc.format.channel_type = format->channel_type;
tempArray.desc.format.channel_order = format->channel_order;
status = manager->PopulateMipmapSrd(tempArray);
if (status == HSA_STATUS_SUCCESS) {
status = manager->PopulateMipLevelSrd(*level_view, tempArray, mip_level);
}
else {
debug_print("PopulateMipmapSrd() failed with status %d", status);
}
}
else {
status = manager->PopulateMipLevelSrd(*level_view, *array, mip_level);
}
status = manager->PopulateMipLevelSrd(*level_view, *array, mip_level);
if (status != HSA_STATUS_SUCCESS) {
MipmappedArray::Destroy(level_view);
return status;
}
debug_print("Created mip level view using SRD fields");
if (core::Runtime::runtime_singleton_->flag().image_print_srd())
if (core::Runtime::runtime_singleton_->flag().image_print_srd()) {
level_view->printSRD();
manager->printSRDDetailed(level_view->srd);
manager->printSRDDetailed(level_view->srd);
}
// Return handle
level_image_out.handle = level_view->Convert();
return HSA_STATUS_SUCCESS;
+2 -1
ファイルの表示
@@ -171,7 +171,8 @@ class ImageRuntime {
/// @brief Get the handle for a specific mipmap level in a mipmapped array.
hsa_status_t GetMipmapArrayLevelHandle(
hsa_agent_t agent, const hsa_ext_image_t& mipmapped_array,
uint32_t mip_level, hsa_ext_image_t& level_image_out);
uint32_t mip_level, const hsa_ext_image_descriptor_v2_t* image_descriptor,
hsa_ext_image_t& level_image_out);
ImageManager* image_manager(hsa_agent_t agent) {
std::map<uint64_t, ImageManager*>::iterator it = image_managers_.find(agent.handle);
+2 -2
ファイルの表示
@@ -223,9 +223,9 @@ private:
tile_mode = LINEAR;
}
~MipmappedArray() {}
public:
~MipmappedArray() {}
/// @brief Create a MipmappedArray.
/// Only internal metadata is allocated; image data must be provided by the user.
static MipmappedArray* Create(hsa_agent_t agent);
+13 -2
ファイルの表示
@@ -1053,6 +1053,7 @@ hsa_status_t HSA_API hsa_ext_image_destroy_v2(hsa_agent_t agent, hsa_ext_image_t
hsa_status_t HSA_API hsa_ext_image_mipmap_array_get_level(hsa_agent_t agent,
const hsa_ext_image_t* mipmapped_array,
uint32_t mip_level,
const hsa_ext_image_descriptor_v2_t* image_descriptor,
hsa_ext_image_t* level_image_out);
/**
@@ -1381,7 +1382,12 @@ typedef enum {
* square block or 2x2x2 cube block around the specified coordinate. The
* elements are combined using linear interpolation.
*/
HSA_EXT_SAMPLER_FILTER_MODE_LINEAR = 1
HSA_EXT_SAMPLER_FILTER_MODE_LINEAR = 1,
/**
* None filter. Used for mipmap filter mode of non-mipmap images.
*/
HSA_EXT_SAMPLER_FILTER_MODE_NONE = 2
} hsa_ext_sampler_filter_mode_t;
@@ -1422,10 +1428,15 @@ typedef struct hsa_ext_sampler_descriptor_v2_s {
hsa_ext_sampler_coordinate_mode32_t coordinate_mode;
/**
* Sampler filter type describes the type of sampling performed.
* Sampler filter type describes the type of sampling performed on regular image.
*/
hsa_ext_sampler_filter_mode32_t filter_mode;
/**
* Sampler filter type describes the type of sampling performed on mipmap image.
*/
hsa_ext_sampler_filter_mode32_t mipmap_filter_mode;
/**
* Sampler address mode describes the processing of out-of-range image
* coordinates.