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.
This commit is contained in:
Tao Sang
2026-01-21 12:10:29 -05:00
committed by GitHub
szülő 5daeb14582
commit 163e44d0a8
29 fájl változott, egészen pontosan 224 új sor hozzáadva és 142 régi sor törölve
@@ -628,7 +628,7 @@ class VirtualGPU : public device::VirtualDevice {
) {
amd::Memory* mem = new (amdImage.getContext()) amd::Buffer(amdImage, 0, 0, amdImage.getSize());
mem->setVirtualDevice(this);
if ((mem != nullptr) && !mem->create()) {
if (!mem->create()) {
mem->release();
}
return mem;
@@ -915,6 +915,16 @@ void Sampler::fillSampleDescriptor(hsa_ext_sampler_descriptor_v2_t& samplerDescr
samplerDescriptor.filter_mode = sampler.filterMode() == CL_FILTER_NEAREST
? HSA_EXT_SAMPLER_FILTER_MODE_NEAREST
: HSA_EXT_SAMPLER_FILTER_MODE_LINEAR;
switch (sampler.mipFilter()) {
case CL_FILTER_NEAREST:
samplerDescriptor.mipmap_filter_mode = HSA_EXT_SAMPLER_FILTER_MODE_NEAREST;
break;
case CL_FILTER_LINEAR:
samplerDescriptor.mipmap_filter_mode = HSA_EXT_SAMPLER_FILTER_MODE_LINEAR;
break;
default:
samplerDescriptor.mipmap_filter_mode = HSA_EXT_SAMPLER_FILTER_MODE_NONE;
}
samplerDescriptor.coordinate_mode = sampler.normalizedCoords()
? HSA_EXT_SAMPLER_COORDINATE_MODE_NORMALIZED
: HSA_EXT_SAMPLER_COORDINATE_MODE_UNNORMALIZED;
@@ -1175,6 +1175,7 @@ void Image::populateImageDescriptor() {
imageDescriptor_.height = image->getHeight();
imageDescriptor_.depth = image->getDepth();
imageDescriptor_.array_size = 0;
imageDescriptor_.mipmap_levels = image->getMipLevels() == 0 ? 1 : image->getMipLevels();
switch (image->getType()) {
case CL_MEM_OBJECT_IMAGE1D:
@@ -1440,8 +1441,31 @@ bool Image::createView(const Memory& parent) {
status = Hsa::image_create(dev().getBackendDevice(), &imageDescriptor_, amdImageDesc_,
deviceMemory_, permission_, &hsaImageObject_);
} else {
status = Hsa::image_create(dev().getBackendDevice(), &imageDescriptor_, deviceMemory_,
permission_, &hsaImageObject_);
if (ancestor->asImage()->getMipLevels() > 1 && imageDescriptor_.mipmap_levels == 1) {
// This is on leveled image of mipmap image ancestor
amd::Memory* parentOwner = parent.owner();
auto* ancestor_image = static_cast<Image*>(ancestor->getDeviceMemory(dev()));
if (ancestor == parentOwner) {
// This is leveled image
status = Hsa::image_get_mipmap_level(dev().getBackendDevice(),
&ancestor_image->hsaImageObject_,
owner()->asImage()->getBaseMipLevel(),
nullptr, &hsaImageObject_);
} else if (ancestor == parentOwner->parent()) {
// This is format changed view on leveled image
status = Hsa::image_get_mipmap_level(dev().getBackendDevice(),
&ancestor_image->hsaImageObject_,
parentOwner->asImage()->getBaseMipLevel(),
&imageDescriptor_, &hsaImageObject_);
} else {
// This is an impossible view on leveled image
status = HSA_STATUS_ERROR_INVALID_REGION;
}
} else {
// This is a view on regular image or mipmap image.
status = Hsa::image_create(dev().getBackendDevice(), &imageDescriptor_, deviceMemory_,
permission_, &hsaImageObject_);
}
}
if (status != HSA_STATUS_SUCCESS) {
@@ -227,7 +227,7 @@ class Image : public roc::Memory {
size_t getDeviceDataAlignment() { return deviceImageInfo_.alignment; }
hsa_ext_image_t getHsaImageObject() const { return hsaImageObject_; }
const hsa_ext_image_descriptor_t& getHsaImageDescriptor() const { return imageDescriptor_; }
const hsa_ext_image_descriptor_v2_t& getHsaImageDescriptor() const { return imageDescriptor_; }
virtual const address cpuSrd() const {
return reinterpret_cast<const address>(getHsaImageObject().handle);
@@ -263,7 +263,7 @@ class Image : public roc::Memory {
void populateImageDescriptor();
hsa_ext_image_descriptor_t imageDescriptor_;
hsa_ext_image_descriptor_v2_t imageDescriptor_;
hsa_access_permission_t permission_;
hsa_ext_image_data_info_t deviceImageInfo_;
hsa_ext_image_t hsaImageObject_;
@@ -130,14 +130,15 @@ bool Hsa::LoadLib() {
GET_ROCR_SYMBOL(hsa_amd_ais_file_write)
// Image extensions
GET_ROCR_SYMBOL(hsa_ext_image_data_get_info)
GET_ROCR_SYMBOL(hsa_ext_image_create)
GET_ROCR_SYMBOL(hsa_ext_image_data_get_info_v2)
GET_ROCR_SYMBOL(hsa_ext_image_create_v2)
GET_ROCR_SYMBOL(hsa_ext_image_import)
GET_ROCR_SYMBOL(hsa_ext_image_export)
GET_ROCR_SYMBOL(hsa_ext_image_destroy)
GET_ROCR_SYMBOL(hsa_ext_image_destroy_v2)
GET_ROCR_SYMBOL(hsa_ext_sampler_create_v2)
GET_ROCR_SYMBOL(hsa_ext_sampler_destroy)
GET_ROCR_SYMBOL(hsa_ext_image_create_with_layout)
GET_ROCR_SYMBOL(hsa_ext_image_mipmap_array_get_level)
is_ready_ = true;
return true;
}
@@ -138,14 +138,15 @@ struct RocrEntryPoints {
decltype(hsa_amd_ais_file_read)* hsa_amd_ais_file_read_;
decltype(hsa_amd_ais_file_write)* hsa_amd_ais_file_write_;
// Image extensions
decltype(hsa_ext_image_data_get_info)* hsa_ext_image_data_get_info_;
decltype(hsa_ext_image_create)* hsa_ext_image_create_;
decltype(hsa_ext_image_data_get_info_v2)* hsa_ext_image_data_get_info_v2_;
decltype(hsa_ext_image_create_v2)* hsa_ext_image_create_v2_;
decltype(hsa_ext_image_import)* hsa_ext_image_import_;
decltype(hsa_ext_image_export)* hsa_ext_image_export_;
decltype(hsa_ext_image_destroy)* hsa_ext_image_destroy_;
decltype(hsa_ext_image_destroy_v2)* hsa_ext_image_destroy_v2_;
decltype(hsa_ext_sampler_create_v2)* hsa_ext_sampler_create_v2_;
decltype(hsa_ext_sampler_destroy)* hsa_ext_sampler_destroy_;
decltype(hsa_ext_image_create_with_layout)* hsa_ext_image_create_with_layout_;
decltype(hsa_ext_image_mipmap_array_get_level)* hsa_ext_image_mipmap_array_get_level_;
};
#ifdef ROCR_DYN_DLL
@@ -523,25 +524,27 @@ class Hsa : public amd::AllStatic {
// Image extensions
static hsa_status_t image_create(hsa_agent_t agent,
const hsa_ext_image_descriptor_t* image_descriptor,
const hsa_ext_image_descriptor_v2_t* image_descriptor,
const hsa_amd_image_descriptor_t* image_layout,
const void* image_data, hsa_access_permission_t access_permission,
hsa_ext_image_t* image) {
return ROCR_DYN(hsa_amd_image_create)(agent, image_descriptor, image_layout, image_data,
access_permission, image);
assert(image_descriptor->mipmap_levels == 1);
return ROCR_DYN(hsa_amd_image_create)(agent,
reinterpret_cast<const hsa_ext_image_descriptor_t*>(image_descriptor),
image_layout, image_data, access_permission, image);
}
static hsa_status_t image_data_get_info(
hsa_agent_t agent, const hsa_ext_image_descriptor_t* image_descriptor,
hsa_agent_t agent, const hsa_ext_image_descriptor_v2_t* image_descriptor,
hsa_access_permission_t access_permission, hsa_ext_image_data_info_t* image_data_info) {
return ROCR_DYN(hsa_ext_image_data_get_info)(agent, image_descriptor, access_permission,
return ROCR_DYN(hsa_ext_image_data_get_info_v2)(agent, image_descriptor, access_permission,
image_data_info);
}
static hsa_status_t image_create(hsa_agent_t agent,
const hsa_ext_image_descriptor_t* image_descriptor,
const hsa_ext_image_descriptor_v2_t* image_descriptor,
const void* image_data,
hsa_access_permission_t access_permission,
hsa_ext_image_t* image) {
return ROCR_DYN(hsa_ext_image_create)(agent, image_descriptor, image_data,
return ROCR_DYN(hsa_ext_image_create_v2)(agent, image_descriptor, image_data,
access_permission, image);
}
static hsa_status_t image_import(hsa_agent_t agent, const void* src_memory,
@@ -559,7 +562,7 @@ class Hsa : public amd::AllStatic {
dst_slice_pitch, image_region);
}
static hsa_status_t image_destroy(hsa_agent_t agent, hsa_ext_image_t image) {
return ROCR_DYN(hsa_ext_image_destroy)(agent, image);
return ROCR_DYN(hsa_ext_image_destroy_v2)(agent, image);
}
static hsa_status_t sampler_create(hsa_agent_t agent,
const hsa_ext_sampler_descriptor_v2_t* sampler_descriptor, hsa_ext_sampler_t* sampler) {
@@ -569,14 +572,20 @@ class Hsa : public amd::AllStatic {
return ROCR_DYN(hsa_ext_sampler_destroy)(agent, sampler);
}
static hsa_status_t image_create_with_layout(
hsa_agent_t agent, const hsa_ext_image_descriptor_t* image_descriptor, const void* image_data,
hsa_agent_t agent, const hsa_ext_image_descriptor_v2_t* image_descriptor, const void* image_data,
hsa_access_permission_t access_permission, hsa_ext_image_data_layout_t image_data_layout,
size_t image_data_row_pitch, size_t image_data_slice_pitch, hsa_ext_image_t* image) {
return ROCR_DYN(hsa_ext_image_create_with_layout)(
agent, image_descriptor, image_data, access_permission, image_data_layout,
agent, reinterpret_cast<const hsa_ext_image_descriptor_t*>(image_descriptor),
image_data, access_permission, image_data_layout,
image_data_row_pitch, image_data_slice_pitch, image);
}
static hsa_status_t image_get_mipmap_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) {
return ROCR_DYN(hsa_ext_image_mipmap_array_get_level)(
agent, mipmapped_array, mip_level, image_descriptor, level_image_out);
}
private:
static RocrEntryPoints cep_;
static bool is_ready_;
@@ -177,6 +177,10 @@ bool Settings::create(bool fullProfile, const amd::Isa& isa, bool enableXNACK, b
gwsInitSupported_ = false;
}
if (GPU_MIPMAP) {
enableExtension(ClKhrMipMapImage);
enableExtension(ClKhrMipMapImageWrites);
}
// Override current device settings
override();
@@ -660,10 +660,10 @@ class Image : public Memory {
//! Returns image's slice pitch in bytes
size_t getSlicePitch() const { return impl_.sp_; }
//! Returns image's slice pitch in bytes
//! Returns image's mipmap levels
uint getMipLevels() const { return mipLevels_; }
//! Returns image's slice pitch in bytes
//! Returns image's mipmap base level
uint getBaseMipLevel() const { return baseMipLevel_; }
//! Get the image covered region
Fájl megtekintése
@@ -82,6 +82,25 @@ set(NOT_FOR_gfx90a_AND_ABOVE_TEST
tex2DLayered.cc
tex3D.cc
tex3DGrad.cc
hipBindTextureToMipmappedArray.cc
hipMallocMipmappedArray.cc
hipFreeMipmappedArray.cc
hipGetMipmappedArrayLevel.cc
hipMipmappedArrayCreate.cc
hipMipmappedArrayDestroy.cc
hipMipmappedArrayGetLevel.cc
hipTextureMipmapObj1D.cc
hipTextureMipmapObj2D.cc
hipTextureMipmapObj3D.cc
tex1DLod.cc
tex1DLayeredLod.cc
tex2DLod.cc
tex2DLayeredLod.cc
tex3DLod.cc
hipTexRefSetGetMipmapFilterMode.cc
hipTexRefSetGetMipmapLevelBias.cc
hipTexRefSetGetMipmapLevelClamp.cc
hipTexRefSetGetMipmappedArray.cc
)
set(gfx90a_AND_ABOVE_TARGETS gfx90a gfx942 gfx950)
@@ -125,33 +144,6 @@ else()
set(TEST_SRC ${TEST_SRC} ${NOT_FOR_gfx90a_AND_ABOVE_TEST})
endif()
# Mipmap APIs are not supported on Linux
if(0)
set(TEST_SRC
${TEST_SRC}
hipBindTextureToMipmappedArray.cc
hipMallocMipmappedArray.cc
hipFreeMipmappedArray.cc
hipGetMipmappedArrayLevel.cc
hipMipmappedArrayCreate.cc
hipMipmappedArrayDestroy.cc
hipMipmappedArrayGetLevel.cc
hipTextureMipmapObj1D.cc
hipTextureMipmapObj2D.cc
hipTextureMipmapObj3D.cc
tex1DLod.cc
tex1DLayeredLod.cc
tex2DLod.cc
tex2DLayeredLod.cc
tex3DLod.cc
hipTexRefSetGetMipmapFilterMode.cc
hipTexRefSetGetMipmapLevelBias.cc
hipTexRefSetGetMipmapLevelClamp.cc
hipTexRefSetGetMipmappedArray.cc
)
endif()
hip_add_exe_to_target(NAME TextureTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests)
@@ -42,11 +42,6 @@ THE SOFTWARE.
TEST_CASE("Unit_hipFreeMipmappedArray_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
#ifdef __linux__
HipTest::HIP_SKIP_TEST("Mipmap APIs are not supported on Linux");
return;
#endif //__linux__
SECTION("array is nullptr") {
HIP_CHECK_ERROR(hipFreeMipmappedArray(nullptr), hipErrorInvalidValue);
}
@@ -42,11 +42,6 @@ THE SOFTWARE.
TEST_CASE("Unit_hipGetMipmappedArrayLevel_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
#ifdef __linux__
HipTest::HIP_SKIP_TEST("Mipmap APIs are not supported on Linux");
return;
#endif //__linux__
hipMipmappedArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
hipExtent extent = make_hipExtent(4, 4, 6);
@@ -42,11 +42,6 @@ THE SOFTWARE.
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
#ifdef __linux__
HipTest::HIP_SKIP_TEST("Mipmap APIs are not supported on Linux");
return;
#endif //__linux__
hipMipmappedArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
hipExtent extent = make_hipExtent(4, 4, 6);
@@ -43,11 +43,6 @@ THE SOFTWARE.
TEST_CASE("Unit_hipMipmappedArrayCreate_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
#ifdef __linux__
HipTest::HIP_SKIP_TEST("Mipmap APIs are not supported on Linux");
return;
#endif //__linux__
hipmipmappedArray array;
HIP_ARRAY3D_DESCRIPTOR desc = {};
@@ -43,13 +43,6 @@ THE SOFTWARE.
TEST_CASE("Unit_hipMipmappedArrayDestroy_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
#ifdef __linux__
HipTest::HIP_SKIP_TEST("Mipmap APIs are not supported on Linux");
return;
#endif //__linux__
HIP_CHECK(hipFree(0));
SECTION("array is nullptr") {
HIP_CHECK_ERROR(hipMipmappedArrayDestroy(nullptr), hipErrorInvalidValue);
}
@@ -43,11 +43,6 @@ THE SOFTWARE.
TEST_CASE("Unit_hipMipmappedArrayGetLevel_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
#ifdef __linux__
HipTest::HIP_SKIP_TEST("Mipmap APIs are not supported on Linux");
return;
#endif //__linux__
hipmipmappedArray array;
HIP_ARRAY3D_DESCRIPTOR desc = {};
@@ -79,6 +74,7 @@ TEST_CASE("Unit_hipMipmappedArrayGetLevel_Negative_Parameters") {
}
HIP_CHECK(hipMipmappedArrayDestroy(array));
(void)hipGetLastError();
}
/**
@@ -246,10 +246,6 @@ TEST_CASE("Unit_TexObjectCreate_TypeArray_NullptrArray") {
#if 0
TEST_CASE("Unit_TexObjectCreate_TypeMipmapped") {
#if __linux__
HipTest::HIP_SKIP_TEST("Mipmap APIs are not supported on Linux");
return;
#endif // __linux__
CHECK_IMAGE_SUPPORT
hipMipmappedArray_t mipmapped_array;
@@ -277,10 +273,6 @@ TEST_CASE("Unit_TexObjectCreate_TypeMipmapped") {
}
TEST_CASE("Unit_TexObjectCreate_TypeMipmaped_IncompleteInit") {
#if __linux__
HipTest::HIP_SKIP_TEST("Mipmap APIs are not supported on Linux");
return;
#endif // __linux__
CHECK_IMAGE_SUPPORT
CTX_CREATE();
@@ -243,8 +243,6 @@ TEST_CASE("Unit_hipGetTextureObjectResourceViewDesc_Negative_Parameters") {
hipGetTextureObjectResourceViewDesc(&check_desc, static_cast<hipTextureObject_t>(0)),
hipErrorInvalidValue);
}
HipTest::HIP_SKIP_TEST("Skipping on NVIDIA platform");
}
#endif
@@ -161,7 +161,7 @@ TEMPLATE_TEST_CASE("Unit_tex2DLayeredLod_Positive_ReadModeNormalizedFloat", "",
y = GetCoordinate(y, params.NumItersY(), params.Height(), params.num_subdivisions,
params.tex_desc.normalizedCoords);
auto ref_val = fixture.tex_h.Tex2DLayered(x, y, layer, params.tex_desc);
if (!fixture.Verify(fixture.out_alloc_h[i], ref_val) {
if (!fixture.Verify(fixture.out_alloc_h[i], ref_val)) {
INFO("Layer: " << layer);
INFO("Filtering mode: " << FilteringModeToString(params.tex_desc.filterMode));
INFO("Normalized coordinates: " << std::boolalpha << params.tex_desc.normalizedCoords);
@@ -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);
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
@@ -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);
@@ -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);
@@ -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.