feat(zebin): support data const/global buffer arg

Add support for kernel payload arguments describing data const and
data global buffers in zeInfo.

Argument contains:
* Offset in cross thread data where buffer's address should be written to.
To be removed later. Relocations should be used instead.
* Index in binding table where corresponding Surface State should be present.
Required for bindful access to data buffers.

Signed-off-by: Krystian Chmielewski <krystian.chmielewski@intel.com>
This commit is contained in:
Krystian Chmielewski 2022-12-14 09:46:25 +00:00 committed by Compute-Runtime-Automation
parent 46136cd2f6
commit b2a51146a5
4 changed files with 133 additions and 7 deletions

View File

@ -201,6 +201,7 @@ inline constexpr ConstStringRef filterMode("sampler_desc_filtermode");
inline constexpr ConstStringRef normalized("sampler_desc_normalized");
inline constexpr ConstStringRef isPipe("is_pipe");
inline constexpr ConstStringRef isPtr("is_ptr");
inline constexpr ConstStringRef btiValue("bti_value");
namespace ArgType {
inline constexpr ConstStringRef localSize("local_size");
@ -218,6 +219,8 @@ inline constexpr ConstStringRef workDimensions("work_dimensions");
inline constexpr ConstStringRef implicitArgBuffer("implicit_arg_buffer");
inline constexpr ConstStringRef syncBuffer("sync_buffer");
inline constexpr ConstStringRef rtGlobalBuffer("rt_global_buffer");
inline constexpr ConstStringRef dataConstBuffer("const_base");
inline constexpr ConstStringRef dataGlobalBuffer("global_base");
namespace Image {
inline constexpr ConstStringRef width("image_width");
@ -579,6 +582,8 @@ enum ArgType : uint8_t {
ArgTypeVmeSearchPathType,
ArgTypeSyncBuffer,
ArgTypeRtGlobalBuffer,
ArgTypeDataConstBuffer,
ArgTypeDataGlobalBuffer,
ArgTypeMax
};
@ -667,7 +672,7 @@ enum SamplerType : uint8_t {
};
using ArgTypeT = ArgType;
using OffseT = int32_t;
using OffsetT = int32_t;
using SourceOffseT = int32_t;
using SizeT = int32_t;
using ArgIndexT = int32_t;
@ -676,28 +681,32 @@ using AddrspaceT = AddressSpace;
using AccessTypeT = AccessType;
using SlmAlignmentT = uint8_t;
using SamplerIndexT = int32_t;
using BtiValueT = int32_t;
namespace Defaults {
inline constexpr ArgIndexT argIndex = -1;
inline constexpr SlmAlignmentT slmArgAlignment = 16U;
inline constexpr SamplerIndexT samplerIndex = -1;
inline constexpr SourceOffseT sourceOffset = -1;
inline constexpr OffsetT offset = -1;
inline constexpr BtiValueT btiValue = -1;
} // namespace Defaults
struct PayloadArgumentBaseT {
ArgTypeT argType = ArgTypeUnknown;
OffseT offset = 0;
OffsetT offset = Defaults::offset;
SourceOffseT sourceOffset = Defaults::sourceOffset;
SizeT size = 0;
ArgIndexT argIndex = Defaults::argIndex;
BtiValueT btiValue = Defaults::btiValue;
AddrmodeT addrmode = MemoryAddressingModeUnknown;
AddrspaceT addrspace = AddressSpaceUnknown;
AccessTypeT accessType = AccessTypeUnknown;
SamplerIndexT samplerIndex = Defaults::samplerIndex;
SlmAlignmentT slmArgAlignment = Defaults::slmArgAlignment;
ImageType imageType = ImageTypeUnknown;
bool imageTransformable = false;
SamplerType samplerType = SamplerTypeUnknown;
bool imageTransformable = false;
bool isPipe = false;
bool isPtr = false;
};

View File

@ -22,7 +22,7 @@ using namespace Tags::Kernel::PayloadArgument::ArgType::Sampler::Vme;
using ArgType = Types::Kernel::ArgType;
inline constexpr ConstStringRef name = "argument type";
inline constexpr LookupArray<ConstStringRef, ArgType, 36> lookup({{{packedLocalIds, ArgType::ArgTypePackedLocalIds},
inline constexpr LookupArray<ConstStringRef, ArgType, 38> lookup({{{packedLocalIds, ArgType::ArgTypePackedLocalIds},
{localId, ArgType::ArgTypeLocalId},
{localSize, ArgType::ArgTypeLocalSize},
{groupCount, ArgType::ArgTypeGroupCount},
@ -57,7 +57,9 @@ inline constexpr LookupArray<ConstStringRef, ArgType, 36> lookup({{{packedLocalI
{sadAdjustMode, ArgType::ArgTypeVmeSadAdjustMode},
{searchPathType, ArgType::ArgTypeVmeSearchPathType},
{syncBuffer, ArgType::ArgTypeSyncBuffer},
{rtGlobalBuffer, ArgType::ArgTypeRtGlobalBuffer}}});
{rtGlobalBuffer, ArgType::ArgTypeRtGlobalBuffer},
{dataConstBuffer, ArgType::ArgTypeDataConstBuffer},
{dataGlobalBuffer, ArgType::ArgTypeDataGlobalBuffer}}});
static_assert(lookup.size() == ArgType::ArgTypeMax - 1, "Every enum field must be present");
} // namespace ArgType

View File

@ -593,6 +593,8 @@ DecodeError readZeInfoPayloadArguments(const NEO::Yaml::YamlParser &parser, cons
validPayload &= readZeInfoValueChecked(parser, payloadArgumentMemberNd, payloadArgMetadata.isPipe, context, outErrReason);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PayloadArgument::isPtr == key) {
validPayload &= readZeInfoValueChecked(parser, payloadArgumentMemberNd, payloadArgMetadata.isPtr, context, outErrReason);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PayloadArgument::btiValue == key) {
validPayload &= readZeInfoValueChecked(parser, payloadArgumentMemberNd, payloadArgMetadata.btiValue, 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");
}
@ -720,6 +722,15 @@ bool setVecArgIndicesBasedOnSize(CrossThreadDataOffset (&vec)[Len], size_t vecSi
return true;
}
bool setSSHOffsetBasedOnBti(SurfaceStateHeapOffset &offset, Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::BtiValueT bti) {
if (bti < 0) {
return false;
}
constexpr auto surfaceStateSize = 64U;
offset = surfaceStateSize * bti;
return true;
}
NEO::DecodeError populateArgDescriptor(const NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadPayloadArgument::PerThreadPayloadArgumentBaseT &src, NEO::KernelDescriptor &dst, uint32_t grfSize,
std::string &outErrReason, std::string &outWarning) {
switch (src.argType) {
@ -791,7 +802,9 @@ NEO::DecodeError populateArgDescriptor(const NEO::Elf::ZebinKernelMetadata::Type
NEO::DecodeError populateArgDescriptor(const NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::PayloadArgumentBaseT &src, NEO::KernelDescriptor &dst, uint32_t &crossThreadDataSize,
std::string &outErrReason, std::string &outWarning) {
if (src.offset != Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::Defaults::offset) {
crossThreadDataSize = std::max<uint32_t>(crossThreadDataSize, src.offset + src.size);
}
auto &explicitArgs = dst.payloadMappings.explicitArgs;
auto getVmeDescriptor = [&src, &dst]() {
@ -1104,6 +1117,28 @@ NEO::DecodeError populateArgDescriptor(const NEO::Elf::ZebinKernelMetadata::Type
dst.payloadMappings.implicitArgs.rtDispatchGlobals.stateless = src.offset;
dst.kernelAttributes.flags.hasRTCalls = true;
break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeDataConstBuffer: {
if (src.offset != Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::Defaults::offset) {
dst.payloadMappings.implicitArgs.globalConstantsSurfaceAddress.stateless = src.offset;
dst.payloadMappings.implicitArgs.globalConstantsSurfaceAddress.pointerSize = src.size;
}
if (false == setSSHOffsetBasedOnBti(dst.payloadMappings.implicitArgs.globalConstantsSurfaceAddress.bindful, src.btiValue)) {
outErrReason.append("DeviceBinaryFormat::Zebin : Invalid bti for argument of type " + NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PayloadArgument::ArgType::dataConstBuffer.str() + " in context of : " + dst.kernelMetadata.kernelName + "\n");
return DecodeError::InvalidBinary;
}
} break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeDataGlobalBuffer: {
if (src.offset != Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::Defaults::offset) {
dst.payloadMappings.implicitArgs.globalVariablesSurfaceAddress.stateless = src.offset;
dst.payloadMappings.implicitArgs.globalVariablesSurfaceAddress.pointerSize = src.size;
}
if (false == setSSHOffsetBasedOnBti(dst.payloadMappings.implicitArgs.globalVariablesSurfaceAddress.bindful, src.btiValue)) {
outErrReason.append("DeviceBinaryFormat::Zebin : Invalid bti for argument of type " + NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PayloadArgument::ArgType::dataGlobalBuffer.str() + " in context of : " + dst.kernelMetadata.kernelName + "\n");
return DecodeError::InvalidBinary;
}
} break;
}
return DecodeError::Success;

View File

@ -2181,6 +2181,10 @@ kernels:
size : 4
arg_index : 2
is_ptr : true
- arg_type : const_base
offset : 32
size : 8
bti_value : 1
...
)===";
@ -2200,7 +2204,7 @@ kernels:
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
ASSERT_EQ(2U, args.size());
ASSERT_EQ(3U, args.size());
EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeArgBypointer, args[0].argType);
EXPECT_EQ(16, args[0].offset);
@ -2213,7 +2217,13 @@ kernels:
EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeArgByvalue, args[1].argType);
EXPECT_EQ(24, args[1].offset);
EXPECT_EQ(4, args[1].size);
EXPECT_EQ(2, args[1].argIndex);
EXPECT_TRUE(args[1].isPtr);
EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeDataConstBuffer, args[2].argType);
EXPECT_EQ(32, args[2].offset);
EXPECT_EQ(8, args[2].size);
EXPECT_EQ(1, args[2].btiValue);
}
TEST(ReadZeInfoPayloadArguments, GivenUnknownEntryThenEmmitsWarning) {
@ -5648,6 +5658,76 @@ TEST(PopulateArgDescriptor, GivenValidArgOfTypeRTGlobalBufferThenRtGlobalBufferI
EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.hasRTCalls);
}
TEST(PopulateArgDescriptor, GivenValidConstDataBufferArgThenItIsPopulatedCorrectly) {
NEO::KernelDescriptor kernelDescriptor;
NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::PayloadArgumentBaseT dataConstBuffer;
dataConstBuffer.argType = NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeDataConstBuffer;
dataConstBuffer.size = 8;
dataConstBuffer.offset = 32;
dataConstBuffer.btiValue = 1;
uint32_t crossThreadDataSize = 0U;
std::string errors, warnings;
auto err = NEO::populateArgDescriptor(dataConstBuffer, kernelDescriptor, crossThreadDataSize, errors, warnings);
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty());
EXPECT_TRUE(warnings.empty());
EXPECT_EQ(40U, crossThreadDataSize);
EXPECT_EQ(8U, kernelDescriptor.payloadMappings.implicitArgs.globalConstantsSurfaceAddress.pointerSize);
EXPECT_EQ(32U, kernelDescriptor.payloadMappings.implicitArgs.globalConstantsSurfaceAddress.stateless);
EXPECT_EQ(64U, kernelDescriptor.payloadMappings.implicitArgs.globalConstantsSurfaceAddress.bindful);
}
TEST(PopulateArgDescriptor, GivenInvalidConstDataBufferArgThenErrorIsReturned) {
NEO::KernelDescriptor kernelDescriptor;
kernelDescriptor.kernelMetadata.kernelName = "kernel";
NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::PayloadArgumentBaseT dataConstBuffer;
dataConstBuffer.argType = NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeDataConstBuffer;
dataConstBuffer.btiValue = -1;
uint32_t crossThreadDataSize = 0U;
std::string errors, warnings;
auto err = NEO::populateArgDescriptor(dataConstBuffer, kernelDescriptor, crossThreadDataSize, errors, warnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_TRUE(warnings.empty());
EXPECT_STREQ("DeviceBinaryFormat::Zebin : Invalid bti for argument of type const_base in context of : kernel\n", errors.c_str());
}
TEST(PopulateArgDescriptor, GivenValidGlobalDataBufferArgThenItIsPopulatedCorrectly) {
NEO::KernelDescriptor kernelDescriptor;
NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::PayloadArgumentBaseT dataGlobalBuffer;
dataGlobalBuffer.argType = NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeDataGlobalBuffer;
dataGlobalBuffer.size = 8;
dataGlobalBuffer.offset = 32;
dataGlobalBuffer.btiValue = 1;
uint32_t crossThreadDataSize = 0U;
std::string errors, warnings;
auto err = NEO::populateArgDescriptor(dataGlobalBuffer, kernelDescriptor, crossThreadDataSize, errors, warnings);
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty());
EXPECT_TRUE(warnings.empty());
EXPECT_EQ(40U, crossThreadDataSize);
EXPECT_EQ(8U, kernelDescriptor.payloadMappings.implicitArgs.globalVariablesSurfaceAddress.pointerSize);
EXPECT_EQ(32U, kernelDescriptor.payloadMappings.implicitArgs.globalVariablesSurfaceAddress.stateless);
EXPECT_EQ(64U, kernelDescriptor.payloadMappings.implicitArgs.globalVariablesSurfaceAddress.bindful);
}
TEST(PopulateArgDescriptor, GivenInvalidGlobalDataBufferArgThenErrorIsReturned) {
NEO::KernelDescriptor kernelDescriptor;
kernelDescriptor.kernelMetadata.kernelName = "kernel";
NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::PayloadArgumentBaseT dataGlobalBuffer;
dataGlobalBuffer.argType = NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgTypeDataGlobalBuffer;
dataGlobalBuffer.btiValue = -1;
uint32_t crossThreadDataSize = 0U;
std::string errors, warnings;
auto err = NEO::populateArgDescriptor(dataGlobalBuffer, kernelDescriptor, crossThreadDataSize, errors, warnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_TRUE(warnings.empty());
EXPECT_STREQ("DeviceBinaryFormat::Zebin : Invalid bti for argument of type global_base in context of : kernel\n", errors.c_str());
}
TEST(PopulateArgDescriptorCrossthreadPayload, GivenArgTypePrintfBufferWhenOffsetAndSizeIsValidThenPopulatesKernelDescriptor) {
NEO::ConstStringRef zeinfo = R"===(
kernels: