feat(zebin): add image metadata support

This commit adds support of image metadata in zebin format.

Resolves: NEO-7251

Signed-off-by: Krystian Chmielewski <krystian.chmielewski@intel.com>
This commit is contained in:
Krystian Chmielewski
2022-08-09 17:17:54 +00:00
committed by Compute-Runtime-Automation
parent 3a2d3b9274
commit eecde9114a
4 changed files with 323 additions and 4 deletions

View File

@@ -167,6 +167,8 @@ static constexpr ConstStringRef accessType("access_type");
static constexpr ConstStringRef samplerIndex("sampler_index");
static constexpr ConstStringRef sourceOffset("source_offset");
static constexpr ConstStringRef slmArgAlignment("slm_alignment");
static constexpr ConstStringRef imageType("image_type");
static constexpr ConstStringRef imageTransformable("image_transformable");
namespace ArgType {
static constexpr ConstStringRef localSize("local_size");
static constexpr ConstStringRef groupCount("group_count");
@@ -181,7 +183,25 @@ static constexpr ConstStringRef bufferOffset("buffer_offset");
static constexpr ConstStringRef printfBuffer("printf_buffer");
static constexpr ConstStringRef workDimensions("work_dimensions");
static constexpr ConstStringRef implicitArgBuffer("implicit_arg_buffer");
namespace Image {
static constexpr ConstStringRef width("image_width");
static constexpr ConstStringRef height("image_height");
static constexpr ConstStringRef depth("image_depth");
static constexpr ConstStringRef channelDataType("image_channel_data_type");
static constexpr ConstStringRef channelOrder("image_channel_order");
static constexpr ConstStringRef arraySize("image_array_size");
static constexpr ConstStringRef numSamples("image_num_samples");
static constexpr ConstStringRef numMipLevels("image_mip_levels");
static constexpr ConstStringRef flatBaseOffset("image_flat_base_offset");
static constexpr ConstStringRef flatWidth("image_flat_width");
static constexpr ConstStringRef flatHeight("image_flat_height");
static constexpr ConstStringRef flatPitch("image_flat_pitch");
} // namespace Image
} // namespace ArgType
namespace ImageType {
static constexpr ConstStringRef imageTypeMedia("media");
static constexpr ConstStringRef imageTypeBlock("media_block");
} // namespace ImageType
namespace MemoryAddressingMode {
static constexpr ConstStringRef stateless("stateless");
static constexpr ConstStringRef stateful("stateful");
@@ -378,7 +398,19 @@ enum ArgType : uint8_t {
ArgTypeBufferOffset,
ArgTypePrintfBuffer,
ArgTypeWorkDimensions,
ArgTypeImplicitArgBuffer
ArgTypeImplicitArgBuffer,
ArgTypeImageWidth,
ArgTypeImageHeight,
ArgTypeImageDepth,
ArgTypeImageChannelDataType,
ArgTypeImageChannelOrder,
ArgTypeImageArraySize,
ArgTypeImageNumSamples,
ArgTypeImageMipLevels,
ArgTypeImageFlatBaseOffset,
ArgTypeImageFlatWidth,
ArgTypeImageFlatHeight,
ArgTypeImageFlatPitch
};
namespace PerThreadPayloadArgument {
@@ -424,6 +456,12 @@ enum AccessType : uint8_t {
AccessTypeReadwrite,
};
enum ImageType : uint8_t {
ImageTypeUnknown,
MediaImage,
MediaBlockImage
};
using ArgTypeT = ArgType;
using OffseT = int32_t;
using SourceOffseT = int32_t;
@@ -453,6 +491,8 @@ struct PayloadArgumentBaseT {
AccessTypeT accessType = AccessTypeUnknown;
SamplerIndexT samplerIndex = Defaults::samplerIndex;
SlmAlignmentT slmArgAlignment = Defaults::slmArgAlignment;
ImageType imageType = ImageTypeUnknown;
bool imageTransformable = false;
};
} // namespace PayloadArgument

View File

@@ -444,6 +444,30 @@ bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Ty
out = ArgTypeT::ArgTypeWorkDimensions;
} else if (tokenValue == PayloadArgument::ArgType::implicitArgBuffer) {
out = ArgTypeT::ArgTypeImplicitArgBuffer;
} else if (tokenValue == PayloadArgument::ArgType::Image::width) {
out = ArgTypeT::ArgTypeImageWidth;
} else if (tokenValue == PayloadArgument::ArgType::Image::height) {
out = ArgTypeT::ArgTypeImageHeight;
} else if (tokenValue == PayloadArgument::ArgType::Image::depth) {
out = ArgTypeT::ArgTypeImageDepth;
} else if (tokenValue == PayloadArgument::ArgType::Image::channelDataType) {
out = ArgTypeT::ArgTypeImageChannelDataType;
} else if (tokenValue == PayloadArgument::ArgType::Image::channelOrder) {
out = ArgTypeT::ArgTypeImageChannelOrder;
} else if (tokenValue == PayloadArgument::ArgType::Image::arraySize) {
out = ArgTypeT::ArgTypeImageArraySize;
} else if (tokenValue == PayloadArgument::ArgType::Image::numSamples) {
out = ArgTypeT::ArgTypeImageNumSamples;
} else if (tokenValue == PayloadArgument::ArgType::Image::numMipLevels) {
out = ArgTypeT::ArgTypeImageMipLevels;
} else if (tokenValue == PayloadArgument::ArgType::Image::flatBaseOffset) {
out = ArgTypeT::ArgTypeImageFlatBaseOffset;
} else if (tokenValue == PayloadArgument::ArgType::Image::flatWidth) {
out = ArgTypeT::ArgTypeImageFlatWidth;
} else if (tokenValue == PayloadArgument::ArgType::Image::flatHeight) {
out = ArgTypeT::ArgTypeImageFlatHeight;
} else if (tokenValue == PayloadArgument::ArgType::Image::flatPitch) {
out = ArgTypeT::ArgTypeImageFlatPitch;
} else {
outErrReason.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unhandled \"" + tokenValue.str() + "\" argument type in context of " + context.str() + "\n");
return false;
@@ -533,6 +557,27 @@ bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Ty
return true;
}
bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::ImageType &out, ConstStringRef context, std::string &outErrReason) {
if (nullptr == token) {
return false;
}
using namespace NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PayloadArgument::ImageType;
using ImageType = NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::ImageType;
auto tokenValue = token->cstrref();
if (imageTypeMedia == tokenValue) {
out = ImageType::MediaImage;
} else if (imageTypeBlock == tokenValue) {
out = ImageType::MediaBlockImage;
} else {
outErrReason.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unhandled \"" + tokenValue.str() + "\" image type in context of " + context.str() + "\n");
return false;
}
return true;
}
bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::AllocationType &out,
ConstStringRef context, std::string &outErrReason) {
if (nullptr == token) {
@@ -651,6 +696,11 @@ DecodeError readZeInfoPayloadArguments(const NEO::Yaml::YamlParser &parser, cons
validPayload &= readZeInfoValueChecked(parser, payloadArgumentMemberNd, payloadArgMetadata.sourceOffset, context, outErrReason);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PayloadArgument::slmArgAlignment == key) {
validPayload &= readZeInfoValueChecked(parser, payloadArgumentMemberNd, payloadArgMetadata.slmArgAlignment, context, outErrReason);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PayloadArgument::imageType == key) {
auto imageTypeToken = parser.getValueToken(payloadArgumentMemberNd);
validPayload &= readEnumChecked(imageTypeToken, payloadArgMetadata.imageType, context, outErrReason);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PayloadArgument::imageTransformable == key) {
validPayload &= readZeInfoValueChecked(parser, payloadArgumentMemberNd, payloadArgMetadata.imageTransformable, context, outErrReason);
} else {
outWarning.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unknown entry \"" + key.str() + "\" for payload argument in context of " + context.str() + "\n");
}
@@ -857,9 +907,13 @@ NEO::DecodeError populateArgDescriptor(const NEO::Elf::ZebinKernelMetadata::Type
argTraits.addressQualifier = KernelArgMetadata::AddrConstant;
dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescPointer>(true);
break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::AddressSpaceImage:
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::AddressSpaceImage: {
dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>(true);
break;
auto &extendedInfo = dst.payloadMappings.explicitArgs[src.argIndex].getExtendedTypeInfo();
extendedInfo.isMediaImage = (src.imageType == NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::ImageType::MediaImage);
extendedInfo.isMediaBlockImage = (src.imageType == NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::ImageType::MediaBlockImage);
extendedInfo.isTransformable = src.imageTransformable;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::AddressSpaceSampler:
static constexpr auto maxSamplerStateSize = 16U;
static constexpr auto maxIndirectSamplerStateSize = 64U;
@@ -1015,8 +1069,67 @@ NEO::DecodeError populateArgDescriptor(const NEO::Elf::ZebinKernelMetadata::Type
dst.kernelAttributes.flags.requiresImplicitArgs = true;
break;
}
}
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageHeight: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.imgHeight = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageWidth: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.imgWidth = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageDepth: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.imgDepth = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageChannelDataType: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.channelDataType = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageChannelOrder: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.channelOrder = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageArraySize: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.arraySize = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageNumSamples: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.numSamples = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageMipLevels: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.numMipLevels = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageFlatBaseOffset: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.flatBaseOffset = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageFlatWidth: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.flatWidth = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageFlatHeight: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.flatHeight = src.offset;
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeImageFlatPitch: {
auto &arg = dst.payloadMappings.explicitArgs[src.argIndex].as<ArgDescImage>();
arg.metadataPayload.flatPitch = src.offset;
} break;
}
return DecodeError::Success;
}

View File

@@ -72,6 +72,8 @@ bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Ty
ConstStringRef context, std::string &outErrReason);
bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::AccessType &out,
ConstStringRef context, std::string &outErrReason);
bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::ImageType &out,
ConstStringRef context, std::string &outErrReason);
bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::AllocationType &out,
ConstStringRef context, std::string &outErrReason);
bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::MemoryUsage &out,

View File

@@ -1814,6 +1814,48 @@ TEST(ReadEnumCheckedMemoryUsage, GivenUnknownStringRepresentationThenFail) {
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Unhandled \"some_entry\" per-thread memory buffer usage type in context of some_kernel\n", errors.c_str());
}
TEST(ReadEnumCheckedImageType, GiveValidStringRepresentationThenParseItCorrectly) {
using namespace NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PayloadArgument::ImageType;
NEO::Yaml::Token tokMedia(imageTypeMedia, NEO::Yaml::Token::Token::LiteralString);
NEO::Yaml::Token tokBlock(imageTypeBlock, NEO::Yaml::Token::Token::LiteralString);
using ImageType = NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::ImageType;
ImageType enumMedia, enumBlock;
std::string errors;
bool success;
success = NEO::readEnumChecked(&tokMedia, enumMedia, "some_kernel", errors);
EXPECT_TRUE(success);
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_EQ(ImageType::MediaImage, enumMedia);
success = NEO::readEnumChecked(&tokBlock, enumBlock, "some_kernel", errors);
EXPECT_TRUE(success);
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_EQ(ImageType::MediaBlockImage, enumBlock);
}
TEST(ReadEnumCheckedImageType, GivenNullTokenThenFail) {
using ImageType = NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::ImageType;
ImageType enumRepresentation;
std::string errors;
bool success = NEO::readEnumChecked(nullptr, enumRepresentation, "some_kernel", errors);
EXPECT_FALSE(success);
}
TEST(ReadEnumCheckedImageType, GivenUnknownStringRepresentationThenFail) {
using ImageType = NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::ImageType;
ImageType enumRepresentation;
std::string errors;
NEO::Yaml::Token someEntry("some_entry", NEO::Yaml::Token::Token::LiteralString);
bool success = NEO::readEnumChecked(&someEntry, enumRepresentation, "some_kernel", errors);
EXPECT_FALSE(success);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Unhandled \"some_entry\" image type in context of some_kernel\n", errors.c_str());
}
TEST(ReadZeInfoPerThreadPayloadArguments, GivenValidYamlEntriesThenSetProperMembers) {
NEO::ConstStringRef yaml = R"===(---
kernels:
@@ -5243,6 +5285,128 @@ TEST(PopulateArgDescriptorCrossthreadPayload, GivenArgTypePrintfBufferWhenOffset
ASSERT_EQ(32U, printfSurfaceAddress.stateless);
EXPECT_EQ(8U, printfSurfaceAddress.pointerSize);
}
TEST(PopulateArgDescriptorCrossthreadPayload, GivenValidImageArgumentWithImageMetadataThenPopulatesKernelDescriptor) {
NEO::ConstStringRef zeinfo = R"===(
kernels:
- name : some_kernel
execution_env:
simd_size: 32
payload_arguments:
- arg_type: arg_bypointer
offset: 0
size: 0
arg_index: 0
addrmode: stateful
addrspace: image
access_type: readwrite
image_type: media
image_transformable: true
- arg_type: arg_bypointer
offset: 0
size: 0
arg_index: 1
addrmode: stateful
addrspace: image
access_type: readwrite
image_type: media_block
- arg_type: image_height
offset: 0
size: 4
arg_index: 1
- arg_type: image_width
offset: 4
size: 4
arg_index: 1
- arg_type: image_depth
offset: 8
size: 4
arg_index: 1
- arg_type: image_channel_data_type
offset: 12
size: 4
arg_index: 1
- arg_type: image_channel_order
offset: 16
size: 4
arg_index: 1
- arg_type: image_array_size
offset: 20
size: 4
arg_index: 1
- arg_type: image_num_samples
offset: 24
size: 4
arg_index: 1
- arg_type: image_mip_levels
offset: 28
size: 4
arg_index: 1
- arg_type: image_flat_base_offset
offset: 32
size: 8
arg_index: 1
- arg_type: image_flat_width
offset: 40
size: 4
arg_index: 1
- arg_type: image_flat_height
offset: 44
size: 4
arg_index: 1
- arg_type: image_flat_pitch
offset: 48
size: 4
arg_index: 1
binding_table_indices:
- bti_value: 1
arg_index: 0
- bti_value: 2
arg_index: 1
)===";
NEO::ProgramInfo programInfo;
ZebinTestData::ValidEmptyProgram zebin;
zebin.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "some_kernel", {});
std::string errors, warnings;
auto elf = NEO::Elf::decodeElf(zebin.storage, errors, warnings);
ASSERT_NE(nullptr, elf.elfFileHeader) << errors << " " << warnings;
NEO::Yaml::YamlParser parser;
bool parseSuccess = parser.parse(zeinfo, errors, warnings);
ASSERT_TRUE(parseSuccess) << errors << " " << warnings;
NEO::ZebinSections zebinSections;
auto extractErr = NEO::extractZebinSections(elf, zebinSections, errors, warnings);
ASSERT_EQ(NEO::DecodeError::Success, extractErr) << errors << " " << warnings;
auto &kernelNode = *parser.createChildrenRange(*parser.findNodeWithKeyDfs("kernels")).begin();
auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
auto &args = programInfo.kernelInfos[0]->kernelDescriptor.payloadMappings.explicitArgs;
EXPECT_EQ(64U, args[0].as<ArgDescImage>().bindful);
EXPECT_TRUE(args[0].getExtendedTypeInfo().isMediaImage);
EXPECT_TRUE(args[0].getExtendedTypeInfo().isTransformable);
EXPECT_EQ(128U, args[1].as<ArgDescImage>().bindful);
EXPECT_TRUE(args[1].getExtendedTypeInfo().isMediaBlockImage);
EXPECT_FALSE(args[1].getExtendedTypeInfo().isTransformable);
const auto &imgMetadata = args[1].as<ArgDescImage>().metadataPayload;
EXPECT_EQ(0U, imgMetadata.imgHeight);
EXPECT_EQ(4U, imgMetadata.imgWidth);
EXPECT_EQ(8U, imgMetadata.imgDepth);
EXPECT_EQ(12U, imgMetadata.channelDataType);
EXPECT_EQ(16U, imgMetadata.channelOrder);
EXPECT_EQ(20U, imgMetadata.arraySize);
EXPECT_EQ(24U, imgMetadata.numSamples);
EXPECT_EQ(28U, imgMetadata.numMipLevels);
EXPECT_EQ(32U, imgMetadata.flatBaseOffset);
EXPECT_EQ(40U, imgMetadata.flatWidth);
EXPECT_EQ(44U, imgMetadata.flatHeight);
EXPECT_EQ(48U, imgMetadata.flatPitch);
}
class IntelGTNotesFixture : public ::testing::Test {
protected:
void SetUp() override {