From 4db9c789ffb69193ccd5d2dfad1d7bcab5e00f23 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Wed, 11 Jul 2018 16:53:19 -0400 Subject: [PATCH] Add option to skip verifying block layout We need this to avoid emitting errors on DirectX layout rules. --- include/spirv-tools/libspirv.h | 8 +++++++- include/spirv-tools/libspirv.hpp | 7 +++++++ source/spirv_validator_options.cpp | 5 +++++ source/spirv_validator_options.h | 4 +++- source/val/validate_decorations.cpp | 3 +++ test/val/val_decoration_test.cpp | 32 +++++++++++++++++++++++++++++ tools/val/val.cpp | 6 +++++- 7 files changed, 62 insertions(+), 3 deletions(-) diff --git a/include/spirv-tools/libspirv.h b/include/spirv-tools/libspirv.h index cbf4c4eff..d9952a555 100644 --- a/include/spirv-tools/libspirv.h +++ b/include/spirv-tools/libspirv.h @@ -475,10 +475,16 @@ SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetRelaxLogicalPointer( // Records whether or not the validator should relax the rules on block layout. // -// When relaxed, it will skip checking standard uniform/storage buffer layout. +// When relaxed, it will enable VK_KHR_relaxed_block_layout when validating +// standard uniform/storage block layout. SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetRelaxBlockLayout( spv_validator_options options, bool val); +// Records whether or not the validator should skip validating standard +// uniform/storage block layout. +SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetSkipBlockLayout( + spv_validator_options options, bool val); + // Encodes the given SPIR-V assembly text to its binary representation. The // length parameter specifies the number of bytes for text. Encoded binary will // be stored into *binary. Any error will be written into *diagnostic if diff --git a/include/spirv-tools/libspirv.hpp b/include/spirv-tools/libspirv.hpp index dd6ae88c3..538a355bb 100644 --- a/include/spirv-tools/libspirv.hpp +++ b/include/spirv-tools/libspirv.hpp @@ -81,10 +81,17 @@ class ValidatorOptions { spvValidatorOptionsSetRelaxStoreStruct(options_, val); } + // Enables VK_KHR_relaxed_block_layout when validating standard + // uniform/storage buffer layout. void SetRelaxBlockLayout(bool val) { spvValidatorOptionsSetRelaxBlockLayout(options_, val); } + // Skips validating standard uniform/storage buffer layout. + void SetSkipBlockLayout(bool val) { + spvValidatorOptionsSetSkipBlockLayout(options_, val); + } + // Records whether or not the validator should relax the rules on pointer // usage in logical addressing mode. // diff --git a/source/spirv_validator_options.cpp b/source/spirv_validator_options.cpp index 828d15032..daa53ebd1 100644 --- a/source/spirv_validator_options.cpp +++ b/source/spirv_validator_options.cpp @@ -91,3 +91,8 @@ void spvValidatorOptionsSetRelaxBlockLayout(spv_validator_options options, bool val) { options->relax_block_layout = val; } + +void spvValidatorOptionsSetSkipBlockLayout(spv_validator_options options, + bool val) { + options->skip_block_layout = val; +} diff --git a/source/spirv_validator_options.h b/source/spirv_validator_options.h index f28cca680..46f24ead4 100644 --- a/source/spirv_validator_options.h +++ b/source/spirv_validator_options.h @@ -41,12 +41,14 @@ struct spv_validator_options_t { : universal_limits_(), relax_struct_store(false), relax_logical_pointer(false), - relax_block_layout(false) {} + relax_block_layout(false), + skip_block_layout(false) {} validator_universal_limits_t universal_limits_; bool relax_struct_store; bool relax_logical_pointer; bool relax_block_layout; + bool skip_block_layout; }; #endif // LIBSPIRV_SPIRV_VALIDATOR_OPTIONS_H_ diff --git a/source/val/validate_decorations.cpp b/source/val/validate_decorations.cpp index 29e8f742e..40ce5bb56 100644 --- a/source/val/validate_decorations.cpp +++ b/source/val/validate_decorations.cpp @@ -331,6 +331,8 @@ spv_result_t checkLayout(uint32_t struct_id, const char* storage_class_str, const char* decoration_str, bool blockRules, MemberConstraints& constraints, ValidationState_t& vstate) { + if (vstate.options()->skip_block_layout) return SPV_SUCCESS; + auto fail = [&vstate, struct_id, storage_class_str, decoration_str, blockRules](uint32_t member_idx) -> DiagnosticStream { DiagnosticStream ds = @@ -342,6 +344,7 @@ spv_result_t checkLayout(uint32_t struct_id, const char* storage_class_str, << " layout rules: member " << member_idx << " "); return ds; }; + const bool relaxed_block_layout = vstate.IsRelaxedBlockLayout(); const auto& members = getStructMembers(struct_id, vstate); diff --git a/test/val/val_decoration_test.cpp b/test/val/val_decoration_test.cpp index c489c15cb..87130e8c0 100644 --- a/test/val/val_decoration_test.cpp +++ b/test/val/val_decoration_test.cpp @@ -2985,6 +2985,38 @@ TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackBad) { "offset 60 overlaps previous member ending at offset 63")); } +TEST_F(ValidateDecorations, LayoutNotCheckedWhenSkipBlockLayout) { + // Checks that block layout is not verified in skipping block layout mode. + // Even for obviously wrong layout. + string spirv = R"( + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" + OpSource GLSL 450 + OpMemberDecorate %S 0 Offset 3 ; wrong alignment + OpMemberDecorate %S 1 Offset 3 ; same offset as before! + OpDecorate %S Block + OpDecorate %B DescriptorSet 0 + OpDecorate %B Binding 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v3float = OpTypeVector %float 3 + %S = OpTypeStruct %float %v3float +%_ptr_Uniform_S = OpTypePointer Uniform %S + %B = OpVariable %_ptr_Uniform_S Uniform + %main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd + )"; + + CompileSuccessfully(spirv); + spvValidatorOptionsSetSkipBlockLayout(getValidatorOptions(), true); + EXPECT_EQ(SPV_SUCCESS, + ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0)); + EXPECT_THAT(getDiagnosticString(), Eq("")); +} } // namespace } // namespace val } // namespace spvtools diff --git a/tools/val/val.cpp b/tools/val/val.cpp index f65c13c0e..94f983378 100644 --- a/tools/val/val.cpp +++ b/tools/val/val.cpp @@ -46,7 +46,9 @@ Options: --max-access-chain-indexes --relax-logical-pointer Allow allocating an object of a pointer type and returning a pointer value from a function in logical addressing mode - --relax-block-layout Skips checking of standard uniform/storage buffer layout + --relax-block-layout Enable VK_HR_relaxed_block_layout when checking standard + uniform/storage buffer layout + --skip-block-layout Skip checking standard uniform/storage buffer layout --relax-struct-store Allow store from one struct type to a different type with compatible layout and members. @@ -124,6 +126,8 @@ int main(int argc, char** argv) { options.SetRelaxLogicalPointer(true); } else if (0 == strcmp(cur_arg, "--relax-block-layout")) { options.SetRelaxBlockLayout(true); + } else if (0 == strcmp(cur_arg, "--skip-block-layout")) { + options.SetSkipBlockLayout(true); } else if (0 == strcmp(cur_arg, "--relax-struct-store")) { options.SetRelaxStructStore(true); } else if (0 == cur_arg[1]) {