[spirv] Add support for VK_EXT_scalar_block_layout (#1716)
Ref: https://github.com/KhronosGroup/Vulkan-Docs/issues/854
This commit is contained in:
Родитель
e9dac9bd79
Коммит
7a2a95e36c
|
@ -803,7 +803,7 @@ To know more about the Vulkan buffer types, please refer to the Vulkan spec
|
|||
Memory layout rules
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
SPIR-V CodeGen supports three sets of memory layout rules for buffer resources
|
||||
SPIR-V CodeGen supports four sets of memory layout rules for buffer resources
|
||||
right now:
|
||||
|
||||
1. Vector-relaxed OpenGL ``std140`` for uniform buffers and vector-relaxed
|
||||
|
@ -817,6 +817,14 @@ right now:
|
|||
3. Strict OpenGL ``std140`` for uniform buffers and strict OpenGL ``std430``
|
||||
for storage buffers: they allow packing data on the application side that
|
||||
can be shared with OpenGL. They can be enabled by ``-fvk-use-gl-layout``.
|
||||
4. Scalar layout rules introduced via `VK_EXT_scalar_block_layout`, which
|
||||
basically aligns all aggregrate types according to their elements'
|
||||
natural alignment. They can be enabled by ``-fvk-use-scalar-layout``.
|
||||
|
||||
To use scalar layout, the application side need to request
|
||||
``VK_EXT_scalar_block_layout``. This is also true for using DirectX memory
|
||||
layout since there is no dedicated DirectX layout extension for Vulkan
|
||||
(at least for now). So we must request something more permissive.
|
||||
|
||||
In the above, "vector-relaxed OpenGL ``std140``/``std430``" rules mean OpenGL
|
||||
``std140``/``std430`` rules with the following modification for vector type
|
||||
|
@ -846,19 +854,19 @@ As an exmaple, for the following HLSL definition:
|
|||
|
||||
We will have the following offsets for each member:
|
||||
|
||||
============== ====== ====== ====== ====== ====== ======
|
||||
HLSL Uniform Buffer Storage Buffer
|
||||
-------------- -------------------- --------------------
|
||||
Member 1 (VK) 2 (DX) 3 (GL) 1 (VK) 2 (DX) 3 (GL)
|
||||
============== ====== ====== ====== ====== ====== ======
|
||||
``a_float`` 0 0 0 0 0 0
|
||||
``b_float3`` 4 4 16 4 4 16
|
||||
``c_S_float3`` 16 16 32 16 16 32
|
||||
``d_float2x3`` 32 32 48 32 28 48
|
||||
``e_float2x3`` 80 80 96 64 52 80
|
||||
``f_int_3`` 112 112 128 96 76 112
|
||||
``g_float2_2`` 160 160 176 112 88 128
|
||||
============== ====== ====== ====== ====== ====== ======
|
||||
============== ====== ====== ====== ========== ====== ====== ====== ==========
|
||||
HLSL Uniform Buffer Storage Buffer
|
||||
-------------- ------------------------------- -------------------------------
|
||||
Member 1 (VK) 2 (DX) 3 (GL) 4 (Scalar) 1 (VK) 2 (DX) 3 (GL) 4 (Scalar)
|
||||
============== ====== ====== ====== ========== ====== ====== ====== ==========
|
||||
``a_float`` 0 0 0 0 0 0 0 0
|
||||
``b_float3`` 4 4 16 4 4 4 16 4
|
||||
``c_S_float3`` 16 16 32 16 16 16 32 16
|
||||
``d_float2x3`` 32 32 48 28 32 28 48 28
|
||||
``e_float2x3`` 80 80 96 52 64 52 80 52
|
||||
``f_int_3`` 112 112 128 76 96 76 112 76
|
||||
``g_float2_2`` 160 160 176 88 112 88 128 88
|
||||
============== ====== ====== ====== ========== ====== ====== ====== ==========
|
||||
|
||||
If the above layout rules do not satisfy your needs and you want to manually
|
||||
control the layout of struct members, you can use either
|
||||
|
|
|
@ -263,6 +263,8 @@ def fvk_use_gl_layout: Flag<["-"], "fvk-use-gl-layout">, Group<spirv_Group>, Fla
|
|||
HelpText<"Use strict OpenGL std140/std430 memory layout for Vulkan resources">;
|
||||
def fvk_use_dx_layout: Flag<["-"], "fvk-use-dx-layout">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
|
||||
HelpText<"Use DirectX memory layout for Vulkan resources">;
|
||||
def fvk_use_scalar_layout: Flag<["-"], "fvk-use-scalar-layout">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
|
||||
HelpText<"Use scalar memory layout for Vulkan resources">;
|
||||
def fspv_reflect: Flag<["-"], "fspv-reflect">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
|
||||
HelpText<"Emit additional SPIR-V instructions to aid reflection">;
|
||||
def fspv_debug_EQ : Joined<["-"], "fspv-debug=">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
|
||||
|
|
|
@ -31,6 +31,7 @@ enum class SpirvLayoutRule {
|
|||
RelaxedGLSLStd430, // std430 with relaxed vector layout
|
||||
FxcCTBuffer, // fxc.exe layout rule for cbuffer/tbuffer
|
||||
FxcSBuffer, // fxc.exe layout rule for structured buffers
|
||||
Scalar, // VK_EXT_scalar_block_layout
|
||||
};
|
||||
|
||||
struct SpirvCodeGenOptions {
|
||||
|
@ -50,6 +51,7 @@ struct SpirvCodeGenOptions {
|
|||
bool noWarnIgnoredFeatures;
|
||||
bool useDxLayout;
|
||||
bool useGlLayout;
|
||||
bool useScalarLayout;
|
||||
SpirvLayoutRule cBufferLayoutRule;
|
||||
SpirvLayoutRule sBufferLayoutRule;
|
||||
SpirvLayoutRule tBufferLayoutRule;
|
||||
|
|
|
@ -636,6 +636,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
|
|||
opts.SpirvOptions.invertW = Args.hasFlag(OPT_fvk_use_dx_position_w, OPT_INVALID, false);
|
||||
opts.SpirvOptions.useGlLayout = Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false);
|
||||
opts.SpirvOptions.useDxLayout = Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false);
|
||||
opts.SpirvOptions.useScalarLayout = Args.hasFlag(OPT_fvk_use_scalar_layout, OPT_INVALID, false);
|
||||
opts.SpirvOptions.enableReflect = Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false);
|
||||
opts.SpirvOptions.noWarnIgnoredFeatures = Args.hasFlag(OPT_Wno_vk_ignored_features, OPT_INVALID, false);
|
||||
opts.SpirvOptions.noWarnEmulatedFeatures = Args.hasFlag(OPT_Wno_vk_emulated_features, OPT_INVALID, false);
|
||||
|
@ -711,6 +712,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
|
|||
Args.hasFlag(OPT_fvk_use_dx_position_w, OPT_INVALID, false) ||
|
||||
Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false) ||
|
||||
Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false) ||
|
||||
Args.hasFlag(OPT_fvk_use_scalar_layout, OPT_INVALID, false) ||
|
||||
Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false) ||
|
||||
Args.hasFlag(OPT_Wno_vk_ignored_features, OPT_INVALID, false) ||
|
||||
Args.hasFlag(OPT_Wno_vk_emulated_features, OPT_INVALID, false) ||
|
||||
|
|
|
@ -242,9 +242,9 @@ bool spirvToolsOptimize(spv_target_env env, std::vector<uint32_t> *module,
|
|||
return optimizer.Run(module->data(), module->size(), module, options);
|
||||
}
|
||||
|
||||
bool spirvToolsValidate(spv_target_env env, std::vector<uint32_t> *module,
|
||||
std::string *messages, bool relaxLogicalPointer,
|
||||
bool glLayout, bool dxLayout) {
|
||||
bool spirvToolsValidate(spv_target_env env, const SpirvCodeGenOptions &opts,
|
||||
bool relaxLogicalPointer, std::vector<uint32_t> *module,
|
||||
std::string *messages) {
|
||||
spvtools::SpirvTools tools(env);
|
||||
|
||||
tools.SetMessageConsumer(
|
||||
|
@ -257,8 +257,13 @@ bool spirvToolsValidate(spv_target_env env, std::vector<uint32_t> *module,
|
|||
// GL: strict block layout rules
|
||||
// VK: relaxed block layout rules
|
||||
// DX: Skip block layout rules
|
||||
options.SetRelaxBlockLayout(!glLayout && !dxLayout);
|
||||
options.SetSkipBlockLayout(dxLayout);
|
||||
if (opts.useScalarLayout || opts.useDxLayout) {
|
||||
options.SetSkipBlockLayout(true);
|
||||
} else if (opts.useGlLayout) {
|
||||
// spirv-val by default checks this.
|
||||
} else {
|
||||
options.SetRelaxBlockLayout(true);
|
||||
}
|
||||
|
||||
return tools.Validate(module->data(), module->size(), options);
|
||||
}
|
||||
|
@ -625,6 +630,10 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci)
|
|||
spirvOptions.cBufferLayoutRule = SpirvLayoutRule::GLSLStd140;
|
||||
spirvOptions.tBufferLayoutRule = SpirvLayoutRule::GLSLStd430;
|
||||
spirvOptions.sBufferLayoutRule = SpirvLayoutRule::GLSLStd430;
|
||||
} else if (spirvOptions.useScalarLayout) {
|
||||
spirvOptions.cBufferLayoutRule = SpirvLayoutRule::Scalar;
|
||||
spirvOptions.tBufferLayoutRule = SpirvLayoutRule::Scalar;
|
||||
spirvOptions.sBufferLayoutRule = SpirvLayoutRule::Scalar;
|
||||
} else {
|
||||
spirvOptions.cBufferLayoutRule = SpirvLayoutRule::RelaxedGLSLStd140;
|
||||
spirvOptions.tBufferLayoutRule = SpirvLayoutRule::RelaxedGLSLStd430;
|
||||
|
@ -736,9 +745,9 @@ void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
|
|||
// Validate the generated SPIR-V code
|
||||
if (!spirvOptions.disableValidation) {
|
||||
std::string messages;
|
||||
if (!spirvToolsValidate(
|
||||
targetEnv, &m, &messages, declIdMapper.requiresLegalization(),
|
||||
spirvOptions.useGlLayout, spirvOptions.useDxLayout)) {
|
||||
if (!spirvToolsValidate(targetEnv, spirvOptions,
|
||||
declIdMapper.requiresLegalization(), &m,
|
||||
&messages)) {
|
||||
emitFatalError("generated SPIR-V is invalid: %0", {}) << messages;
|
||||
emitNote("please file a bug report on "
|
||||
"https://github.com/Microsoft/DirectXShaderCompiler/issues "
|
||||
|
|
|
@ -1190,6 +1190,7 @@ llvm::SmallVector<const Decoration *, 4> TypeTranslator::getLayoutDecorations(
|
|||
offset = roundToPow2(offset, memberAlignment);
|
||||
}
|
||||
|
||||
|
||||
// The vk::offset attribute takes precedence over all.
|
||||
if (const auto *offsetAttr = decl->getAttr<VKOffsetAttr>()) {
|
||||
offset = offsetAttr->getOffset();
|
||||
|
@ -1713,9 +1714,10 @@ TypeTranslator::getAlignmentAndSize(QualType type, SpirvLayoutRule rule,
|
|||
if (isVectorType(type, &elemType, &elemCount)) {
|
||||
uint32_t alignment = 0, size = 0;
|
||||
std::tie(alignment, size) = getAlignmentAndSize(elemType, rule, stride);
|
||||
// Use element alignment for fxc rules
|
||||
// Use element alignment for fxc rules and VK_EXT_scalar_block_layout
|
||||
if (rule != SpirvLayoutRule::FxcCTBuffer &&
|
||||
rule != SpirvLayoutRule::FxcSBuffer)
|
||||
rule != SpirvLayoutRule::FxcSBuffer &&
|
||||
rule != SpirvLayoutRule::Scalar)
|
||||
alignment = (elemCount == 3 ? 4 : elemCount) * size;
|
||||
|
||||
return {alignment, elemCount * size};
|
||||
|
@ -1737,9 +1739,11 @@ TypeTranslator::getAlignmentAndSize(QualType type, SpirvLayoutRule rule,
|
|||
|
||||
const uint32_t vecStorageSize = isRowMajor ? colCount : rowCount;
|
||||
|
||||
if (rule == SpirvLayoutRule::FxcSBuffer) {
|
||||
if (rule == SpirvLayoutRule::FxcSBuffer ||
|
||||
rule == SpirvLayoutRule::Scalar) {
|
||||
*stride = vecStorageSize * size;
|
||||
// Use element alignment for fxc structured buffers
|
||||
// Use element alignment for fxc structured buffers and
|
||||
// VK_EXT_scalar_block_layout
|
||||
return {alignment, rowCount * colCount * size};
|
||||
}
|
||||
|
||||
|
@ -1794,6 +1798,12 @@ TypeTranslator::getAlignmentAndSize(QualType type, SpirvLayoutRule rule,
|
|||
structSize += memberSize;
|
||||
}
|
||||
|
||||
if (rule == SpirvLayoutRule::Scalar) {
|
||||
// A structure has a scalar alignment equal to the largest scalar
|
||||
// alignment of any of its members in VK_EXT_scalar_block_layout.
|
||||
return {maxAlignment, structSize};
|
||||
}
|
||||
|
||||
if (rule == SpirvLayoutRule::GLSLStd140 ||
|
||||
rule == SpirvLayoutRule::RelaxedGLSLStd140 ||
|
||||
rule == SpirvLayoutRule::FxcCTBuffer) {
|
||||
|
@ -1817,9 +1827,11 @@ TypeTranslator::getAlignmentAndSize(QualType type, SpirvLayoutRule rule,
|
|||
std::tie(alignment, size) =
|
||||
getAlignmentAndSize(arrayType->getElementType(), rule, stride);
|
||||
|
||||
if (rule == SpirvLayoutRule::FxcSBuffer) {
|
||||
if (rule == SpirvLayoutRule::FxcSBuffer ||
|
||||
rule == SpirvLayoutRule::Scalar) {
|
||||
*stride = size;
|
||||
// Use element alignment for fxc structured buffers
|
||||
// Use element alignment for fxc structured buffers and
|
||||
// VK_EXT_scalar_block_layout
|
||||
return {alignment, size * elemCount};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// Run: %dxc -T vs_6_2 -E main -fvk-use-scalar-layout -enable-16bit-types
|
||||
|
||||
struct R { // Alignment Offset Size Next
|
||||
double rf; // 8 -> 0 + 8 = 8
|
||||
}; // 8 8
|
||||
|
||||
struct S { // Alignment Offset Size Next
|
||||
R sf1; // 8 -> 0 + 8 = 8
|
||||
float sf2; // 4 -> 8 + 4 = 12
|
||||
float3 sf3; // 4 -> 12 + 4 * 3 = 24
|
||||
float sf4; // 4 -> 24 + 4 = 28
|
||||
}; // 8(max) 28
|
||||
|
||||
struct T { // Alignment Offset Size = Next
|
||||
int tf1; // 4 -> 0 + 4 = 4
|
||||
R tf2[3]; // 8 -> 8 (4 round up to R alignment) + 3 * stride(8) = 32
|
||||
float3x2 tf3; // 4 -> 32 + 4 * 3 * 2 = 56
|
||||
S tf4; // 8 -> 56 + 28 = 84
|
||||
float16_t tf5; // 2 -> 84 + 2 = 86
|
||||
float tf6; // 4 -> 88 (86 round up to float align) + 4 = 92
|
||||
}; // 8(max) 92
|
||||
|
||||
cbuffer MyCBuffer { // Alignment Offset Size Next
|
||||
bool a; // 4 -> 0 + 4 = 4
|
||||
uint1 b; // 4 -> 4 + 4 = 8
|
||||
float3 c; // 4 -> 8 + 3 * 4 = 20
|
||||
row_major float2x3 d; // 4 -> 20 + 4 * 2 * 3 = 44
|
||||
column_major float2x3 e; // 4 -> 44 + 4 * 2 * 3 = 68
|
||||
float2x1 f; // 4 -> 68 + 4 * 2 = 76
|
||||
row_major float2x3 g[3]; // 4 -> 76 + 4 * 2 * 3 * 3 = 148
|
||||
column_major float2x2 h[4]; // 4 -> 148 + 4 * 2 * 2 * 4 = 212
|
||||
T t; // 8 -> 216 (212 round up to T alignment) + 92 = 308
|
||||
float z; // 4 -> 308
|
||||
};
|
||||
|
||||
// CHECK: OpDecorate %_arr_mat2v3float_uint_3 ArrayStride 24
|
||||
// CHECK: OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 16
|
||||
|
||||
// CHECK: OpMemberDecorate %R 0 Offset 0
|
||||
|
||||
// CHECK: OpDecorate %_arr_R_uint_3 ArrayStride 8
|
||||
|
||||
// CHECK: OpMemberDecorate %S 0 Offset 0
|
||||
// CHECK-NEXT: OpMemberDecorate %S 1 Offset 8
|
||||
// CHECK-NEXT: OpMemberDecorate %S 2 Offset 12
|
||||
// CHECK-NEXT: OpMemberDecorate %S 3 Offset 24
|
||||
|
||||
// CHECK: OpMemberDecorate %T 0 Offset 0
|
||||
// CHECK-NEXT: OpMemberDecorate %T 1 Offset 8
|
||||
// CHECK-NEXT: OpMemberDecorate %T 2 Offset 32
|
||||
// CHECK-NEXT: OpMemberDecorate %T 2 MatrixStride 12
|
||||
// CHECK-NEXT: OpMemberDecorate %T 2 RowMajor
|
||||
// CHECK-NEXT: OpMemberDecorate %T 3 Offset 56
|
||||
// CHECK-NEXT: OpMemberDecorate %T 4 Offset 84
|
||||
// CHECK-NEXT: OpMemberDecorate %T 5 Offset 88
|
||||
|
||||
// CHECK: OpMemberDecorate %type_MyCBuffer 0 Offset 0
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 1 Offset 4
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 2 Offset 8
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 3 Offset 20
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 3 MatrixStride 12
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 3 ColMajor
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 4 Offset 44
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 4 MatrixStride 8
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 4 RowMajor
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 5 Offset 68
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 6 Offset 76
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 6 MatrixStride 12
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 6 ColMajor
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 7 Offset 148
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 7 MatrixStride 8
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 7 RowMajor
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 8 Offset 216
|
||||
// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 9 Offset 308
|
||||
// CHECK-NEXT: OpDecorate %type_MyCBuffer Block
|
||||
|
||||
float main() : A {
|
||||
return 1.0;
|
||||
}
|
|
@ -1623,6 +1623,12 @@ TEST_F(FileTest, VulkanLayoutFxcRulesCBuffer1) {
|
|||
runFileTest("vk.layout.cbuffer.fxc.1.hlsl");
|
||||
}
|
||||
|
||||
TEST_F(FileTest, VulkanLayoutCBufferScalar) {
|
||||
// VK_EXT_scalar_block_layout
|
||||
setScalarLayout();
|
||||
runFileTest("vk.layout.cbuffer.scalar.hlsl");
|
||||
}
|
||||
|
||||
TEST_F(FileTest, VulkanSubpassInput) { runFileTest("vk.subpass-input.hlsl"); }
|
||||
TEST_F(FileTest, VulkanSubpassInputBinding) {
|
||||
runFileTest("vk.subpass-input.binding.hlsl");
|
||||
|
|
|
@ -102,8 +102,9 @@ void FileTest::runFileTest(llvm::StringRef filename, Expect expect,
|
|||
ASSERT_EQ(result.status(), effcee::Result::Status::Ok);
|
||||
|
||||
if (runValidation)
|
||||
EXPECT_TRUE(utils::validateSpirvBinary(
|
||||
targetEnv, generatedBinary, relaxLogicalPointer, glLayout, dxLayout));
|
||||
EXPECT_TRUE(utils::validateSpirvBinary(targetEnv, generatedBinary,
|
||||
relaxLogicalPointer, glLayout,
|
||||
dxLayout, scalarLayout));
|
||||
} else if (expect == Expect::Warning) {
|
||||
ASSERT_TRUE(compileOk);
|
||||
|
||||
|
@ -127,8 +128,9 @@ void FileTest::runFileTest(llvm::StringRef filename, Expect expect,
|
|||
ASSERT_EQ(result.status(), effcee::Result::Status::Ok);
|
||||
|
||||
if (runValidation)
|
||||
EXPECT_TRUE(utils::validateSpirvBinary(
|
||||
targetEnv, generatedBinary, relaxLogicalPointer, glLayout, dxLayout));
|
||||
EXPECT_TRUE(utils::validateSpirvBinary(targetEnv, generatedBinary,
|
||||
relaxLogicalPointer, glLayout,
|
||||
dxLayout, scalarLayout));
|
||||
} else if (expect == Expect::Failure) {
|
||||
ASSERT_FALSE(compileOk);
|
||||
|
||||
|
@ -154,9 +156,9 @@ void FileTest::runFileTest(llvm::StringRef filename, Expect expect,
|
|||
generatedBinary, &generatedSpirvAsm, true /* generateHeader */));
|
||||
|
||||
std::string valMessages;
|
||||
EXPECT_FALSE(utils::validateSpirvBinary(targetEnv, generatedBinary,
|
||||
relaxLogicalPointer, glLayout,
|
||||
dxLayout, &valMessages));
|
||||
EXPECT_FALSE(utils::validateSpirvBinary(
|
||||
targetEnv, generatedBinary, relaxLogicalPointer, glLayout, dxLayout,
|
||||
scalarLayout, &valMessages));
|
||||
auto options = effcee::Options()
|
||||
.SetChecksName(filename.str())
|
||||
.SetInputName("<val-message>");
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
void setRelaxLogicalPointer() { relaxLogicalPointer = true; }
|
||||
void setGlLayout() { glLayout = true; }
|
||||
void setDxLayout() { dxLayout = true; }
|
||||
void setScalarLayout() { scalarLayout = true; }
|
||||
|
||||
/// \brief Runs a File Test! (See class description for more info)
|
||||
void runFileTest(llvm::StringRef path, Expect expect = Expect::Success,
|
||||
|
@ -55,6 +56,7 @@ private:
|
|||
bool relaxLogicalPointer;
|
||||
bool glLayout;
|
||||
bool dxLayout;
|
||||
bool scalarLayout;
|
||||
};
|
||||
|
||||
} // end namespace spirv
|
||||
|
|
|
@ -36,11 +36,16 @@ bool disassembleSpirvBinary(std::vector<uint32_t> &binary,
|
|||
|
||||
bool validateSpirvBinary(spv_target_env env, std::vector<uint32_t> &binary,
|
||||
bool relaxLogicalPointer, bool glLayout, bool dxLayout,
|
||||
std::string *message) {
|
||||
bool scalarLayout, std::string *message) {
|
||||
spvtools::ValidatorOptions options;
|
||||
options.SetRelaxLogicalPointer(relaxLogicalPointer);
|
||||
options.SetRelaxBlockLayout(!glLayout && !dxLayout);
|
||||
options.SetSkipBlockLayout(dxLayout);
|
||||
if (dxLayout || scalarLayout) {
|
||||
options.SetSkipBlockLayout(true);
|
||||
} else if (glLayout) {
|
||||
// The default for spirv-val.
|
||||
} else {
|
||||
options.SetRelaxBlockLayout(true);
|
||||
}
|
||||
spvtools::SpirvTools spirvTools(env);
|
||||
spirvTools.SetMessageConsumer([message](spv_message_level_t, const char *,
|
||||
const spv_position_t &,
|
||||
|
|
|
@ -34,7 +34,7 @@ bool disassembleSpirvBinary(std::vector<uint32_t> &binary,
|
|||
/// Returns true if validation is successful; false otherwise.
|
||||
bool validateSpirvBinary(spv_target_env, std::vector<uint32_t> &binary,
|
||||
bool relaxLogicalPointer, bool glLayout, bool dxLayout,
|
||||
std::string *message = nullptr);
|
||||
bool scalarLayout, std::string *message = nullptr);
|
||||
|
||||
/// \brief Parses the Target Profile and Entry Point from the Run command
|
||||
/// Returns the target profile, entry point, and the rest via arguments.
|
||||
|
|
|
@ -109,7 +109,8 @@ void WholeFileTest::runWholeFileTest(llvm::StringRef filename,
|
|||
if (runSpirvValidation) {
|
||||
EXPECT_TRUE(utils::validateSpirvBinary(
|
||||
targetEnv, generatedBinary,
|
||||
/*relaxLogicalPointer=*/false, /*glLayout=*/false, /*dxLayout=*/false));
|
||||
/*relaxLogicalPointer=*/false, /*glLayout=*/false, /*dxLayout=*/false,
|
||||
/*scalarLayout=*/false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче