| /* |
| * Copyright (c) 2015-2025 The Khronos Group Inc. |
| * Copyright (c) 2015-2025 Valve Corporation |
| * Copyright (c) 2015-2025 LunarG, Inc. |
| * Copyright (c) 2015-2025 Google, Inc. |
| * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| */ |
| |
| #include <vulkan/vulkan_core.h> |
| #include "../framework/layer_validation_tests.h" |
| #include "../framework/pipeline_helper.h" |
| |
| struct icd_spv_header { |
| uint32_t magic = 0x07230203; |
| uint32_t version = 99; |
| uint32_t gen_magic = 0; // Generator's magic number |
| }; |
| |
| class NegativeShaderSpirv : public VkLayerTest {}; |
| |
| TEST_F(NegativeShaderSpirv, CodeSize) { |
| TEST_DESCRIPTION("Test that errors are produced for a spirv modules with invalid code sizes"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| { |
| VkShaderModule module; |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| |
| module_create_info.pCode = nullptr; |
| module_create_info.codeSize = 0; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-codeSize-01085"); |
| vk::CreateShaderModule(device(), &module_create_info, nullptr, &module); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| VkShaderModule module; |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| |
| constexpr icd_spv_header spv = {}; |
| module_create_info.pCode = reinterpret_cast<const uint32_t *>(&spv); |
| module_create_info.codeSize = 4; |
| |
| m_errorMonitor->SetDesiredError("Invalid SPIR-V header"); |
| vk::CreateShaderModule(device(), &module_create_info, nullptr, &module); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| VkShaderModule module; |
| std::vector<uint32_t> shader = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl); |
| module_create_info.pCode = shader.data(); |
| // Introduce failure by making codeSize a non-multiple of 4 |
| module_create_info.codeSize = shader.size() * sizeof(uint32_t) - 1; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-codeSize-08735"); |
| vk::CreateShaderModule(*m_device, &module_create_info, nullptr, &module); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeShaderSpirv, CodeSizeMaintenance5) { |
| TEST_DESCRIPTION("Test SPIRV is still checked if using new pNext in VkPipelineShaderStageCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| module_create_info.pCode = nullptr; |
| module_create_info.codeSize = 0; |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&module_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_VERTEX_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = "main"; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.stageCount = 1; |
| pipe.gp_ci_.pStages = &stage_ci; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-codeSize-01085"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| std::vector<uint32_t> shader = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl); |
| module_create_info.pCode = shader.data(); |
| // Introduce failure by making codeSize a non-multiple of 4 |
| module_create_info.codeSize = shader.size() * sizeof(uint32_t) - 1; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-codeSize-08735"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, CodeSizeMaintenance5Compute) { |
| TEST_DESCRIPTION("Test SPIRV is still checked if using new pNext in VkPipelineShaderStageCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| module_create_info.pCode = nullptr; |
| module_create_info.codeSize = 0; |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&module_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = "main"; |
| |
| vkt::PipelineLayout layout(*m_device, {}); |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cp_ci_.stage = stage_ci; |
| pipe.cp_ci_.layout = layout; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-codeSize-01085"); |
| pipe.CreateComputePipeline(false); |
| m_errorMonitor->VerifyFound(); |
| |
| std::vector<uint32_t> shader = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kMinimalShaderGlsl); |
| module_create_info.pCode = shader.data(); |
| // Introduce failure by making codeSize a non-multiple of 4 |
| module_create_info.codeSize = shader.size() * sizeof(uint32_t) - 1; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-codeSize-08735"); |
| pipe.CreateComputePipeline(false); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, Magic) { |
| TEST_DESCRIPTION("Test that an error is produced for a spirv module with a bad magic number"); |
| RETURN_IF_SKIP(Init()); |
| |
| VkShaderModule module; |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| |
| constexpr uint32_t bad_magic = 4175232508U; |
| constexpr icd_spv_header spv = {bad_magic}; |
| |
| module_create_info.pCode = reinterpret_cast<const uint32_t *>(&spv); |
| module_create_info.codeSize = sizeof(spv); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08738"); |
| vk::CreateShaderModule(device(), &module_create_info, nullptr, &module); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, MagicMaintenance5) { |
| TEST_DESCRIPTION("Test SPIRV is still checked if using new pNext in VkPipelineShaderStageCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| constexpr uint32_t bad_magic = 4175232508U; |
| constexpr icd_spv_header spv = {bad_magic}; |
| |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| module_create_info.pCode = reinterpret_cast<const uint32_t *>(&spv); |
| module_create_info.codeSize = sizeof(spv); |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&module_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_VERTEX_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = "main"; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.stageCount = 1; |
| pipe.gp_ci_.pStages = &stage_ci; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08738"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, MagicMaintenance5Compute) { |
| TEST_DESCRIPTION("Test SPIRV is still checked if using new pNext in VkPipelineShaderStageCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| |
| constexpr uint32_t bad_magic = 4175232508U; |
| constexpr icd_spv_header spv = {bad_magic}; |
| |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| module_create_info.pCode = reinterpret_cast<const uint32_t *>(&spv); |
| module_create_info.codeSize = sizeof(spv); |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&module_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = "main"; |
| vkt::PipelineLayout layout(*m_device, {}); |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cp_ci_.stage = stage_ci; |
| pipe.cp_ci_.layout = layout; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08738"); |
| pipe.CreateComputePipeline(false); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderFloatControl) { |
| TEST_DESCRIPTION("Test VK_KHR_shader_float_controls"); |
| |
| // Need 1.1 to get SPIR-V 1.3 since OpExecutionModeId was added in SPIR-V 1.2 |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| |
| // The issue with revision 4 of this extension should not be an issue with the tests |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPhysicalDeviceFloatControlsProperties shader_float_control = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(shader_float_control); |
| |
| if (shader_float_control.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE) { |
| GTEST_SKIP() << "denormBehaviorIndependence is NONE"; |
| } |
| if (shader_float_control.roundingModeIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE) { |
| GTEST_SKIP() << "roundingModeIndependence is NONE"; |
| } |
| |
| // Check for support of 32-bit properties, but only will test if they are not supported |
| // in case all 16/32/64 version are not supported will set SetUnexpectedError for capability check |
| bool signed_zero_inf_nan_preserve = (shader_float_control.shaderSignedZeroInfNanPreserveFloat32 == VK_TRUE); |
| bool denorm_preserve = (shader_float_control.shaderDenormPreserveFloat32 == VK_TRUE); |
| bool denorm_flush_to_zero = (shader_float_control.shaderDenormFlushToZeroFloat32 == VK_TRUE); |
| bool rounding_mode_rte = (shader_float_control.shaderRoundingModeRTEFloat32 == VK_TRUE); |
| bool rounding_mode_rtz = (shader_float_control.shaderRoundingModeRTZFloat32 == VK_TRUE); |
| |
| // same body for each shader, only the start is different |
| // this is just "float a = 1.0 + 2.0;" in SPIR-V |
| const std::string source_body = R"( |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpSource GLSL 450 |
| OpName %main "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %pFunction = OpTypePointer Function %float |
| %float_3 = OpConstant %float 3 |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| %6 = OpVariable %pFunction Function |
| OpStore %6 %float_3 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| if (!signed_zero_inf_nan_preserve) { |
| const std::string spv_source = R"( |
| OpCapability Shader |
| OpCapability SignedZeroInfNanPreserve |
| OpExtension "SPV_KHR_float_controls" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main SignedZeroInfNanPreserve 32 |
| )" + source_body; |
| |
| m_errorMonitor->SetUnexpectedError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderSignedZeroInfNanPreserveFloat32-06294"); |
| VkShaderObj::CreateFromASM(this, spv_source.c_str(), VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| if (!denorm_preserve) { |
| const std::string spv_source = R"( |
| OpCapability Shader |
| OpCapability DenormPreserve |
| OpExtension "SPV_KHR_float_controls" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main DenormPreserve 32 |
| )" + source_body; |
| |
| m_errorMonitor->SetUnexpectedError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderDenormPreserveFloat32-06297"); |
| VkShaderObj::CreateFromASM(this, spv_source.c_str(), VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| if (!denorm_flush_to_zero) { |
| const std::string spv_source = R"( |
| OpCapability Shader |
| OpCapability DenormFlushToZero |
| OpExtension "SPV_KHR_float_controls" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main DenormFlushToZero 32 |
| )" + source_body; |
| |
| m_errorMonitor->SetUnexpectedError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderDenormFlushToZeroFloat32-06300"); |
| VkShaderObj::CreateFromASM(this, spv_source.c_str(), VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| if (!rounding_mode_rte) { |
| const std::string spv_source = R"( |
| OpCapability Shader |
| OpCapability RoundingModeRTE |
| OpExtension "SPV_KHR_float_controls" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main RoundingModeRTE 32 |
| )" + source_body; |
| |
| m_errorMonitor->SetUnexpectedError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderRoundingModeRTEFloat32-06303"); |
| VkShaderObj::CreateFromASM(this, spv_source.c_str(), VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| if (!rounding_mode_rtz) { |
| const std::string spv_source = R"( |
| OpCapability Shader |
| OpCapability RoundingModeRTZ |
| OpExtension "SPV_KHR_float_controls" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main RoundingModeRTZ 32 |
| )" + source_body; |
| |
| m_errorMonitor->SetUnexpectedError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderRoundingModeRTZFloat32-06306"); |
| VkShaderObj::CreateFromASM(this, spv_source.c_str(), VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeShaderSpirv, Storage8and16bitCapability) { |
| TEST_DESCRIPTION("Test VK_KHR_8bit_storage and VK_KHR_16bit_storage not having feature bits required for SPIR-V capability"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework(&kDisableMessageLimit)); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| // storageBuffer8BitAccess |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_8bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int8: enable |
| layout(set = 0, binding = 0) buffer SSBO { int8_t x; } data; |
| void main(){ |
| int8_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageBuffer8BitAccess-06328"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int8 |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| // uniformAndStorageBuffer8BitAccess |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_8bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int8: enable |
| layout(set = 0, binding = 0) uniform UBO { int8_t x; } data; |
| void main(){ |
| int8_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-uniformAndStorageBuffer8BitAccess-06329"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int8 |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storagePushConstant8 |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_8bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int8: enable |
| layout(push_constant) uniform PushConstant { int8_t x; } data; |
| void main(){ |
| int8_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storagePushConstant8-06330"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int8 |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storageBuffer16BitAccess - Float |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float16: enable |
| layout(set = 0, binding = 0) buffer SSBO { float16_t x; } data; |
| void main(){ |
| float16_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageBuffer16BitAccess-11161"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int8 |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // uniformAndStorageBuffer16BitAccess - Float |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float16: enable |
| layout(set = 0, binding = 0) uniform UBO { float16_t x; } data; |
| void main(){ |
| float16_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-uniformAndStorageBuffer16BitAccess-06332"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int8 |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storagePushConstant16 - Float |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float16: enable |
| layout(push_constant) uniform PushConstant { float16_t x; } data; |
| void main(){ |
| float16_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storagePushConstant16-06333"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int8 |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storageInputOutput16 - Float |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float16: enable |
| layout(location = 0) out float16_t outData; |
| void main(){ |
| outData = float16_t(1); |
| gl_Position = vec4(0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageInputOutput16-11162"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int8 |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Need to match in/out |
| const char *fsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float16: enable |
| layout(location = 0) in float16_t x; |
| layout(location = 0) out vec4 uFragColor; |
| void main(){ |
| uFragColor = vec4(0,1,0,1); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageInputOutput16-11162"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); // Int8 |
| VkShaderObj const fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storageBuffer16BitAccess - Int |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int16: enable |
| layout(set = 0, binding = 0) buffer SSBO { int16_t x; } data; |
| void main(){ |
| int16_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageBuffer16BitAccess-11161"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int16 and StorageBuffer16BitAccess |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // uniformAndStorageBuffer16BitAccess - Int |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int16: enable |
| layout(set = 0, binding = 0) uniform UBO { int16_t x; } data; |
| void main(){ |
| int16_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-uniformAndStorageBuffer16BitAccess-06332"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", |
| 2); // Int16 and UniformAndStorageBuffer16BitAccess |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storagePushConstant16 - Int |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int16: enable |
| layout(push_constant) uniform PushConstant { int16_t x; } data; |
| void main(){ |
| int16_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storagePushConstant16-06333"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int16 and StoragePushConstant16 |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storageInputOutput16 - Int |
| { |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int16: enable |
| layout(location = 0) out int16_t outData; |
| void main(){ |
| outData = int16_t(1); |
| gl_Position = vec4(0.0); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageInputOutput16-11162"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int16 and StorageInputOutput16 |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Need to match in/out |
| const char *fsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_16bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int16: enable |
| layout(location = 0) flat in int16_t x; |
| layout(location = 0) out vec4 uFragColor; |
| void main(){ |
| uFragColor = vec4(0,1,0,1); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageInputOutput16-11162"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); // StorageInputOutput16 |
| VkShaderObj const fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeShaderSpirv, InputOutput8Bit) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-Docs/issues/2595"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderInt8); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_8bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int8: enable |
| layout(location = 0) in int8_t inData; |
| void main(){ |
| gl_Position = vec4(float(inData)); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-None-10980"); |
| VkShaderObj const vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_8bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int8: enable |
| layout(location = 0) out uint8_t outData; |
| void main(){ |
| outData = uint8_t(3); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-None-10980"); |
| VkShaderObj const fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpirvStatelessMaintenance5) { |
| TEST_DESCRIPTION("Test SPIRV is still checked if using new pNext in VkPipelineShaderStageCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::vertexPipelineStoresAndAtomics); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *vsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_8bit_storage: enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int8: enable |
| layout(set = 0, binding = 0) buffer SSBO { int8_t x; } data; |
| void main(){ |
| int8_t a = data.x + data.x; |
| gl_Position = vec4(float(a) * 0.0); |
| } |
| )glsl"; |
| std::vector<uint32_t> shader = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, vsSource); |
| |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| module_create_info.pCode = shader.data(); |
| module_create_info.codeSize = shader.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&module_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_VERTEX_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = "main"; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.stageCount = 1; |
| pipe.gp_ci_.pStages = &stage_ci; |
| pipe.dsl_bindings_[0] = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr}; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-uniformAndStorageBuffer8BitAccess-06329"); // feature |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740", 2); // Int8 |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpirvStatelessMaintenance5VertAndFrag) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::vertexPipelineStoresAndAtomics); |
| AddRequiredFeature(vkt::Feature::fragmentStoresAndAtomics); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char shader[] = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_atomic_float : enable |
| #extension GL_KHR_memory_scope_semantics : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float32 : enable |
| layout(set = 0, binding = 0) buffer ssbo { float32_t y; }; |
| void main() { |
| y = 1 + atomicLoad(y, gl_ScopeDevice, gl_StorageSemanticsBuffer, gl_SemanticsAcquire); |
| } |
| )glsl"; |
| |
| const auto vs_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, shader); |
| const auto fs_spv = GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, shader); |
| |
| VkShaderModuleCreateInfo module_create_info_vs = vku::InitStructHelper(); |
| module_create_info_vs.pCode = vs_spv.data(); |
| module_create_info_vs.codeSize = vs_spv.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci_vs = vku::InitStructHelper(&module_create_info_vs); |
| stage_ci_vs.stage = VK_SHADER_STAGE_VERTEX_BIT; |
| stage_ci_vs.module = VK_NULL_HANDLE; |
| stage_ci_vs.pName = "main"; |
| |
| VkShaderModuleCreateInfo module_create_info_fs = vku::InitStructHelper(); |
| module_create_info_fs.pCode = fs_spv.data(); |
| module_create_info_fs.codeSize = fs_spv.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci_fs = vku::InitStructHelper(&module_create_info_fs); |
| stage_ci_fs.stage = VK_SHADER_STAGE_FRAGMENT_BIT; |
| stage_ci_fs.module = VK_NULL_HANDLE; |
| stage_ci_fs.pName = "main"; |
| |
| std::array stages = {stage_ci_vs, stage_ci_fs}; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.stageCount = size32(stages); |
| pipe.gp_ci_.pStages = stages.data(); |
| pipe.dsl_bindings_[0] = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-None-06338", 2); // Vertex and Fragment |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, Storage8and16bitFeatures) { |
| TEST_DESCRIPTION( |
| "Test VK_KHR_8bit_storage and VK_KHR_16bit_storage where the Int8/Int16 capability are only used and since they are " |
| "superset of a capabilty"); |
| |
| // the following [OpCapability UniformAndStorageBuffer8BitAccess] requires the uniformAndStorageBuffer8BitAccess feature bit or |
| // the generated capability checking code will catch it |
| // |
| // But having just [OpCapability Int8] is still a legal SPIR-V shader because the Int8 capabilty allows all storage classes in |
| // the SPIR-V spec... but the shaderInt8 feature bit in Vulkan spec explains how you still need the |
| // uniformAndStorageBuffer8BitAccess feature bit for Uniform storage class from Vulkan's perspective |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()); |
| |
| // Prevent extra errors for not having the support for the SPV extensions |
| |
| VkPhysicalDeviceShaderFloat16Int8Features float16Int8 = vku::InitStructHelper(); |
| auto features2 = GetPhysicalDeviceFeatures2(float16Int8); |
| RETURN_IF_SKIP(InitState(nullptr, &features2)); |
| InitRenderTarget(); |
| |
| if (float16Int8.shaderInt8 == VK_TRUE) { |
| // storageBuffer8BitAccess |
| { |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Int8 |
| OpExtension "SPV_KHR_8bit_storage" |
| OpExtension "SPV_KHR_storage_buffer_storage_class" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %Data 0 Offset 0 |
| OpDecorate %Data Block |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int8 = OpTypeInt 8 0 |
| %Data = OpTypeStruct %int8 |
| %ptr = OpTypePointer StorageBuffer %Data |
| %var = OpVariable %ptr StorageBuffer |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageBuffer8BitAccess-06328"); |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // uniformAndStorageBuffer8BitAccess |
| { |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Int8 |
| OpExtension "SPV_KHR_8bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %Data 0 Offset 0 |
| OpDecorate %Data Block |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int8 = OpTypeInt 8 0 |
| %Data = OpTypeStruct %int8 |
| %ptr = OpTypePointer Uniform %Data |
| %var = OpVariable %ptr Uniform |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-uniformAndStorageBuffer8BitAccess-06329"); |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storagePushConstant8 |
| { |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Int8 |
| OpExtension "SPV_KHR_8bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %Data 0 Offset 0 |
| OpDecorate %Data Block |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int8 = OpTypeInt 8 0 |
| %Data = OpTypeStruct %int8 |
| %ptr = OpTypePointer PushConstant %Data |
| %var = OpVariable %ptr PushConstant |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storagePushConstant8-06330"); |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| if (float16Int8.shaderFloat16 == VK_TRUE) { |
| // storageBuffer16BitAccess - float |
| { |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpExtension "SPV_KHR_16bit_storage" |
| OpExtension "SPV_KHR_storage_buffer_storage_class" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %Data 0 Offset 0 |
| OpDecorate %Data Block |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %float16 = OpTypeFloat 16 |
| %Data = OpTypeStruct %float16 |
| %ptr = OpTypePointer StorageBuffer %Data |
| %var = OpVariable %ptr StorageBuffer |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageBuffer16BitAccess-11161"); |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // uniformAndStorageBuffer16BitAccess - float |
| { |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpExtension "SPV_KHR_16bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %Data 0 Offset 0 |
| OpDecorate %Data Block |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %float16 = OpTypeFloat 16 |
| %Data = OpTypeStruct %float16 |
| %ptr = OpTypePointer Uniform %Data |
| %var = OpVariable %ptr Uniform |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-uniformAndStorageBuffer16BitAccess-06332"); |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storagePushConstant16 - float |
| { |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpExtension "SPV_KHR_16bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %Data 0 Offset 0 |
| OpDecorate %Data Block |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %float16 = OpTypeFloat 16 |
| %Data = OpTypeStruct %float16 |
| %ptr = OpTypePointer PushConstant %Data |
| %var = OpVariable %ptr PushConstant |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storagePushConstant16-06333"); |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storageInputOutput16 - float |
| { |
| const char *vs_source = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpExtension "SPV_KHR_16bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" %var |
| OpDecorate %var Location 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %float16 = OpTypeFloat 16 |
| %ptr = OpTypePointer Output %float16 |
| %var = OpVariable %ptr Output |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageInputOutput16-11162"); |
| auto vs = VkShaderObj::CreateFromASM(this, vs_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| |
| const char *fs_source = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpExtension "SPV_KHR_16bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %in %out |
| OpExecutionMode %main OriginUpperLeft |
| OpDecorate %in Location 0 |
| OpDecorate %out Location 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %float16 = OpTypeFloat 16 |
| %inPtr = OpTypePointer Input %float16 |
| %in = OpVariable %inPtr Input |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %outPtr = OpTypePointer Output %v4float |
| %out = OpVariable %outPtr Output |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageInputOutput16-11162"); |
| auto fs = VkShaderObj::CreateFromASM(this, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| if (features2.features.shaderInt16 == VK_TRUE) { |
| // storageBuffer16BitAccess - int |
| { |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Int16 |
| OpExtension "SPV_KHR_16bit_storage" |
| OpExtension "SPV_KHR_storage_buffer_storage_class" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %Data 0 Offset 0 |
| OpDecorate %Data Block |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int16 = OpTypeInt 16 0 |
| %Data = OpTypeStruct %int16 |
| %ptr = OpTypePointer StorageBuffer %Data |
| %var = OpVariable %ptr StorageBuffer |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageBuffer16BitAccess-11161"); |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // uniformAndStorageBuffer16BitAccess - int |
| { |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Int16 |
| OpExtension "SPV_KHR_16bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %Data 0 Offset 0 |
| OpDecorate %Data Block |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int16 = OpTypeInt 16 0 |
| %Data = OpTypeStruct %int16 |
| %ptr = OpTypePointer Uniform %Data |
| %var = OpVariable %ptr Uniform |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-uniformAndStorageBuffer16BitAccess-06332"); |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storagePushConstant16 - int |
| { |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Int16 |
| OpExtension "SPV_KHR_16bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %Data 0 Offset 0 |
| OpDecorate %Data Block |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int16 = OpTypeInt 16 0 |
| %Data = OpTypeStruct %int16 |
| %ptr = OpTypePointer PushConstant %Data |
| %var = OpVariable %ptr PushConstant |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storagePushConstant16-06333"); |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // storageInputOutput16 - int |
| { |
| const char *vs_source = R"( |
| OpCapability Shader |
| OpCapability Int16 |
| OpExtension "SPV_KHR_16bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" %var |
| OpDecorate %var Location 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int16 = OpTypeInt 16 0 |
| %ptr = OpTypePointer Output %int16 |
| %var = OpVariable %ptr Output |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageInputOutput16-11162"); |
| auto vs = VkShaderObj::CreateFromASM(this, vs_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| |
| const char *fs_source = R"( |
| OpCapability Shader |
| OpCapability Int16 |
| OpExtension "SPV_KHR_16bit_storage" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %in %out |
| OpExecutionMode %main OriginUpperLeft |
| OpDecorate %in Location 0 |
| OpDecorate %in Flat |
| OpDecorate %out Location 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int16 = OpTypeInt 16 0 |
| %inPtr = OpTypePointer Input %int16 |
| %in = OpVariable %inPtr Input |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %outPtr = OpTypePointer Output %v4float |
| %out = OpVariable %outPtr Output |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageInputOutput16-11162"); |
| auto fs = VkShaderObj::CreateFromASM(this, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // tests struct with multiple types |
| if (float16Int8.shaderInt8 == VK_TRUE && features2.features.shaderInt16 == VK_TRUE) { |
| // struct X { |
| // u16vec2 a; |
| // }; |
| // struct { |
| // uint a; |
| // X b; |
| // uint8_t c; |
| // } Data; |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Int8 |
| OpCapability Int16 |
| OpExtension "SPV_KHR_8bit_storage" |
| OpExtension "SPV_KHR_16bit_storage" |
| OpExtension "SPV_KHR_storage_buffer_storage_class" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" |
| OpMemberDecorate %X 0 Offset 0 |
| OpMemberDecorate %Data 0 Offset 0 |
| OpMemberDecorate %Data 1 Offset 4 |
| OpMemberDecorate %Data 2 Offset 8 |
| OpDecorate %Data Block |
| OpDecorate %var DescriptorSet 0 |
| OpDecorate %var Binding 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int8 = OpTypeInt 8 0 |
| %int16 = OpTypeInt 16 0 |
| %v2int16 = OpTypeVector %int16 2 |
| %int32 = OpTypeInt 32 0 |
| %X = OpTypeStruct %v2int16 |
| %Data = OpTypeStruct %int32 %X %int8 |
| %ptr = OpTypePointer StorageBuffer %Data |
| %var = OpVariable %ptr StorageBuffer |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageBuffer16BitAccess-11161"); // 16 bit var |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-storageBuffer8BitAccess-06328"); // 8 bit var |
| auto vs = VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeShaderSpirv, ReadShaderClock) { |
| TEST_DESCRIPTION("Test VK_KHR_shader_clock"); |
| |
| AddRequiredExtensions(VK_KHR_SHADER_CLOCK_EXTENSION_NAME); |
| // Don't enable either feature bit on |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // Device scope using GL_EXT_shader_realtime_clock |
| const char *vsSourceDevice = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_realtime_clock: enable |
| void main(){ |
| uvec2 a = clockRealtime2x32EXT(); |
| gl_Position = vec4(float(a.x) * 0.0); |
| } |
| )glsl"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderDeviceClock-06268"); |
| VkShaderObj vs_device(*m_device, vsSourceDevice, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| |
| // Subgroup scope using ARB_shader_clock |
| const char *vsSourceScope = R"glsl( |
| #version 450 |
| #extension GL_ARB_shader_clock: enable |
| void main(){ |
| uvec2 a = clock2x32ARB(); |
| gl_Position = vec4(float(a.x) * 0.0); |
| } |
| )glsl"; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderSubgroupClock-06267"); |
| VkShaderObj vs_subgroup(*m_device, vsSourceScope, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpecializationApplied) { |
| TEST_DESCRIPTION( |
| "Make sure specialization constants get applied during shader validation by using a value that breaks compilation."); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // Size an array using a specialization constant of default value equal to 1. |
| const char *fs_src = R"( |
| OpCapability Shader |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" |
| OpExecutionMode %main OriginUpperLeft |
| OpSource GLSL 450 |
| OpName %main "main" |
| OpName %size "size" |
| OpName %array "array" |
| OpDecorate %size SpecId 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %int = OpTypeInt 32 1 |
| %size = OpSpecConstant %int 1 |
| %_arr_float_size = OpTypeArray %float %size |
| %_ptr_Function__arr_float_size = OpTypePointer Function %_arr_float_size |
| %int_0 = OpConstant %int 0 |
| %float_0 = OpConstant %float 0 |
| %_ptr_Function_float = OpTypePointer Function %float |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| %array = OpVariable %_ptr_Function__arr_float_size Function |
| %15 = OpAccessChain %_ptr_Function_float %array %int_0 |
| OpStore %15 %float_0 |
| OpReturn |
| OpFunctionEnd)"; |
| VkShaderObj fs(*m_device, fs_src, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM); |
| |
| // Set the specialization constant to 0. |
| const VkSpecializationMapEntry entry = { |
| 0, // id |
| 0, // offset |
| sizeof(uint32_t) // size |
| }; |
| uint32_t data = 0; |
| const VkSpecializationInfo specialization_info = { |
| 1, |
| &entry, |
| 1 * sizeof(uint32_t), |
| &data, |
| }; |
| |
| const auto set_info = [&](CreatePipelineHelper &helper) { |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| helper.shader_stages_[1].pSpecializationInfo = &specialization_info; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849"); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpecializationOffsetOutOfBounds) { |
| TEST_DESCRIPTION("Validate VkSpecializationInfo offset."); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| layout (constant_id = 0) const float r = 0.0f; |
| layout(location = 0) out vec4 uFragColor; |
| void main(){ |
| uFragColor = vec4(r,1,0,1); |
| } |
| )glsl"; |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| // Entry offset is greater than dataSize. |
| const VkSpecializationMapEntry entry = {0, 5, sizeof(uint32_t)}; |
| |
| uint32_t data = 1; |
| const VkSpecializationInfo specialization_info = { |
| 1, |
| &entry, |
| 1 * sizeof(float), |
| &data, |
| }; |
| |
| const auto set_info = [&](CreatePipelineHelper &helper) { |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| helper.shader_stages_[1].pSpecializationInfo = &specialization_info; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationInfo-offset-00773"); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpecializationOffsetOutOfBoundsWithIdentifier) { |
| TEST_DESCRIPTION("Validate VkSpecializationInfo offset using a shader module identifier."); |
| |
| AddRequiredExtensions(VK_EXT_SHADER_MODULE_IDENTIFIER_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::pipelineCreationCacheControl); |
| AddRequiredFeature(vkt::Feature::shaderModuleIdentifier); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *vs_source = R"glsl( |
| #version 450 |
| layout (constant_id = 0) const float x = 0.0f; |
| void main(){ |
| gl_Position = vec4(x); |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT); |
| |
| VkPipelineShaderStageModuleIdentifierCreateInfoEXT sm_id_create_info = vku::InitStructHelper(); |
| VkShaderModuleIdentifierEXT get_identifier = vku::InitStructHelper(); |
| vk::GetShaderModuleIdentifierEXT(device(), vs, &get_identifier); |
| sm_id_create_info.identifierSize = get_identifier.identifierSize; |
| sm_id_create_info.pIdentifier = get_identifier.identifier; |
| |
| // Entry offset is greater than dataSize. |
| const VkSpecializationMapEntry entry = {0, 5, sizeof(uint32_t)}; |
| uint32_t data = 1; |
| const VkSpecializationInfo specialization_info = { |
| 1, |
| &entry, |
| 1 * sizeof(float), |
| &data, |
| }; |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&sm_id_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_VERTEX_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = "main"; |
| stage_ci.pSpecializationInfo = &specialization_info; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.stageCount = 1; |
| pipe.gp_ci_.pStages = &stage_ci; |
| pipe.rs_state_ci_.rasterizerDiscardEnable = VK_TRUE; |
| pipe.gp_ci_.flags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; |
| m_errorMonitor->SetDesiredError("VUID-VkSpecializationInfo-offset-00773"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpecializationSizeOutOfBounds) { |
| TEST_DESCRIPTION("Challenge core_validation with shader validation issues related to vkCreateGraphicsPipelines."); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| layout (constant_id = 0) const float r = 0.0f; |
| layout(location = 0) out vec4 uFragColor; |
| void main(){ |
| uFragColor = vec4(r,1,0,1); |
| } |
| )glsl"; |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| // Entry size is greater than dataSize minus offset. |
| const VkSpecializationMapEntry entry = {0, 3, sizeof(uint32_t)}; |
| |
| uint32_t data = 1; |
| const VkSpecializationInfo specialization_info = { |
| 1, |
| &entry, |
| 1 * sizeof(float), |
| &data, |
| }; |
| |
| const auto set_info = [&](CreatePipelineHelper &helper) { |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| helper.shader_stages_[1].pSpecializationInfo = &specialization_info; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationInfo-pMapEntries-00774"); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpecializationSizeZero) { |
| TEST_DESCRIPTION("Make sure an error is logged when a specialization map entry's size is 0"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *cs_src = R"glsl( |
| #version 450 |
| layout (constant_id = 0) const int c = 3; |
| layout (local_size_x = 1) in; |
| void main() { |
| if (gl_GlobalInvocationID.x >= c) { return; } |
| } |
| )glsl"; |
| |
| // Set the specialization constant size to 0 (anything other than 1, 2, 4, or 8 will produce the expected error). |
| VkSpecializationMapEntry entry = { |
| 0, // id |
| 0, // offset |
| 0, // size |
| }; |
| int32_t data = 0; |
| const VkSpecializationInfo specialization_info = { |
| 1, |
| &entry, |
| 1 * sizeof(decltype(data)), |
| &data, |
| }; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = |
| VkShaderObj(*m_device, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, &specialization_info); |
| m_errorMonitor->SetDesiredError("VUID-VkSpecializationMapEntry-constantID-00776"); |
| pipe.CreateComputePipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| entry.size = sizeof(decltype(data)); |
| pipe.cs_ = |
| VkShaderObj(*m_device, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, &specialization_info); |
| pipe.CreateComputePipeline(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpecializationSizeMismatch) { |
| TEST_DESCRIPTION("Make sure an error is logged when a specialization map entry's size is not correct with type"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| RETURN_IF_SKIP(InitFramework(&kDisableMessageLimit)); |
| RETURN_IF_SKIP(InitState()); |
| |
| // layout (constant_id = 0) const int a = 3; |
| // layout (constant_id = 1) const uint b = 3; |
| // layout (constant_id = 2) const float c = 3.0f; |
| // layout (constant_id = 3) const bool d = true; |
| // layout (constant_id = 4) const bool f = false; |
| const char *cs_src = R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpSource GLSL 450 |
| OpDecorate %a SpecId 0 |
| OpDecorate %b SpecId 1 |
| OpDecorate %c SpecId 2 |
| OpDecorate %d SpecId 3 |
| OpDecorate %f SpecId 4 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %int = OpTypeInt 32 1 |
| %uint = OpTypeInt 32 0 |
| %float = OpTypeFloat 32 |
| %bool = OpTypeBool |
| %a = OpSpecConstant %int 3 |
| %b = OpSpecConstant %uint 3 |
| %c = OpSpecConstant %float 3 |
| %d = OpSpecConstantTrue %bool |
| %f = OpSpecConstantFalse %bool |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| // use same offset to keep simple since unused data being read |
| VkSpecializationMapEntry entries[5] = { |
| {0, 0, 4}, // OpTypeInt 32 |
| {1, 0, 4}, // OpTypeInt 32 |
| {2, 0, 4}, // OpTypeFloat 32 |
| {3, 0, sizeof(VkBool32)}, // OpTypeBool |
| {4, 0, sizeof(VkBool32)} // OpTypeBool |
| }; |
| |
| std::array<int32_t, 4> data; // enough garbage data to grab from |
| VkSpecializationInfo specialization_info = { |
| 5, |
| entries, |
| data.size() * sizeof(decltype(data)::value_type), |
| data.data(), |
| }; |
| |
| VkShaderObj cs; |
| const auto set_info = [&cs](CreateComputePipelineHelper &helper) { helper.cs_ = std::move(cs); }; |
| |
| // Sanity check |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| if (!cs) { |
| GTEST_SKIP() << "Driver bug - not able to create shader module"; |
| } |
| |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit); |
| |
| // signed int mismatch |
| entries[0].size = 0; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[0].size = 2; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[0].size = 8; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[0].size = 4; // reset |
| |
| // unsigned int mismatch |
| entries[1].size = 1; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[1].size = 8; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[1].size = 3; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[1].size = 4; // reset |
| |
| // float mismatch |
| entries[2].size = 0; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[2].size = 8; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[2].size = 7; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[2].size = 4; // reset |
| |
| // bool mismatch |
| entries[3].size = sizeof(VkBool32) / 2; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[3].size = sizeof(VkBool32) + 1; |
| cs = VkShaderObj::CreateFromASM(this, cs_src, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpecializationSizeMismatchInt8) { |
| TEST_DESCRIPTION("Make sure an error is logged when a specialization map entry's size is not correct with type"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredFeature(vkt::Feature::shaderInt8); |
| RETURN_IF_SKIP(Init()); |
| |
| // use same offset to keep simple since unused data being read |
| VkSpecializationMapEntry entries[2] = { |
| {0, 0, 4}, // OpTypeInt 32 |
| {1, 0, 4}, // OpTypeInt 32 |
| }; |
| |
| std::array<int32_t, 2> data; // enough garbage data to grab from |
| VkSpecializationInfo specialization_info = { |
| 2, |
| entries, |
| data.size() * sizeof(decltype(data)::value_type), |
| data.data(), |
| }; |
| |
| VkShaderObj cs; |
| const auto set_info = [&cs](CreateComputePipelineHelper &helper) { helper.cs_ = std::move(cs); }; |
| |
| // #extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable |
| // layout (constant_id = 0) const int8_t a = int8_t(3); |
| // layout (constant_id = 1) const uint8_t b = uint8_t(3); |
| const char *cs_int8 = R"( |
| OpCapability Shader |
| OpCapability Int8 |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpSource GLSL 450 |
| OpSourceExtension "GL_EXT_shader_explicit_arithmetic_types_int8" |
| OpDecorate %a SpecId 0 |
| OpDecorate %b SpecId 1 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %char = OpTypeInt 8 1 |
| %uchar = OpTypeInt 8 0 |
| %a = OpSpecConstant %char 3 |
| %b = OpSpecConstant %uchar 3 |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| specialization_info.mapEntryCount = 2; |
| entries[0] = {0, 0, 1}; // OpTypeInt 8 |
| entries[1] = {1, 0, 1}; // OpTypeInt 8 |
| |
| cs = VkShaderObj::CreateFromASM(this, cs_int8, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| if (!cs) { |
| GTEST_SKIP() << "Driver bug - not able to create shader module"; |
| } |
| // Sanity check |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit); |
| |
| // signed int 8 mismatch |
| entries[0].size = 0; |
| cs = VkShaderObj::CreateFromASM(this, cs_int8, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[0].size = 2; |
| cs = VkShaderObj::CreateFromASM(this, cs_int8, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[0].size = 4; |
| cs = VkShaderObj::CreateFromASM(this, cs_int8, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[0].size = 1; // reset |
| |
| // unsigned int 8 mismatch |
| entries[1].size = 0; |
| cs = VkShaderObj::CreateFromASM(this, cs_int8, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[1].size = 2; |
| cs = VkShaderObj::CreateFromASM(this, cs_int8, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[1].size = 4; |
| cs = VkShaderObj::CreateFromASM(this, cs_int8, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpecializationSizeMismatchFloat64) { |
| TEST_DESCRIPTION("Make sure an error is logged when a specialization map entry's size is not correct with type"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredFeature(vkt::Feature::shaderFloat64); |
| RETURN_IF_SKIP(Init()); |
| |
| // use same offset to keep simple since unused data being read |
| VkSpecializationMapEntry entries[3] = { |
| {0, 0, 4}, // OpTypeInt 32 |
| {1, 0, 4}, // OpTypeInt 32 |
| {2, 0, 4}, // OpTypeFloat 32 |
| }; |
| |
| std::array<int32_t, 4> data; // enough garbage data to grab from |
| VkSpecializationInfo specialization_info = { |
| 3, |
| entries, |
| data.size() * sizeof(decltype(data)::value_type), |
| data.data(), |
| }; |
| |
| VkShaderObj cs; |
| const auto set_info = [&cs](CreateComputePipelineHelper &helper) { helper.cs_ = std::move(cs); }; |
| |
| // #extension GL_EXT_shader_explicit_arithmetic_types_float64 : enable |
| // layout (constant_id = 0) const float64_t a = 3.0f; |
| const char *cs_float64 = R"( |
| OpCapability Shader |
| OpCapability Float64 |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpSource GLSL 450 |
| OpSourceExtension "GL_EXT_shader_explicit_arithmetic_types_float64" |
| OpDecorate %a SpecId 0 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %double = OpTypeFloat 64 |
| %a = OpSpecConstant %double 3 |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| specialization_info.mapEntryCount = 1; |
| entries[0] = {0, 0, 8}; // OpTypeFloat |
| |
| cs = VkShaderObj::CreateFromASM(this, cs_float64, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| if (!cs) { |
| GTEST_SKIP() << "Driver bug - not able to create shader module"; |
| } |
| |
| // Sanity check |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit); |
| |
| // float 64 mismatch |
| entries[0].size = 1; |
| cs = VkShaderObj::CreateFromASM(this, cs_float64, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[0].size = 2; |
| cs = VkShaderObj::CreateFromASM(this, cs_float64, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[0].size = 4; |
| cs = VkShaderObj::CreateFromASM(this, cs_float64, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| entries[0].size = 16; |
| cs = VkShaderObj::CreateFromASM(this, cs_float64, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, &specialization_info); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationMapEntry-constantID-00776"); |
| } |
| |
| TEST_F(NegativeShaderSpirv, DuplicatedSpecializationConstantID) { |
| TEST_DESCRIPTION("Create a pipeline with non unique constantID in specialization pMapEntries."); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| layout (constant_id = 0) const float r = 0.0f; |
| layout(location = 0) out vec4 uFragColor; |
| void main(){ |
| uFragColor = vec4(r,1,0,1); |
| } |
| )glsl"; |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| VkSpecializationMapEntry entries[2]; |
| entries[0].constantID = 0; |
| entries[0].offset = 0; |
| entries[0].size = sizeof(uint32_t); |
| entries[1].constantID = 0; |
| entries[1].offset = 0; |
| entries[1].size = sizeof(uint32_t); |
| |
| uint32_t data = 1; |
| VkSpecializationInfo specialization_info; |
| specialization_info.mapEntryCount = 2; |
| specialization_info.pMapEntries = entries; |
| specialization_info.dataSize = sizeof(uint32_t); |
| specialization_info.pData = &data; |
| |
| const auto set_info = [&](CreatePipelineHelper &helper) { |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| helper.shader_stages_[1].pSpecializationInfo = &specialization_info; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkSpecializationInfo-constantID-04911"); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderModuleCheckCapability) { |
| TEST_DESCRIPTION("Create a shader in which a capability declared by the shader is not supported."); |
| // Note that this failure message comes from spirv-tools, specifically the validator. |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *spv_source = R"( |
| OpCapability ImageRect |
| OpEntryPoint Vertex %main "main" |
| %main = OpFunction %void None %3 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("Capability ImageRect is not allowed by Vulkan"); |
| VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderNotEnabled) { |
| TEST_DESCRIPTION( |
| "Create a graphics pipeline in which a capability declared by the shader requires a feature not enabled on the device."); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| layout(location=0) out vec4 color; |
| void main(){ |
| dvec4 green = vec4(0.0, 1.0, 0.0, 1.0); |
| color = vec4(green); |
| } |
| )glsl"; |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderImageFootprintEnabled) { |
| TEST_DESCRIPTION("Create a pipeline requiring the shader image footprint feature which has not enabled on the device."); |
| AddRequiredExtensions(VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| #extension GL_NV_shader_texture_footprint : require |
| layout(set=0, binding=0) uniform sampler2D s; |
| layout(location=0) out vec4 color; |
| void main(){ |
| gl_TextureFootprint2DNV footprint; |
| if (textureFootprintNV(s, vec2(1.0), 5, false, footprint)) { |
| color = vec4(0.0, 1.0, 0.0, 1.0); |
| } else { |
| color = vec4(vec2(footprint.anchor), vec2(footprint.offset)); |
| } |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, FragmentShaderBarycentricEnabled) { |
| TEST_DESCRIPTION("Create a pipeline requiring the fragment shader barycentric feature which has not enabled on the device."); |
| |
| AddRequiredExtensions(VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| #extension GL_NV_fragment_shader_barycentric : require |
| layout(location=0) out float value; |
| void main(){ |
| value = gl_BaryCoordNV.x; |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ComputeShaderDerivativesEnabled) { |
| TEST_DESCRIPTION("Create a pipeline requiring the compute shader derivatives feature which has not enabled on the device."); |
| |
| AddRequiredExtensions(VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *csSource = R"glsl( |
| #version 450 |
| #extension GL_NV_compute_shader_derivatives : require |
| layout(local_size_x=2, local_size_y=4) in; |
| layout(derivative_group_quadsNV) in; |
| layout(set=0, binding=0) buffer InputOutputBuffer { |
| float values[]; |
| }; |
| void main(){ |
| values[gl_LocalInvocationIndex] = dFdx(values[gl_LocalInvocationIndex]); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj cs(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, FragmentShaderInterlockEnabled) { |
| TEST_DESCRIPTION("Create a pipeline requiring the fragment shader interlock feature which has not enabled on the device."); |
| |
| AddRequiredExtensions(VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| #extension GL_ARB_fragment_shader_interlock : require |
| layout(sample_interlock_ordered) in; |
| void main(){ |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, DemoteToHelperInvocation) { |
| TEST_DESCRIPTION("Create a pipeline requiring the demote to helper invocation feature which has not enabled on the device."); |
| |
| AddRequiredExtensions(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| #extension GL_EXT_demote_to_helper_invocation : require |
| void main(){ |
| demote; |
| } |
| |
| )glsl"; |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, NoUniformBufferStandardLayout10) { |
| TEST_DESCRIPTION("Don't enable uniformBufferStandardLayout in Vulkan 1.0 and have spirv-val catch invalid shader"); |
| SetTargetApiVersion(VK_API_VERSION_1_0); |
| RETURN_IF_SKIP(Init()); |
| if (DeviceValidationVersion() > VK_API_VERSION_1_0) { |
| GTEST_SKIP() << "Tests for 1.0 only"; |
| } |
| |
| // layout(std430, set = 0, binding = 0) uniform ubo430 { |
| // float floatArray430[8]; |
| // }; |
| const char *spv_source = R"( |
| OpCapability Shader |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpSource GLSL 450 |
| OpDecorate %_arr_float_uint_8 ArrayStride 4 |
| OpMemberDecorate %ubo430 0 Offset 0 |
| OpDecorate %ubo430 Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %uint = OpTypeInt 32 0 |
| %uint_8 = OpConstant %uint 8 |
| %_arr_float_uint_8 = OpTypeArray %float %uint_8 |
| %ubo430 = OpTypeStruct %_arr_float_uint_8 |
| %_ptr_Uniform_ubo430 = OpTypePointer Uniform %ubo430 |
| %_ = OpVariable %_ptr_Uniform_ubo430 Uniform |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08737"); |
| VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, NoUniformBufferStandardLayout12) { |
| TEST_DESCRIPTION( |
| "Don't enable uniformBufferStandardLayout in Vulkan1.2 when VK_KHR_uniform_buffer_standard_layout was promoted"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| RETURN_IF_SKIP(Init()); |
| |
| // layout(std430, set = 0, binding = 0) uniform ubo430 { |
| // float floatArray430[8]; |
| // }; |
| const char *spv_source = R"( |
| OpCapability Shader |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpSource GLSL 450 |
| OpDecorate %_arr_float_uint_8 ArrayStride 4 |
| OpMemberDecorate %ubo430 0 Offset 0 |
| OpDecorate %ubo430 Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %uint = OpTypeInt 32 0 |
| %uint_8 = OpConstant %uint 8 |
| %_arr_float_uint_8 = OpTypeArray %float %uint_8 |
| %ubo430 = OpTypeStruct %_arr_float_uint_8 |
| %_ptr_Uniform_ubo430 = OpTypePointer Uniform %ubo430 |
| %_ = OpVariable %_ptr_Uniform_ubo430 Uniform |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08737"); |
| VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, NoScalarBlockLayout10) { |
| TEST_DESCRIPTION("Don't enable scalarBlockLayout in Vulkan 1.0 and have spirv-val catch invalid shader"); |
| SetTargetApiVersion(VK_API_VERSION_1_0); |
| RETURN_IF_SKIP(Init()); |
| if (DeviceValidationVersion() > VK_API_VERSION_1_0) { |
| GTEST_SKIP() << "Tests for 1.0 only"; |
| } |
| |
| // layout (scalar, set = 0, binding = 0) buffer ssbo { |
| // layout(offset = 4) vec3 x; |
| // }; |
| // |
| // Note: using BufferBlock for Vulkan 1.0 |
| // Note: Relaxed Block Layout would also make this valid if enabled |
| const char *spv_source = R"( |
| OpCapability Shader |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpSource GLSL 450 |
| OpMemberDecorate %ssbo 0 Offset 4 |
| OpDecorate %ssbo BufferBlock |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %ssbo = OpTypeStruct %v3float |
| %_ptr_Uniform_ssbo = OpTypePointer Uniform %ssbo |
| %_ = OpVariable %_ptr_Uniform_ssbo Uniform |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08737"); |
| VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, NoScalarBlockLayout12) { |
| TEST_DESCRIPTION("Don't enable scalarBlockLayout in Vulkan1.2 when VK_EXT_scalar_block_layout was promoted"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| RETURN_IF_SKIP(Init()); |
| |
| // layout (scalar, set = 0, binding = 0) buffer ssbo { |
| // layout(offset = 0) vec3 a; |
| // layout(offset = 12) vec2 b; |
| // }; |
| const char *spv_source = R"( |
| OpCapability Shader |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %_ |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpSource GLSL 450 |
| OpMemberDecorate %ssbo 0 Offset 0 |
| OpMemberDecorate %ssbo 1 Offset 12 |
| OpDecorate %ssbo Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %v2float = OpTypeVector %float 2 |
| %ssbo = OpTypeStruct %v3float %v2float |
| %_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo |
| %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08737"); |
| VkShaderObj::CreateFromASM(this, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SubgroupRotate) { |
| TEST_DESCRIPTION("Missing shaderSubgroupRotate"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| const char *source = R"glsl( |
| #version 450 |
| #extension GL_KHR_shader_subgroup_rotate: enable |
| layout(binding = 0) buffer Buffers { vec4 x; } data; |
| void main() { |
| data.x = subgroupRotate(data.x, 1); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj cs(*m_device, source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SubgroupRotateClustered) { |
| TEST_DESCRIPTION("Missing shaderSubgroupRotateClustered"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderSubgroupRotate); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| const char *source = R"glsl( |
| #version 450 |
| #extension GL_KHR_shader_subgroup_rotate: enable |
| layout(binding = 0) buffer Buffers { vec4 x; } data; |
| void main() { |
| data.x = subgroupClusteredRotate(data.x, 1, 1); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderSubgroupRotateClustered-09566"); |
| VkShaderObj cs(*m_device, source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, DeviceMemoryScope) { |
| TEST_DESCRIPTION("Validate using Device memory scope in spirv."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredFeature(vkt::Feature::vulkanMemoryModel); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| const char *csSource = R"glsl( |
| #version 450 |
| #extension GL_KHR_memory_scope_semantics : enable |
| layout(set = 0, binding = 0) buffer ssbo { uint y; }; |
| void main() { |
| atomicStore(y, 1u, gl_ScopeDevice, gl_StorageSemanticsBuffer, gl_SemanticsRelease); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-vulkanMemoryModel-06265"); |
| VkShaderObj cs(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, QueueFamilyMemoryScope) { |
| TEST_DESCRIPTION("Validate using QueueFamily memory scope in spirv."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| |
| AddRequiredFeature(vkt::Feature::vulkanMemoryModelDeviceScope); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *csSource = R"glsl( |
| #version 450 |
| #extension GL_KHR_memory_scope_semantics : enable |
| layout(set = 0, binding = 0) buffer ssbo { uint y; }; |
| void main() { |
| atomicStore(y, 1u, gl_ScopeQueueFamily, gl_StorageSemanticsBuffer, gl_SemanticsRelease); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-vulkanMemoryModel-06266"); |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj cs(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, DeviceMemoryScopeDebugInfo) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredFeature(vkt::Feature::vulkanMemoryModel); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *csSource = R"( |
| OpCapability Shader |
| %2 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| %1 = OpString "a.comp" |
| OpSource GLSL 450 %1 "// OpModuleProcessed client vulkan100 |
| // OpModuleProcessed target-env vulkan1.0 |
| // OpModuleProcessed entry-point main |
| #line 1 |
| #version 450 |
| #extension GL_KHR_memory_scope_semantics : enable |
| layout(set = 0, binding = 0) buffer ssbo { uint y; }; |
| void main() { |
| atomicStore(y, 1u, gl_ScopeDevice, gl_StorageSemanticsBuffer, gl_SemanticsRelease); |
| }" |
| OpSourceExtension "GL_KHR_memory_scope_semantics" |
| OpName %main "main" |
| OpName %ssbo "ssbo" |
| OpMemberName %ssbo 0 "y" |
| OpName %_ "" |
| OpDecorate %ssbo BufferBlock |
| OpMemberDecorate %ssbo 0 Offset 0 |
| OpDecorate %_ Binding 0 |
| OpDecorate %_ DescriptorSet 0 |
| %void = OpTypeVoid |
| %4 = OpTypeFunction %void |
| %uint = OpTypeInt 32 0 |
| %ssbo = OpTypeStruct %uint |
| %_ptr_Uniform_ssbo = OpTypePointer Uniform %ssbo |
| %_ = OpVariable %_ptr_Uniform_ssbo Uniform |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %_ptr_Uniform_uint = OpTypePointer Uniform %uint |
| %uint_1 = OpConstant %uint 1 |
| %int_1 = OpConstant %int 1 |
| %int_64 = OpConstant %int 64 |
| %uint_0 = OpConstant %uint 0 |
| %uint_68 = OpConstant %uint 68 |
| OpLine %1 4 19 |
| %main = OpFunction %void None %4 |
| %6 = OpLabel |
| OpLine %1 5 0 |
| %14 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 |
| OpAtomicStore %14 %int_1 %uint_68 %uint_1 |
| OpLine %1 6 0 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| // VUID-RuntimeSpirv-vulkanMemoryModel-06265 |
| m_errorMonitor->SetDesiredError("5: atomicStore(y, 1u, gl_ScopeDevice, gl_StorageSemanticsBuffer, gl_SemanticsRelease);"); |
| VkShaderObj cs(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ConservativeRasterizationPostDepthCoverage) { |
| TEST_DESCRIPTION("Make sure conservativeRasterizationPostDepthCoverage is set if needed."); |
| |
| AddRequiredExtensions(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_rasterization_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(conservative_rasterization_props); |
| if (conservative_rasterization_props.conservativeRasterizationPostDepthCoverage) { |
| GTEST_SKIP() << "need conservativeRasterizationPostDepthCoverage to not be supported"; |
| } |
| InitRenderTarget(); |
| |
| std::string const source{R"( |
| OpCapability Shader |
| OpCapability SampleMaskPostDepthCoverage |
| OpCapability FragmentFullyCoveredEXT |
| OpExtension "SPV_EXT_fragment_fully_covered" |
| OpExtension "SPV_KHR_post_depth_coverage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %4 "main" %12 |
| OpExecutionMode %4 OriginUpperLeft |
| OpExecutionMode %4 EarlyFragmentTests |
| OpExecutionMode %4 PostDepthCoverage |
| OpDecorate %12 BuiltIn FullyCoveredEXT |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %bool = OpTypeBool |
| %_ptr_Input_bool = OpTypePointer Input %bool |
| %12 = OpVariable %_ptr_Input_bool Input |
| %4 = OpFunction %void None %3 |
| %5 = OpLabel |
| OpReturn |
| OpFunctionEnd)"}; |
| |
| m_errorMonitor->SetDesiredError("VUID-FullyCoveredEXT-conservativeRasterizationPostDepthCoverage-04235"); |
| VkShaderObj::CreateFromASM(this, source.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, DynamicUniformIndex) { |
| TEST_DESCRIPTION("Check for the array dynamic array index features when the SPIR-V capabilities are requested."); |
| |
| VkPhysicalDeviceFeatures features{}; |
| features.shaderUniformBufferArrayDynamicIndexing = VK_FALSE; |
| RETURN_IF_SKIP(Init(&features)); |
| |
| InitRenderTarget(); |
| |
| std::string const source{R"( |
| OpCapability Shader |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" |
| OpExecutionMode %main OriginUpperLeft |
| OpSource GLSL 450 |
| OpName %main "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| OpReturn |
| OpFunctionEnd)"}; |
| |
| { |
| std::string const capability{"OpCapability UniformBufferArrayDynamicIndexing"}; |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj::CreateFromASM(this, (capability + source).c_str(), VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| std::string const capability{"OpCapability SampledImageArrayDynamicIndexing"}; |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj::CreateFromASM(this, (capability + source).c_str(), VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| std::string const capability{"OpCapability StorageBufferArrayDynamicIndexing"}; |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj::CreateFromASM(this, (capability + source).c_str(), VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| std::string const capability{"OpCapability StorageImageArrayDynamicIndexing"}; |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj::CreateFromASM(this, (capability + source).c_str(), VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // TODO - This logic is illegal, but should be done in SPIRV-Tools |
| // see https://github.com/KhronosGroup/SPIRV-Tools/pull/4748 |
| TEST_F(NegativeShaderSpirv, DISABLED_ImageFormatTypeMismatchWithZeroExtend) { |
| TEST_DESCRIPTION("Use ZeroExtend to turn a SINT resource into a UINT, but only for some of the accesses."); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| RETURN_IF_SKIP(Init()); |
| RETURN_IF_SKIP(InitRenderTarget()); |
| if (DeviceValidationVersion() < VK_API_VERSION_1_2) { |
| GTEST_SKIP() << "At least Vulkan version 1.2 is required"; |
| } |
| |
| const char *csSource = R"( |
| OpCapability Shader |
| OpCapability StorageImageExtendedFormats |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %image_ptr |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpSource GLSL 450 |
| OpDecorate %image_ptr DescriptorSet 0 |
| OpDecorate %image_ptr Binding 0 |
| OpDecorate %image_ptr NonReadable |
| %type_void = OpTypeVoid |
| %type_u32 = OpTypeInt 32 0 |
| %type_i32 = OpTypeInt 32 1 |
| %type_vec3_u32 = OpTypeVector %type_u32 3 |
| %type_vec4_u32 = OpTypeVector %type_u32 4 |
| %type_vec2_i32 = OpTypeVector %type_i32 2 |
| %type_fn_void = OpTypeFunction %type_void |
| %type_ptr_fn = OpTypePointer Function %type_vec4_u32 |
| %type_image = OpTypeImage %type_u32 2D 0 0 0 2 Rgba32ui |
| %type_ptr_image = OpTypePointer UniformConstant %type_image |
| %image_ptr = OpVariable %type_ptr_image UniformConstant |
| %const_i32_0 = OpConstant %type_i32 0 |
| %const_vec2_i32_00 = OpConstantComposite %type_vec2_i32 %const_i32_0 %const_i32_0 |
| %main = OpFunction %type_void None %type_fn_void |
| %label = OpLabel |
| %store_location = OpVariable %type_ptr_fn Function |
| %image = OpLoad %type_image %image_ptr |
| ; Is accessing a SINT, no error |
| %value = OpImageRead %type_vec4_u32 %image %const_vec2_i32_00 SignExtend |
| ; But this will still be accessing a UINT, so errors |
| %value2 = OpImageRead %type_vec4_u32 %image %const_vec2_i32_00 |
| OpStore %store_location %value |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-StandaloneSpirv-Image-04965"); |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2, SPV_SOURCE_ASM); |
| pipe.dsl_bindings_[0] = {0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}; |
| pipe.CreateComputePipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // TODO - https://github.com/KhronosGroup/SPIRV-Tools/issues/5468 |
| TEST_F(NegativeShaderSpirv, DISABLED_SpecConstantTextureIndex) { |
| TEST_DESCRIPTION("Apply spec constant to lower array size and detect array being oob"); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fragment_source = R"glsl( |
| #version 400 |
| #extension GL_ARB_separate_shader_objects : enable |
| #extension GL_ARB_shading_language_420pack : enable |
| |
| layout (location = 0) out vec4 out_color; |
| |
| layout (constant_id = 0) const int num_textures = 3; |
| layout (binding = 0) uniform sampler2D textures[num_textures]; |
| |
| void main() { |
| out_color = texture(textures[2], vec2(0.0)); |
| } |
| )glsl"; |
| |
| uint32_t data = 2; // will make textures[2] OOB |
| VkSpecializationMapEntry entry = {0, 0, sizeof(uint32_t)}; |
| VkSpecializationInfo specialization_info = {1, &entry, sizeof(uint32_t), &data}; |
| const VkShaderObj fs(*m_device, fragment_source, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, |
| &specialization_info); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849"); |
| CreatePipelineHelper pipe(*this); |
| pipe.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, VK_SHADER_STAGE_ALL_GRAPHICS, nullptr}}; |
| pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, SpecConstantArraySize) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/SPIRV-Tools/issues/5921"); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fragment_source = R"glsl( |
| #version 450 |
| layout (constant_id = 0) const int array_size = 4; |
| layout(set = 0, binding = 0, std430) buffer foo { |
| uint a[array_size]; |
| uint b; // offset 16 to start |
| }; |
| |
| void main() { |
| b = 0; |
| } |
| )glsl"; |
| |
| uint32_t new_array_size = 6; |
| VkSpecializationMapEntry entry = {0, 0, sizeof(uint32_t)}; |
| VkSpecializationInfo specialization_info = {1, &entry, sizeof(uint32_t), &new_array_size}; |
| const VkShaderObj fs(*m_device, fragment_source, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, |
| &specialization_info); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849"); |
| CreatePipelineHelper pipe(*this); |
| pipe.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, VK_SHADER_STAGE_ALL_GRAPHICS, nullptr}}; |
| pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, DescriptorCountConstant) { |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| layout (set = 0, binding = 0) uniform sampler2D tex[3]; |
| layout (location = 0) out vec4 out_color; |
| void main() { |
| out_color = textureLodOffset(tex[1], vec2(0), 0, ivec2(0)); |
| } |
| )glsl"; |
| const VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-07991"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, DescriptorCountSpecConstant) { |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| layout (constant_id = 0) const int index = 2; |
| layout (set = 0, binding = 0) uniform sampler2D tex[index]; |
| layout (location = 0) out vec4 out_color; |
| void main() { |
| out_color = textureLodOffset(tex[1], vec2(0), 0, ivec2(0)); |
| } |
| )glsl"; |
| |
| uint32_t data = 4; // over VkDescriptorSetLayoutBinding::descriptorCount |
| VkSpecializationMapEntry entry = {0, 0, sizeof(uint32_t)}; |
| VkSpecializationInfo specialization_info = {1, &entry, sizeof(uint32_t), &data}; |
| const VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, |
| &specialization_info); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-07991"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, DescriptorCountSpecConstantOp) { |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| layout (constant_id = 0) const int index = 2; |
| // The length is now a OpSpecConstantOp |
| layout (set = 0, binding = 0) uniform sampler2D tex[index > 3 ? 3 : index]; |
| layout (location = 0) out vec4 out_color; |
| void main() { |
| out_color = textureLodOffset(tex[1], vec2(0), 0, ivec2(0)); |
| } |
| )glsl"; |
| |
| uint32_t data = 4; // over VkDescriptorSetLayoutBinding::descriptorCount |
| VkSpecializationMapEntry entry = {0, 0, sizeof(uint32_t)}; |
| VkSpecializationInfo specialization_info = {1, &entry, sizeof(uint32_t), &data}; |
| const VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, |
| &specialization_info); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-07991"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, DescriptorCountConstantRuntimeArray) { |
| TEST_DESCRIPTION("https://gitlab.khronos.org/vulkan/vulkan/-/issues/4111"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::runtimeDescriptorArray); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *fsSource = R"glsl( |
| #version 460 |
| #extension GL_EXT_nonuniform_qualifier : enable |
| layout (set = 0, binding = 0) uniform sampler2D tex[]; |
| layout (set = 0, binding = 1) uniform UBO { uint index; }; |
| layout (location = 0) out vec4 out_color; |
| void main() { |
| out_color = textureLodOffset(tex[index], vec2(0), 0, ivec2(0)); |
| } |
| )glsl"; |
| const VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_2); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-07991"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, InvalidExtension) { |
| TEST_DESCRIPTION("Use an invalid SPIR-V extension in OpExtension."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| RETURN_IF_SKIP(Init()); |
| |
| InitRenderTarget(); |
| |
| const char *vertex_source = R"spirv( |
| OpCapability Shader |
| OpExtension "GL_EXT_scalar_block_layout" |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %4 "main" |
| OpSource GLSL 450 |
| OpName %4 "main" |
| %2 = OpTypeVoid |
| %3 = OpTypeFunction %2 |
| %4 = OpFunction %2 None %3 |
| %5 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )spirv"; |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08741"); |
| VkShaderObj::CreateFromASM(this, vertex_source, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, FPFastMathDefault) { |
| TEST_DESCRIPTION("FPFastMathDefault missing required modes"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT_CONTROLS_2_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderFloatControls2); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPhysicalDeviceFloatControlsProperties shader_float_control = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(shader_float_control); |
| if (shader_float_control.shaderSignedZeroInfNanPreserveFloat32) { |
| GTEST_SKIP() << "shaderSignedZeroInfNanPreserveFloat32 is supported"; |
| } |
| |
| // Missing NotNaN |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability FloatControls2 |
| OpExtension "SPV_KHR_float_controls2" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionModeId %main FPFastMathDefault %float %constant |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %add FPFastMathMode NSZ|NotInf|NotNaN |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %constant = OpConstant %int 6 |
| %float = OpTypeFloat 32 |
| %zero = OpConstant %float 0 |
| %void_fn = OpTypeFunction %void |
| %main = OpFunction %void None %void_fn |
| %entry = OpLabel |
| OpReturn |
| OpFunctionEnd |
| %func = OpFunction %void None %void_fn |
| %func_entry = OpLabel |
| %add = OpFAdd %float %zero %zero |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderSignedZeroInfNanPreserveFloat32-09561"); |
| VkShaderObj cs(*m_device, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1, SPV_SOURCE_ASM); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, FPFastMathMode) { |
| TEST_DESCRIPTION("FPFastMathMode missing required modes"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT_CONTROLS_2_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderFloatControls2); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPhysicalDeviceFloatControlsProperties shader_float_control = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(shader_float_control); |
| if (shader_float_control.shaderSignedZeroInfNanPreserveFloat32) { |
| GTEST_SKIP() << "shaderSignedZeroInfNanPreserveFloat32 is supported"; |
| } |
| |
| // Missing NotNaN |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability FloatControls2 |
| OpExtension "SPV_KHR_float_controls2" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionModeId %main FPFastMathDefault %float %constant |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %add FPFastMathMode NSZ|NotInf |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %constant = OpConstant %int 7 |
| %float = OpTypeFloat 32 |
| %zero = OpConstant %float 0 |
| %void_fn = OpTypeFunction %void |
| %main = OpFunction %void None %void_fn |
| %entry = OpLabel |
| OpReturn |
| OpFunctionEnd |
| %func = OpFunction %void None %void_fn |
| %func_entry = OpLabel |
| %add = OpFAdd %float %zero %zero |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderSignedZeroInfNanPreserveFloat32-09562"); |
| VkShaderObj cs(*m_device, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1, SPV_SOURCE_ASM); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ScalarBlockLayoutShaderCache) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8031"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| // will NOT set --scalar-block-layout |
| RETURN_IF_SKIP(Init()); |
| |
| // Matches glsl from other ScalarBlockLayoutShaderCache test |
| const char *cs_source = R"glsl( |
| #version 460 |
| #extension GL_EXT_buffer_reference : require |
| #extension GL_EXT_scalar_block_layout : require |
| |
| struct Transform { |
| mat3x3 rotScaMatrix; // 0, 36 |
| vec3 pos; // 36, 12 |
| vec3 pos_err; // 48, 12 |
| float padding; // 60, 4 |
| }; |
| |
| layout(scalar, buffer_reference, buffer_reference_align = 64) readonly buffer Transforms { |
| Transform transforms[]; |
| }; |
| layout(std430, push_constant) uniform PushConstant { |
| Transforms pTransforms; |
| }; |
| |
| void main() { |
| Transform transform = pTransforms.transforms[0]; |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08737"); |
| VkShaderObj cs(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ImageGatherOffsetMaintenance8) { |
| AddRequiredFeature(vkt::Feature::shaderImageGatherExtended); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability ImageGatherExtended |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %tex DescriptorSet 0 |
| OpDecorate %tex Binding 2 |
| %void = OpTypeVoid |
| %4 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %8 = OpTypeImage %float 2D 0 0 0 1 Unknown |
| %9 = OpTypeSampledImage %8 |
| %_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9 |
| %tex = OpVariable %_ptr_UniformConstant_9 UniformConstant |
| %v2float = OpTypeVector %float 2 |
| %float_0 = OpConstant %float 0 |
| %15 = OpConstantComposite %v2float %float_0 %float_0 |
| %int = OpTypeInt 32 1 |
| %v2int = OpTypeVector %int 2 |
| %int_0 = OpConstant %int 0 |
| %19 = OpConstantComposite %v2int %int_0 %int_0 |
| %v4float = OpTypeVector %float 4 |
| %main = OpFunction %void None %4 |
| %6 = OpLabel |
| %12 = OpLoad %9 %tex |
| %21 = OpImageSampleExplicitLod %v4float %12 %15 Lod|Offset %float_0 %19 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-Offset-10213"); |
| VkShaderObj const fs(*m_device, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, VkShaderModuleCreateInfoPNext) { |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| VkPhysicalDeviceFeatures2 pd_features2 = vku::InitStructHelper(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCreateShaderModule-pCreateInfo-06904"); |
| VkShaderObj vs(*m_device, kMinimalShaderGlsl, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, nullptr, "main", |
| &pd_features2); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, NullShaderModuleCreateInfo) { |
| RETURN_IF_SKIP(Init()); |
| VkShaderModule module; |
| m_errorMonitor->SetDesiredError("VUID-vkCreateShaderModule-pCreateInfo-parameter"); |
| vk::CreateShaderModule(device(), nullptr, nullptr, &module); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderTileImageDisabled) { |
| TEST_DESCRIPTION("Validate creating graphics pipeline without shader tile image features enabled."); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredExtensions(VK_EXT_SHADER_TILE_IMAGE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| RETURN_IF_SKIP(Init()); |
| |
| { |
| // shaderTileImageDepthReadAccess |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj::CreateFromASM(this, kShaderTileImageDepthReadSpv, VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| // shaderTileImageStencilReadAccess |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj::CreateFromASM(this, kShaderTileImageStencilReadSpv, VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| // shaderTileImageColorReadAccess |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj::CreateFromASM(this, kShaderTileImageColorReadSpv, VK_SHADER_STAGE_FRAGMENT_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderViewportIndexLayerEXT) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9601"); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredFeature(vkt::Feature::multiViewport); |
| AddRequiredFeature(vkt::Feature::shaderOutputViewportIndex); |
| // missing shaderOutputLayer, need both features |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *vs_source = R"glsl( |
| #version 450 |
| #extension GL_ARB_shader_viewport_layer_array : enable |
| void main() { |
| gl_ViewportIndex = 1; |
| } |
| )glsl"; |
| |
| // 1.1 target env will produce old ShaderViewportIndexLayerEXT version |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj vs(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderRelaxedExtendedInstruction) { |
| TEST_DESCRIPTION("https://gitlab.khronos.org/vulkan/vulkan/-/issues/4252"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability PhysicalStorageBufferAddresses |
| OpExtension "SPV_KHR_physical_storage_buffer" |
| OpExtension "SPV_KHR_storage_buffer_storage_class" |
| OpExtension "SPV_KHR_non_semantic_info" |
| OpExtension "SPV_KHR_relaxed_extended_instruction" |
| %1 = OpExtInstImport "GLSL.std.450" |
| %ns = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" |
| OpMemoryModel PhysicalStorageBuffer64 GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| %x = OpString "x" |
| %file = OpString "a.comp" |
| %40 = OpString "float" |
| %mvp = OpString "MeshVertexPositions" |
| %source = OpString "test |
| test |
| test" |
| OpDecorate %_runtimearr_float ArrayStride 4 |
| OpDecorate %MeshVertexPositions Block |
| OpMemberDecorate %MeshVertexPositions 0 Offset 0 |
| OpDecorate %meshData AliasedPointer |
| OpMemberDecorate %Mesh_0 0 Offset 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| OpTypeForwardPointer %_fptr_MeshVertexPositions PhysicalStorageBuffer |
| %Mesh = OpTypeStruct %_fptr_MeshVertexPositions |
| %float = OpTypeFloat 32 |
| %uint = OpTypeInt 32 0 |
| %int = OpTypeInt 32 1 |
| %float_0 = OpConstant %float 0 |
| %int_0 = OpConstant %int 0 |
| %uint_0 = OpConstant %uint 0 |
| %uint_1 = OpConstant %uint 1 |
| %uint_2 = OpConstant %uint 2 |
| %uint_3 = OpConstant %uint 3 |
| %uint_4 = OpConstant %uint 4 |
| %uint_32 = OpConstant %uint 32 |
| %uint_5349 = OpConstant %uint 5349 |
| %_runtimearr_float = OpTypeRuntimeArray %float |
| %MeshVertexPositions = OpTypeStruct %_runtimearr_float |
| %_fptr_MeshVertexPositions = OpTypePointer PhysicalStorageBuffer %MeshVertexPositions |
| %_ptr_Function_Mesh = OpTypePointer Function %Mesh |
| %18 = OpExtInst %void %ns DebugSource %file %source |
| %55 = OpExtInst %void %ns DebugCompilationUnit %uint_1 %uint_4 %18 %uint_2 |
| %30 = OpExtInstWithForwardRefsKHR %void %ns DebugTypePointer %48 %uint_5349 %uint_0 |
| %Mesh_0 = OpTypeStruct %_fptr_MeshVertexPositions |
| %41 = OpExtInst %void %ns DebugTypeBasic %40 %uint_32 %uint_3 %uint_0 |
| %43 = OpExtInst %void %ns DebugTypeArray %41 %uint_0 |
| %45 = OpExtInst %void %ns DebugTypeMember %x %43 %18 %uint_1 %uint_0 %uint_0 %uint_0 %uint_3 |
| %48 = OpExtInst %void %ns DebugTypeComposite %mvp %uint_1 %18 %uint_1 %uint_0 %55 %mvp %uint_0 %uint_3 %45 |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| %meshData = OpVariable %_ptr_Function_Mesh Function |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderRelaxedExtendedInstruction-10773"); |
| VkShaderObj cs(*m_device, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, Bitwise32bitMaintenance9) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| RETURN_IF_SKIP(Init()); // missing maintenance9 |
| |
| const char *cs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable |
| void main() { |
| uint64_t x = 21; |
| int64_t y = bitCount(x); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-None-10824"); |
| VkShaderObj cs(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderFma32) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_KHR_SHADER_FMA_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderFmaFloat64); |
| AddRequiredFeature(vkt::Feature::shaderFloat64); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability FMAKHR |
| OpExtension "SPV_KHR_fma" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %_ |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %SSBO Block |
| OpMemberDecorate %SSBO 0 Offset 0 |
| OpDecorate %_ Binding 0 |
| OpDecorate %_ DescriptorSet 0 |
| %void = OpTypeVoid |
| %4 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %_ptr_Function_float = OpTypePointer Function %float |
| %float_1 = OpConstant %float 1 |
| %SSBO = OpTypeStruct %float |
| %_ptr_StorageBuffer_SSBO = OpTypePointer StorageBuffer %SSBO |
| %_ = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float |
| %main = OpFunction %void None %4 |
| %6 = OpLabel |
| %a = OpVariable %_ptr_Function_float Function |
| %b = OpVariable %_ptr_Function_float Function |
| %c = OpVariable %_ptr_Function_float Function |
| OpStore %a %float_1 |
| OpStore %b %float_1 |
| OpStore %c %float_1 |
| %load_a = OpLoad %float %a |
| %load_b = OpLoad %float %b |
| %load_c = OpLoad %float %c |
| %24 = OpFmaKHR %float %load_a %load_b %load_c |
| %26 = OpAccessChain %_ptr_StorageBuffer_float %_ %int_0 |
| OpStore %26 %24 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderFmaFloat32-10978"); |
| VkShaderObj cs(*m_device, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2, SPV_SOURCE_ASM); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderFmaNon32) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_KHR_SHADER_FMA_EXTENSION_NAME); |
| // Missing 16 and 64 support for FMA |
| AddRequiredFeature(vkt::Feature::shaderFmaFloat32); |
| AddRequiredFeature(vkt::Feature::shaderFloat64); |
| AddRequiredFeature(vkt::Feature::shaderFloat16); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability Float64 |
| OpCapability FMAKHR |
| OpExtension "SPV_KHR_fma" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %_ |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %SSBO Block |
| OpMemberDecorate %SSBO 0 Offset 0 |
| OpDecorate %_ Binding 0 |
| OpDecorate %_ DescriptorSet 0 |
| %void = OpTypeVoid |
| %4 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %float16 = OpTypeFloat 16 |
| %float64 = OpTypeFloat 64 |
| %_ptr_Function_float = OpTypePointer Function %float |
| %_ptr_Function_float16 = OpTypePointer Function %float16 |
| %_ptr_Function_float64 = OpTypePointer Function %float64 |
| %float_1 = OpConstant %float 1 |
| %float16_1 = OpConstant %float16 1 |
| %float64_1 = OpConstant %float64 1 |
| %SSBO = OpTypeStruct %float |
| %_ptr_StorageBuffer_SSBO = OpTypePointer StorageBuffer %SSBO |
| %_ = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %main = OpFunction %void None %4 |
| %6 = OpLabel |
| %a = OpVariable %_ptr_Function_float Function |
| %b = OpVariable %_ptr_Function_float Function |
| %c = OpVariable %_ptr_Function_float Function |
| %a16 = OpVariable %_ptr_Function_float16 Function |
| %b16 = OpVariable %_ptr_Function_float16 Function |
| %c16 = OpVariable %_ptr_Function_float16 Function |
| %a64 = OpVariable %_ptr_Function_float64 Function |
| %b64 = OpVariable %_ptr_Function_float64 Function |
| %c64 = OpVariable %_ptr_Function_float64 Function |
| |
| OpStore %a %float_1 |
| OpStore %b %float_1 |
| OpStore %c %float_1 |
| %load_a = OpLoad %float %a |
| %load_b = OpLoad %float %b |
| %load_c = OpLoad %float %c |
| %fma32 = OpFmaKHR %float %load_a %load_b %load_c |
| |
| OpStore %a16 %float16_1 |
| OpStore %b16 %float16_1 |
| OpStore %c16 %float16_1 |
| %load_a16 = OpLoad %float16 %a16 |
| %load_b16 = OpLoad %float16 %b16 |
| %load_c16 = OpLoad %float16 %c16 |
| %fma16 = OpFmaKHR %float16 %load_a16 %load_b16 %load_c16 |
| |
| OpStore %a64 %float64_1 |
| OpStore %b64 %float64_1 |
| OpStore %c64 %float64_1 |
| %load_a64 = OpLoad %float64 %a64 |
| %load_b64 = OpLoad %float64 %b64 |
| %load_c64 = OpLoad %float64 %c64 |
| %fma64 = OpFmaKHR %float64 %load_a64 %load_b64 %load_c64 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderFmaFloat16-10977"); |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderFmaFloat64-10979"); |
| VkShaderObj cs(*m_device, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2, SPV_SOURCE_ASM); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeShaderSpirv, ShaderUniformBufferUnsizedArray) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| // Missing shaderUniformBufferUnsizedArray |
| RETURN_IF_SKIP(Init()); |
| |
| const char *spv_source = R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %_ %__0 |
| OpExecutionMode %main LocalSize 1 1 1 |
| OpDecorate %_runtimearr_uint ArrayStride 16 |
| OpDecorate %SSBO Block |
| OpMemberDecorate %SSBO 0 Offset 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %UBO Block |
| OpMemberDecorate %UBO 0 Offset 0 |
| OpMemberDecorate %UBO 1 Offset 16 |
| OpDecorate %__0 Binding 0 |
| OpDecorate %__0 DescriptorSet 0 |
| %void = OpTypeVoid |
| %4 = OpTypeFunction %void |
| %uint = OpTypeInt 32 0 |
| %_runtimearr_uint = OpTypeRuntimeArray %uint |
| %SSBO = OpTypeStruct %_runtimearr_uint |
| %_ptr_StorageBuffer_SSBO = OpTypePointer StorageBuffer %SSBO |
| %_ = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %UBO = OpTypeStruct %uint %_runtimearr_uint |
| %_ptr_Uniform_UBO = OpTypePointer Uniform %UBO |
| %__0 = OpVariable %_ptr_Uniform_UBO Uniform |
| %_ptr_Uniform_uint = OpTypePointer Uniform %uint |
| %int_1 = OpConstant %int 1 |
| %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint |
| %main = OpFunction %void None %4 |
| %6 = OpLabel |
| %20 = OpAccessChain %_ptr_Uniform_uint %__0 %int_0 |
| %21 = OpLoad %uint %20 |
| %23 = OpAccessChain %_ptr_Uniform_uint %__0 %int_1 %21 |
| %24 = OpLoad %uint %20 |
| %26 = OpAccessChain %_ptr_StorageBuffer_uint %_ %int_0 %21 |
| OpStore %26 %24 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2, SPV_SOURCE_ASM); |
| pipe.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}; |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-shaderUniformBufferUnsizedArray-11806"); |
| pipe.CreateComputePipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |