| /* |
| * Copyright (c) 2020-2025 The Khronos Group Inc. |
| * Copyright (c) 2020-2025 Valve Corporation |
| * Copyright (c) 2020-2025 LunarG, Inc. |
| * Copyright (c) 2020-2025 Google, Inc. |
| * |
| * 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 <cstdint> |
| #include "../framework/layer_validation_tests.h" |
| #include "../framework/pipeline_helper.h" |
| #include "../framework/shader_object_helper.h" |
| #include "../framework/descriptor_helper.h" |
| #include "../framework/buffer_helper.h" |
| #include "../framework/gpu_av_helper.h" |
| #include "utils/math_utils.h" |
| |
| void DebugPrintfTests::InitDebugPrintfFramework(void *p_next, bool reserve_slot) { |
| VkValidationFeatureEnableEXT enables[] = {VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT, |
| VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT}; |
| VkValidationFeaturesEXT features = vku::InitStructHelper(p_next); |
| // Most tests don't need to reserve the slot, so keep it as an option for now |
| features.enabledValidationFeatureCount = reserve_slot ? 2 : 1; |
| features.disabledValidationFeatureCount = 0; |
| features.pEnabledValidationFeatures = enables; |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework(&features)); |
| |
| if (!CanEnableGpuAV(*this)) { |
| GTEST_SKIP() << "Requirements for GPU-AV are not met"; |
| } |
| } |
| |
| class NegativeDebugPrintf : public DebugPrintfTests { |
| public: |
| void BasicComputeTest(const char *shader, const char *message); |
| void BasicFormattingTest(const char *shader, bool warning = false); |
| }; |
| |
| void NegativeDebugPrintf::BasicComputeTest(const char *shader, const char *message) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo(message); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Float) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "float == 3.141500"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntUnsigned) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| uint foo = 127; |
| debugPrintfEXT("unsigned == %u", foo); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "unsigned == 127"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntUnsignedUnderflow) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| uint foo = 127; |
| debugPrintfEXT("underflow == %u", foo - 128); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "underflow == 4294967295"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntSignedOverflow) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| int foo = 2147483647; |
| debugPrintfEXT("overflow == %d", foo + 4); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "overflow == -2147483645"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, TwoFloats) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("Here are two float values %f, %F", 1.0, myfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Here are two float values 1.000000, 3.141500"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatPrecision) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("smaller float value %1.2f", myfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "smaller float value 3.14"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, TextBeforeAndAfter) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| int foo = -135; |
| debugPrintfEXT("Here's an integer %i with text before and after it", foo); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Here's an integer -135 with text before and after it"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntOctal) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| int foo = 256; |
| debugPrintfEXT("Here's an integer in octal %o and hex 0x%x", foo, foo); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Here's an integer in octal 400 and hex 0x100"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntOctalNegative) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| int foo = -4; |
| debugPrintfEXT("Here's an integer in octal %o and hex 0x%x", foo, foo); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Here's an integer in octal 37777777774 and hex 0xfffffffc"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntNegative) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| int foo = -135; |
| debugPrintfEXT("%d is a negative integer", foo); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "-135 is a negative integer"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatVector2) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec2 floatvec = vec2(1.2f, 2.2f); |
| debugPrintfEXT("vector of floats %v2f", floatvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of floats 1.200000, 2.200000"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatVector3) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec3 floatvec = vec3(1.2f, 2.2f, 3.2f); |
| debugPrintfEXT("vector of floats %v3f", floatvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of floats 1.200000, 2.200000, 3.200000"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatVector4) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec4 floatvec = vec4(1.2f, 2.2f, 3.2f, 4.2f); |
| debugPrintfEXT("vector of floats %v4f", floatvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of floats 1.200000, 2.200000, 3.200000"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatVectorPrecision) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec4 floatvec = vec4(1.2f, 2.2f, 3.2f, 4.2f); |
| debugPrintfEXT("vector of floats %1.2v4f", floatvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of floats 1.20, 2.20, 3.20, 4.20"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatVectorPrecisionZeroPad) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec2 floatvec = vec2(1.2f, 2.2f); |
| debugPrintfEXT("vector of floats %1.2v4f", floatvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of floats 1.20, 2.20, 0.00, 0.00"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatVectorZeroPad) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec2 floatvec = vec2(1.2f, 2.2f); |
| debugPrintfEXT("vector of floats %v4f", floatvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of floats 1.200000, 2.200000, 0.000000, 0.000000"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatVectorScientificNotation) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec2 floatvec = vec2(1.2f, 2.2f); |
| debugPrintfEXT("vector of floats %v2e", floatvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of floats 1.200000e+00, 2.200000e+00"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntVector) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| ivec3 intvec = ivec3(-4, 32, 64); |
| debugPrintfEXT("vector of ints %v3d", intvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of ints -4, 32, 64"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntVectorUnsigned) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| uvec3 intvec = uvec3(1, 2, 3); |
| debugPrintfEXT("vector of ints %v3u", intvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of ints 1, 2, 3"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntVectorHex) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| ivec3 intvec = ivec3(-4, 32, 64); |
| debugPrintfEXT("vector of ints %v3x", intvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of ints fffffffc, 20, 40"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, IntVectorZeroPad) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| ivec3 intvec = ivec3(1, 2, 3); |
| debugPrintfEXT("vector of ints %v4d", intvec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of ints 1, 2, 3, 0"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ScientificNotation) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float in sn %e and %E", myfloat, myfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "float in sn 3.141500e+00 and 3.141500E+00"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ScientificNotationPrecision) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float in sn %1.2e and %1.2E", myfloat, myfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "float in sn 3.14e+00 and 3.14E+00"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatShortest) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float in shortest %g and %G", myfloat, myfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "float in shortest 3.1415 and 3.1415"); |
| } |
| |
| // TODO - This prints out 0x1.921cacp+1 vs 0x1.921cac0000000p+1 depending on Windows or not |
| TEST_F(NegativeDebugPrintf, DISABLED_FloatHex) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float in hex %a and %A", myfloat, myfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "float in hex 0x1.921cacp+1 and 0X1.921CACP+1"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatHexPrecision) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float in hex %1.3a and %1.9A", myfloat, myfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "float in hex 0x1.922p+1 and 0X1.921CAC000P+1"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int64) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| debugPrintfEXT("Here's an unsigned long 0x%ul", bigvar); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Here's an unsigned long 0x2000000000000001"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int64Vector) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| u64vec4 vecul = u64vec4(bigvar, bigvar, bigvar, bigvar); |
| debugPrintfEXT("vector of ul %v4ul", vecul); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of ul 2000000000000001, 2000000000000001, 2000000000000001, 2000000000000001"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int64Hex) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| debugPrintfEXT("Unsigned long as decimal %lu and as hex 0x%lx", bigvar, bigvar); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Unsigned long as decimal 2305843009213693953 and as hex 0x2000000000000001"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int64VectorHex) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| u64vec2 vecul = u64vec2(bigvar, bigvar); |
| debugPrintfEXT("vector of lx 0x%v2lx", vecul); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of lx 0x2000000000000001, 2000000000000001"); |
| } |
| |
| // TODO - Windows trims the leading values and will print 0x001 (Linux ignores the Precision) |
| TEST_F(NegativeDebugPrintf, DISABLED_Int64VectorHexPrecision) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| u64vec2 vecul = u64vec2(bigvar, bigvar); |
| debugPrintfEXT("vector of lx 0x%1.3v2lx", vecul); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of lx 0x2000000000000001, 2000000000000001"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int64VectorDecimal) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| u64vec2 vecul = u64vec2(bigvar, bigvar); |
| debugPrintfEXT("vector of lu %v2lu", vecul); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of lu 2305843009213693953, 2305843009213693953"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Float64) { |
| AddRequiredFeature(vkt::Feature::shaderFloat64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float64 : enable |
| void main() { |
| float64_t foo = 1.23456789; |
| float bar = 1.23456789; |
| debugPrintfEXT("floats and doubles %f %f %f %f %f", foo, bar, foo, bar, foo); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "floats and doubles 1.234568 1.234568 1.234568 1.234568 1.234568"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Float64Vector) { |
| AddRequiredFeature(vkt::Feature::shaderFloat64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float64 : enable |
| void main() { |
| float64_t foo = 1.23456789; |
| f64vec3 vecfloat = f64vec3(foo, foo, foo); |
| debugPrintfEXT("vector of float64 %v3f", vecfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of float64 1.234568, 1.234568, 1.234568"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Float64VectorPrecision) { |
| AddRequiredFeature(vkt::Feature::shaderFloat64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float64 : enable |
| void main() { |
| float64_t foo = 1.23456789; |
| f64vec2 vecfloat = f64vec2(foo, foo); |
| debugPrintfEXT("vector of float64 %1.2v2f", vecfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of float64 1.23, 1.23"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FloatMix) { |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderFloat16); |
| AddRequiredFeature(vkt::Feature::shaderFloat64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float64 : enable |
| void main() { |
| float16_t a = float16_t(3.3333333333); |
| float b = 3.3333333333; |
| float64_t c = float64_t(3.3333333333); |
| debugPrintfEXT("%f %f %f %f", a, b, c, 3.3333333333f); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "3.332031 3.333333 3.333333 3.333333"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Float16) { |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderFloat16); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable |
| void main() { |
| float16_t foo = float16_t(3.3); |
| float bar = 3.3; |
| debugPrintfEXT("32, 16, 32 | %f %f %f", bar, foo, bar); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "32, 16, 32 | 3.300000 3.298828 3.300000"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Float16Vector) { |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderFloat16); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable |
| void main() { |
| float16_t foo = float16_t(3.3); |
| f16vec2 vecfloat = f16vec2(foo, foo); |
| debugPrintfEXT("vector of float16 %v2f", vecfloat); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "vector of float16 3.298828, 3.298828"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Float16Precision) { |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderFloat16); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable |
| void main() { |
| float16_t foo = float16_t(3.3); |
| debugPrintfEXT("float16 %1.3f", foo); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "float16 3.299"); |
| } |
| |
| // TODO casting is wrong |
| TEST_F(NegativeDebugPrintf, Int16) { |
| AddRequiredFeature(vkt::Feature::shaderInt16); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int16: enable |
| void main() { |
| uint16_t foo = uint16_t(123); |
| int16_t bar = int16_t(-123); |
| debugPrintfEXT("unsigned and signed %d %d", foo, bar); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "unsigned and signed 123 -123"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int16Vector) { |
| AddRequiredFeature(vkt::Feature::shaderInt16); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int16: enable |
| void main() { |
| uint16_t foo = uint16_t(123); |
| u16vec2 fooVec = u16vec2(foo, foo); |
| int16_t bar = int16_t(-123); |
| i16vec2 barVec = i16vec2(bar, bar); |
| debugPrintfEXT("unsigned and signed %v2d | %v2d", fooVec, barVec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "unsigned and signed 123, 123 | -123, -123"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int16Hex) { |
| AddRequiredFeature(vkt::Feature::shaderInt16); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int16: enable |
| void main() { |
| uint16_t foo = uint16_t(123); |
| int16_t bar = int16_t(-123); |
| debugPrintfEXT("unsigned and signed 0x%x 0x%x", foo, bar); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "unsigned and signed 0x7b 0xff85"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int8) { |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderInt8); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int8: enable |
| void main() { |
| uint8_t foo = uint8_t(123); |
| int8_t bar = int8_t(-123); |
| debugPrintfEXT("unsigned and signed %d %d", foo, bar); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "unsigned and signed 123 -123"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int8Vector) { |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderInt8); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int8: enable |
| void main() { |
| uint8_t foo = uint8_t(123); |
| u8vec2 fooVec = u8vec2(foo, foo); |
| int8_t bar = int8_t(-123); |
| i8vec2 barVec = i8vec2(bar, bar); |
| debugPrintfEXT("unsigned and signed %v2d | %v2d", fooVec, barVec); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "unsigned and signed 123, 123 | -123, -123"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int8Hex) { |
| AddRequiredExtensions(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderInt8); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_shader_explicit_arithmetic_types_int8: enable |
| void main() { |
| uint8_t foo = uint8_t(123); |
| int8_t bar = int8_t(-123); |
| debugPrintfEXT("unsigned and signed 0x%x 0x%x", foo, bar); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "unsigned and signed 0x7b 0x85"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, BoolAsHex) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| bool foo = true; |
| bool bar = false; |
| debugPrintfEXT("bool fun 0x%x%x%x%x", foo, bar, foo, bar); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "bool fun 0x1010"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, BoolVector) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| |
| bool foo(int x) { |
| return x == 1; |
| } |
| |
| void main() { |
| bool a = foo(1); |
| bool b = !a; |
| bvec2 c = bvec2(a, b); |
| debugPrintfEXT("bvec2 %v2u", c); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "bvec2 1, 0"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, BoolNonConstant) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| |
| bool foo(int x) { |
| return x == 1; |
| } |
| |
| void main() { |
| debugPrintfEXT("bool %u", foo(1)); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "bool 1"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int32Before) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| uint idx_32 = 42; |
| uint a = 1; |
| uint b = 2; |
| uint c = 3; |
| debugPrintfEXT("Results: %8d %8x %8x %8x\n", idx_32, a, b, c); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Results: 42 1 2 3"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int32After) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| uint idx_32 = 42; |
| uint a = 1; |
| uint b = 2; |
| uint c = 3; |
| debugPrintfEXT("Results: %8x %8x %8x %8d\n", a, b, c, idx_32); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Results: 1 2 3 42"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int64Before) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t idx_64 = 42; |
| uint a = 1; |
| uint b = 2; |
| uint c = 3; |
| |
| debugPrintfEXT("Results: %8lu %8x %8x %8x\n", idx_64, a, b, c); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Results: 42 1 2 3"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int64After) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t idx_64 = 42; |
| uint a = 1; |
| uint b = 2; |
| uint c = 3; |
| debugPrintfEXT("Results: %8x %8x %8x %8lu\n", a, b, c, idx_64); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Results: 1 2 3 42"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int64Signed) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| int64_t zero = 0; |
| int64_t neg1 = -1; |
| int64_t neg42 = -42; |
| int64_t negMin = -9223372036854775808l; // INT64_MIN |
| debugPrintfEXT("Results: %ld %ld %ld %ld\n", zero, neg1, neg42, negMin); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Results: 0 -1 -42 -9223372036854775808"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Int64SignedMix) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| int64_t pos = 42; |
| int64_t neg = -42; |
| int a = 1; |
| debugPrintfEXT("Results: %d %ld %ld %d\n", a, pos, neg, 2); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "Results: 1 42 -42 2"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, FunctionParam) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| int foo(int x, int y) { |
| debugPrintfEXT("x = %d | y = %d", x, y); |
| return x * 2; |
| } |
| void main() { |
| int z = 33; |
| foo(-125, z); |
| } |
| )glsl"; |
| BasicComputeTest(shader_source, "x = -125 | y = 33"); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Pointers) { |
| AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_buffer_reference : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| layout(buffer_reference) readonly buffer BDA { |
| uint payload; |
| }; |
| |
| layout(set = 0, binding = 0) uniform foo { |
| BDA address; |
| BDA address2; |
| }; |
| |
| void main() { |
| debugPrintfEXT("address = 0x%lx", uint64_t(address)); |
| debugPrintfEXT("address2 = %p", address2); |
| debugPrintfEXT("address3 = 0x%lx", uint64_t(address2)); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| vkt::Buffer block_buffer(*m_device, 16, 0, vkt::device_address); |
| vkt::Buffer in_buffer(*m_device, 64, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| |
| auto in_buffer_ptr = (VkDeviceAddress *)in_buffer.Memory().Map(); |
| in_buffer_ptr[0] = block_buffer.Address(); |
| in_buffer_ptr[1] = block_buffer.Address(); |
| |
| pipe.descriptor_set_.WriteDescriptorBufferInfo(0, in_buffer, 0, VK_WHOLE_SIZE); |
| pipe.descriptor_set_.UpdateDescriptorSets(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe.pipeline_layout_, 0, 1, |
| &pipe.descriptor_set_.set_, 0, nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("address = 0x"); |
| #if defined(_WIN32) |
| // TODO - Add 0x for user on Windows |
| m_errorMonitor->SetDesiredInfo("address2 = "); |
| #else |
| m_errorMonitor->SetDesiredInfo("address2 = 0x"); |
| #endif |
| m_errorMonitor->SetDesiredInfo("address3 = 0x"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Empty) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| int foo = -135; |
| debugPrintfEXT("First printf with a %% and no value"); |
| debugPrintfEXT("Second printf with a value %i", foo); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("First printf with a % and no value"); |
| m_errorMonitor->SetDesiredInfo("Second printf with a value -135"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MultipleFunctions) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| int data = 0; |
| |
| void fn2(bool x) { |
| if (x) { |
| debugPrintfEXT("fn2 x [%d]", data++); |
| } else { |
| debugPrintfEXT("fn2 !x [%d]", data++); |
| } |
| } |
| |
| void fn1() { |
| debugPrintfEXT("fn1 [%d]", data++); |
| fn2(true); |
| fn2(false); |
| } |
| |
| void main() { |
| debugPrintfEXT("START"); |
| fn1(); |
| debugPrintfEXT("END"); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("START"); |
| m_errorMonitor->SetDesiredInfo("fn1 [0]"); |
| m_errorMonitor->SetDesiredInfo("fn2 x [1]"); |
| m_errorMonitor->SetDesiredInfo("fn2 !x [2]"); |
| m_errorMonitor->SetDesiredInfo("END"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Fragment) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(location = 0) out vec4 outColor; |
| |
| void main() { |
| if (gl_FragCoord.x > 10 && gl_FragCoord.x < 11) { |
| if (gl_FragCoord.y > 10 && gl_FragCoord.y < 12) { |
| debugPrintfEXT("gl_FragCoord.xy %1.2f, %1.2f\n", gl_FragCoord.x, gl_FragCoord.y); |
| } |
| } |
| outColor = gl_FragCoord; |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, kVertexDrawPassthroughGlsl, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, shader_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("gl_FragCoord.xy 10.50, 10.50"); |
| m_errorMonitor->SetDesiredInfo("gl_FragCoord.xy 10.50, 11.50"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, HLSL) { |
| TEST_DESCRIPTION("Make sure HLSL input works"); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| // [numthreads(64, 1, 1)] |
| // void main(uint2 launchIndex: SV_DispatchThreadID) { |
| // if (launchIndex.x > 1 && launchIndex.x < 4) { |
| // printf("launchIndex %v2d", launchIndex); |
| // } |
| // } |
| const char *shader_source = R"( |
| OpCapability Shader |
| OpExtension "SPV_KHR_non_semantic_info" |
| %29 = OpExtInstImport "NonSemantic.DebugPrintf" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %launchIndex |
| OpExecutionMode %main LocalSize 64 1 1 |
| %27 = OpString "launchIndex %v2d" |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %launchIndex "launchIndex" |
| OpDecorate %launchIndex BuiltIn GlobalInvocationId |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %uint = OpTypeInt 32 0 |
| %v2uint = OpTypeVector %uint 2 |
| %_ptr_Function_v2uint = OpTypePointer Function %v2uint |
| %uint_0 = OpConstant %uint 0 |
| %_ptr_Function_uint = OpTypePointer Function %uint |
| %uint_1 = OpConstant %uint 1 |
| %bool = OpTypeBool |
| %uint_4 = OpConstant %uint 4 |
| %v3uint = OpTypeVector %uint 3 |
| %_ptr_Input_v3uint = OpTypePointer Input %v3uint |
| %launchIndex = OpVariable %_ptr_Input_v3uint Input |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| %param = OpVariable %_ptr_Function_v2uint Function |
| %35 = OpLoad %v3uint %launchIndex |
| %36 = OpCompositeExtract %uint %35 0 |
| %37 = OpCompositeExtract %uint %35 1 |
| %38 = OpCompositeConstruct %v2uint %36 %37 |
| OpStore %param %38 |
| %43 = OpAccessChain %_ptr_Function_uint %param %uint_0 |
| %44 = OpLoad %uint %43 |
| %45 = OpUGreaterThan %bool %44 %uint_1 |
| %46 = OpAccessChain %_ptr_Function_uint %param %uint_0 |
| %47 = OpLoad %uint %46 |
| %48 = OpULessThan %bool %47 %uint_4 |
| %49 = OpLogicalAnd %bool %45 %48 |
| OpSelectionMerge %53 None |
| OpBranchConditional %49 %50 %53 |
| %50 = OpLabel |
| %51 = OpLoad %v2uint %param |
| %52 = OpExtInst %void %29 1 %27 %51 |
| OpBranch %53 |
| %53 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| |
| )"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("launchIndex 2, 0"); |
| m_errorMonitor->SetDesiredInfo("launchIndex 3, 0"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MultiDraw) { |
| TEST_DESCRIPTION("Verify that calls to debugPrintfEXT are received in debug stream"); |
| AddRequiredExtensions(VK_EXT_MULTI_DRAW_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::multiDraw); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| vkt::Buffer buffer_in(*m_device, 8, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer_in, 0, sizeof(uint32_t)); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) uniform ufoo { |
| int whichtest; |
| } u_info; |
| void main() { |
| float myfloat = 3.1415f; |
| int foo = -135; |
| // referencing gl_InstanceIndex appears to be required to ensure this shader runs multiple times |
| // when called from vkCmdDrawMultiEXT(). |
| if (gl_VertexIndex == 0 && gl_InstanceIndex < 10000) { |
| switch(u_info.whichtest) { |
| case 0: |
| debugPrintfEXT("Here are two float values %f, %f", 1.0, myfloat); |
| break; |
| case 1: |
| debugPrintfEXT("Here's a smaller float value %1.2f", myfloat); |
| break; |
| } |
| } |
| gl_Position = vec4(0.0, 0.0, 0.0, 0.0); |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, shader_source, VK_SHADER_STAGE_VERTEX_BIT); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo()}; |
| pipe.rs_state_ci_.rasterizerDiscardEnable = VK_TRUE; |
| pipe.gp_ci_.layout = pipeline_layout; |
| pipe.CreateGraphicsPipeline(); |
| |
| VkMultiDrawInfoEXT multi_draws[3] = {}; |
| multi_draws[0].vertexCount = multi_draws[1].vertexCount = multi_draws[2].vertexCount = 3; |
| VkMultiDrawIndexedInfoEXT multi_draw_indices[3] = {}; |
| multi_draw_indices[0].indexCount = multi_draw_indices[1].indexCount = multi_draw_indices[2].indexCount = 3; |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDrawMultiEXT(m_command_buffer, 3, multi_draws, 1, 0, sizeof(VkMultiDrawInfoEXT)); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| VkDeviceAddress *data = (VkDeviceAddress *)buffer_in.Memory().Map(); |
| data[0] = 0; |
| for (auto i = 0; i < 3; i++) { |
| m_errorMonitor->SetDesiredInfo("Here are two float values 1.000000, 3.141500"); |
| } |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| vkt::Buffer buffer(*m_device, 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| uint16_t *ptr = static_cast<uint16_t *>(buffer.Memory().Map()); |
| ptr[0] = 0; |
| ptr[1] = 1; |
| ptr[2] = 2; |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdBindIndexBuffer(m_command_buffer, buffer, 0, VK_INDEX_TYPE_UINT16); |
| vk::CmdDrawMultiIndexedEXT(m_command_buffer, 3, multi_draw_indices, 1, 0, sizeof(VkMultiDrawIndexedInfoEXT), 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| data[0] = 1; |
| for (auto i = 0; i < 3; i++) { |
| m_errorMonitor->SetDesiredInfo("Here's a smaller float value 3.14"); |
| } |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MeshTaskShadersNV) { |
| TEST_DESCRIPTION("Test debug printf in mesh and task shaders."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(VK_NV_MESH_SHADER_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| |
| // Create a device that enables mesh_shader |
| VkPhysicalDeviceMeshShaderFeaturesNV mesh_shader_features = vku::InitStructHelper(); |
| GetPhysicalDeviceFeatures2(mesh_shader_features); |
| |
| RETURN_IF_SKIP(InitState(nullptr, &mesh_shader_features)); |
| InitRenderTarget(); |
| |
| const char taskShaderText[] = R"glsl( |
| #version 460 |
| #extension GL_NV_mesh_shader : enable |
| #extension GL_EXT_debug_printf : enable |
| layout(local_size_x = 32) in; |
| uint invocationID = gl_LocalInvocationID.x; |
| void main() { |
| if (invocationID == 0) { |
| gl_TaskCountNV = 1; |
| debugPrintfEXT("hello from task shader"); |
| } |
| } |
| )glsl"; |
| |
| const char meshShaderText[] = R"glsl( |
| #version 450 |
| #extension GL_NV_mesh_shader : require |
| #extension GL_EXT_debug_printf : enable |
| layout(local_size_x = 1) in; |
| layout(max_vertices = 3) out; |
| layout(max_primitives = 1) out; |
| layout(triangles) out; |
| uint invocationID = gl_LocalInvocationID.x; |
| void main() { |
| if (invocationID == 0) { |
| debugPrintfEXT("hello from mesh shader"); |
| } |
| } |
| )glsl"; |
| |
| VkShaderObj ts(*m_device, taskShaderText, VK_SHADER_STAGE_TASK_BIT_NV); |
| VkShaderObj ms(*m_device, meshShaderText, VK_SHADER_STAGE_MESH_BIT_NV); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {ts.GetStageCreateInfo(), ms.GetStageCreateInfo()}; |
| pipe.rs_state_ci_.rasterizerDiscardEnable = VK_TRUE; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDrawMeshTasksNV(m_command_buffer, 1, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("hello from task shader"); |
| m_errorMonitor->SetDesiredInfo("hello from mesh shader"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MeshShaders) { |
| TEST_DESCRIPTION("Test debug printf in mesh shaders."); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_MESH_SHADER_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::meshShader); |
| AddRequiredFeature(vkt::Feature::shaderDrawParameters); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| const char *mesh_source = R"glsl( |
| #version 460 |
| #extension GL_EXT_mesh_shader : enable |
| #extension GL_EXT_debug_printf : enable |
| layout(triangles, max_vertices = 3, max_primitives = 1) out; |
| |
| void main() { |
| debugPrintfEXT("gl_DrawID = %d\n", gl_DrawID); |
| SetMeshOutputsEXT(3, 1); |
| gl_MeshVerticesEXT[0].gl_Position = vec4(0); |
| gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2); |
| } |
| )glsl"; |
| |
| VkShaderObj ms(*m_device, mesh_source, VK_SHADER_STAGE_MESH_BIT_EXT, SPV_ENV_VULKAN_1_2); |
| VkShaderObj fs(*m_device, kFragmentMinimalGlsl, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_2); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {ms.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDrawMeshTasksEXT(m_command_buffer, 1, 1, 1); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("gl_DrawID = 0"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, TaskShaders) { |
| TEST_DESCRIPTION("Test debug printf in mesh shaders."); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_MESH_SHADER_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::taskShader); |
| AddRequiredFeature(vkt::Feature::meshShader); |
| AddRequiredFeature(vkt::Feature::shaderDrawParameters); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| const char *task_source = R"glsl( |
| #version 460 |
| #extension GL_EXT_mesh_shader : enable |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("gl_NumWorkGroups = %v3u\n", gl_NumWorkGroups); |
| EmitMeshTasksEXT(3, 1, 1); |
| } |
| )glsl"; |
| |
| VkShaderObj ts(*m_device, task_source, VK_SHADER_STAGE_TASK_BIT_EXT, SPV_ENV_VULKAN_1_2); |
| VkShaderObj ms(*m_device, kMeshMinimalGlsl, VK_SHADER_STAGE_MESH_BIT_EXT, SPV_ENV_VULKAN_1_2); |
| VkShaderObj fs(*m_device, kFragmentMinimalGlsl, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_2); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {ts.GetStageCreateInfo(), ms.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDrawMeshTasksEXT(m_command_buffer, 1, 1, 1); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("gl_NumWorkGroups = 1, 1, 1"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MeshTaskIndirect) { |
| TEST_DESCRIPTION("Test vkCmdDrawMeshTasksIndirectEXT"); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredExtensions(VK_EXT_MESH_SHADER_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance4); |
| AddRequiredFeature(vkt::Feature::meshShader); |
| AddRequiredFeature(vkt::Feature::taskShader); |
| AddRequiredFeature(vkt::Feature::fragmentStoresAndAtomics); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| vkt::Buffer draw_buffer(*m_device, sizeof(VkDrawMeshTasksIndirectCommandEXT), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, |
| kHostVisibleMemProps); |
| auto *draw_ptr = static_cast<VkDrawMeshTasksIndirectCommandEXT *>(draw_buffer.Memory().Map()); |
| draw_ptr->groupCountX = 1; |
| draw_ptr->groupCountY = 1; |
| draw_ptr->groupCountZ = 1; |
| |
| const char *task_source = R"glsl( |
| #version 460 |
| #extension GL_EXT_mesh_shader : enable |
| #extension GL_EXT_debug_printf : enable |
| taskPayloadSharedEXT uint payload; |
| void main() { |
| payload = gl_GlobalInvocationID.x + 4; |
| debugPrintfEXT("task %u", payload); |
| EmitMeshTasksEXT(1u, 1u, 1u); |
| } |
| )glsl"; |
| |
| const char *mesh_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_mesh_shader : require |
| #extension GL_EXT_debug_printf : enable |
| layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; |
| layout(max_vertices = 3, max_primitives = 1) out; |
| layout(triangles) out; |
| taskPayloadSharedEXT uint payload; |
| |
| void main() { |
| debugPrintfEXT("payload %u", payload); |
| SetMeshOutputsEXT(3, 1); |
| gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0); |
| gl_MeshVerticesEXT[1].gl_Position = vec4(1.0, -1.0, 0.0, 1.0); |
| gl_MeshVerticesEXT[2].gl_Position = vec4(0.0, 1.0, 0.0, 1.0); |
| gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2); |
| } |
| )glsl"; |
| |
| const char *frag_source = R"glsl( |
| #version 460 |
| #extension GL_EXT_debug_printf : enable |
| layout(location = 0) out vec4 uFragColor; |
| layout(set = 0, binding = 0) buffer ssbo { uint x; }; |
| void main(){ |
| uint count = atomicAdd(x, 1); |
| if (count == 0) { |
| debugPrintfEXT("frag"); |
| } |
| uFragColor = vec4(0,1,0,1); |
| } |
| )glsl"; |
| |
| VkShaderObj ts(*m_device, task_source, VK_SHADER_STAGE_TASK_BIT_EXT, SPV_ENV_VULKAN_1_3); |
| VkShaderObj ms(*m_device, mesh_source, VK_SHADER_STAGE_MESH_BIT_EXT, SPV_ENV_VULKAN_1_3); |
| VkShaderObj fs(*m_device, frag_source, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_3); |
| |
| vkt::Buffer buffer(*m_device, 4, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps); |
| ((uint32_t *)buffer.Memory().Map())[0] = 0; |
| |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {ts.GetStageCreateInfo(), ms.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.gp_ci_.layout = pipeline_layout; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDrawMeshTasksIndirectEXT(m_command_buffer, draw_buffer, 0, 1, sizeof(VkDrawMeshTasksIndirectCommandEXT)); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("task 4"); |
| m_errorMonitor->SetDesiredInfo("payload 4"); |
| m_errorMonitor->SetDesiredInfo("frag"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, GPL) { |
| TEST_DESCRIPTION("Verify debugPrintfEXT works with GPL"); |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| // Make a uniform buffer to be passed to the shader that contains the test number |
| vkt::Buffer buffer_in(*m_device, 8, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer_in, 0, sizeof(uint32_t)); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) uniform ufoo { |
| int whichtest; |
| } u_info; |
| void main() { |
| float myfloat = 3.1415f; |
| int foo = -135; |
| if (gl_VertexIndex == 0) { |
| switch(u_info.whichtest) { |
| case 0: |
| debugPrintfEXT("Here are two float values %f, %f", 1.0, myfloat); |
| break; |
| case 1: |
| debugPrintfEXT("Here's a smaller float value %1.2f", myfloat); |
| break; |
| case 2: |
| debugPrintfEXT("Here's an integer %i with text before and after it", foo); |
| break; |
| case 3: |
| foo = 256; |
| debugPrintfEXT("Here's an integer in octal %o and hex 0x%x", foo, foo); |
| break; |
| case 4: |
| debugPrintfEXT("%d is a negative integer", foo); |
| break; |
| case 5: |
| vec4 floatvec = vec4(1.2f, 2.2f, 3.2f, 4.2f); |
| debugPrintfEXT("Here's a vector of floats %1.2v4f", floatvec); |
| break; |
| case 6: |
| debugPrintfEXT("Here's a float in sn %e", myfloat); |
| break; |
| case 7: |
| debugPrintfEXT("Here's a float in sn %1.2e", myfloat); |
| break; |
| case 8: |
| debugPrintfEXT("Here's a float in shortest %g", myfloat); |
| break; |
| case 9: |
| debugPrintfEXT("Here's a float in hex %1.9a", myfloat); |
| break; |
| case 10: |
| debugPrintfEXT("First printf with a %% and no value"); |
| debugPrintfEXT("Second printf with a value %i", foo); |
| break; |
| } |
| } |
| gl_Position = vec4(0.0); |
| } |
| )glsl"; |
| |
| vkt::SimpleGPL pipe(*this, pipeline_layout, shader_source); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| std::vector<const char *> messages; |
| messages.emplace_back("Here are two float values 1.000000, 3.141500"); |
| messages.emplace_back("Here's a smaller float value 3.14"); |
| messages.emplace_back("Here's an integer -135 with text before and after it"); |
| messages.emplace_back("Here's an integer in octal 400 and hex 0x100"); |
| messages.emplace_back("-135 is a negative integer"); |
| messages.emplace_back("Here's a vector of floats 1.20, 2.20, 3.20, 4.20"); |
| messages.emplace_back("Here's a float in sn 3.141500e+00"); |
| messages.emplace_back("Here's a float in sn 3.14e+00"); |
| messages.emplace_back("Here's a float in shortest 3.1415"); |
| messages.emplace_back("Here's a float in hex 0x1.921cac000p+1"); |
| // Two error messages have to be last in the vector |
| messages.emplace_back("First printf with a % and no value"); |
| messages.emplace_back("Second printf with a value -135"); |
| for (uint32_t i = 0; i < messages.size(); i++) { |
| VkDeviceAddress *data = (VkDeviceAddress *)buffer_in.Memory().Map(); |
| data[0] = i; |
| buffer_in.Memory().Unmap(); |
| m_errorMonitor->SetDesiredInfo(messages[i]); |
| if (10 == i) { |
| m_errorMonitor->SetDesiredInfo(messages[i + 1]); |
| i++; |
| } |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeDebugPrintf, GPLMultiDraw) { |
| AddRequiredExtensions(VK_EXT_MULTI_DRAW_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::multiDraw); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| // Make a uniform buffer to be passed to the shader that contains the test number |
| vkt::Buffer buffer_in(*m_device, 8, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer_in, 0, sizeof(uint32_t)); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) uniform ufoo { |
| int whichtest; |
| } u_info; |
| void main() { |
| float myfloat = 3.1415f; |
| int foo = -135; |
| // referencing gl_InstanceIndex appears to be required to ensure this shader runs multiple times |
| // when called from vkCmdDrawMultiEXT(). |
| if (gl_VertexIndex == 0 && gl_InstanceIndex < 10000) { |
| switch(u_info.whichtest) { |
| case 0: |
| debugPrintfEXT("Here are two float values %f, %f", 1.0, myfloat); |
| break; |
| case 1: |
| debugPrintfEXT("Here's a smaller float value %1.2f", myfloat); |
| break; |
| } |
| } |
| gl_Position = vec4(0.0); |
| } |
| )glsl"; |
| vkt::SimpleGPL pipe(*this, pipeline_layout, shader_source); |
| |
| VkMultiDrawInfoEXT multi_draws[3] = {}; |
| multi_draws[0].vertexCount = multi_draws[1].vertexCount = multi_draws[2].vertexCount = 3; |
| VkMultiDrawIndexedInfoEXT multi_draw_indices[3] = {}; |
| multi_draw_indices[0].indexCount = multi_draw_indices[1].indexCount = multi_draw_indices[2].indexCount = 3; |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDrawMultiEXT(m_command_buffer, 3, multi_draws, 1, 0, sizeof(VkMultiDrawInfoEXT)); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| VkDeviceAddress *data = (VkDeviceAddress *)buffer_in.Memory().Map(); |
| data[0] = 0; |
| for (auto i = 0; i < 3; i++) { |
| m_errorMonitor->SetDesiredInfo("Here are two float values 1.000000, 3.141500"); |
| } |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| vkt::Buffer buffer(*m_device, 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| uint16_t *ptr = static_cast<uint16_t *>(buffer.Memory().Map()); |
| ptr[0] = 0; |
| ptr[1] = 1; |
| ptr[2] = 2; |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdBindIndexBuffer(m_command_buffer, buffer, 0, VK_INDEX_TYPE_UINT16); |
| vk::CmdDrawMultiIndexedEXT(m_command_buffer, 3, multi_draw_indices, 1, 0, sizeof(VkMultiDrawIndexedInfoEXT), 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| data[0] = 1; |
| for (auto i = 0; i < 3; i++) { |
| m_errorMonitor->SetDesiredInfo("Here's a smaller float value 3.14"); |
| } |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, GPLInt64) { |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| vkt::Buffer buffer_in(*m_device, 8, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer_in, 0, sizeof(uint32_t)); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| const char *shader_source_int64 = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| layout(set = 0, binding = 0) uniform ufoo { |
| int whichtest; |
| } u_info; |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| if (gl_VertexIndex == 0) { |
| switch(u_info.whichtest) { |
| case 0: |
| debugPrintfEXT("Here's an unsigned long 0x%ul", bigvar); |
| break; |
| case 1: |
| u64vec4 vecul = u64vec4(bigvar, bigvar, bigvar, bigvar); |
| debugPrintfEXT("Here's a vector of ul %v4ul", vecul); |
| break; |
| case 2: |
| debugPrintfEXT("Unsigned long as decimal %lu and as hex 0x%lx", bigvar, bigvar); |
| break; |
| } |
| } |
| gl_Position = vec4(0.0); |
| } |
| )glsl"; |
| |
| vkt::SimpleGPL pipe(*this, pipeline_layout, shader_source_int64); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| VkDeviceAddress *data = (VkDeviceAddress *)buffer_in.Memory().Map(); |
| data[0] = 0; |
| m_errorMonitor->SetDesiredInfo("Here's an unsigned long 0x2000000000000001"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| data[0] = 1; |
| m_errorMonitor->SetDesiredFailureMsg( |
| kInformationBit, "Here's a vector of ul 2000000000000001, 2000000000000001, 2000000000000001, 2000000000000001"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| data[0] = 2; |
| m_errorMonitor->SetDesiredFailureMsg(kInformationBit, |
| "Unsigned long as decimal 2305843009213693953 and as hex 0x2000000000000001"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, GPLFragment) { |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| VkDeviceSize buffer_size = 4; |
| vkt::Buffer vs_buffer(*m_device, buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps); |
| vkt::Buffer fs_buffer(*m_device, buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps); |
| |
| OneOffDescriptorSet vertex_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr}}); |
| OneOffDescriptorSet fragment_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}); |
| |
| // "Normal" sets |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&vertex_set.layout_, &fragment_set.layout_}); |
| vertex_set.WriteDescriptorBufferInfo(0, vs_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| vertex_set.UpdateDescriptorSets(); |
| fragment_set.WriteDescriptorBufferInfo(0, fs_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| fragment_set.UpdateDescriptorSets(); |
| |
| { |
| vvl::span<uint32_t> vert_data(static_cast<uint32_t *>(vs_buffer.Memory().Map()), |
| static_cast<uint32_t>(buffer_size) / sizeof(uint32_t)); |
| for (auto &v : vert_data) { |
| v = 0x01030507; |
| } |
| } |
| { |
| vvl::span<uint32_t> frag_data(static_cast<uint32_t *>(fs_buffer.Memory().Map()), |
| static_cast<uint32_t>(buffer_size) / sizeof(uint32_t)); |
| for (auto &v : frag_data) { |
| v = 0x02040608; |
| } |
| } |
| |
| const std::array<VkDescriptorSet, 2> desc_sets = {vertex_set.set_, fragment_set.set_}; |
| |
| const char vert_shader[] = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) readonly buffer Input { uint u_buffer[]; } v_in; // texel_buffer[4] |
| const vec2 vertices[3] = vec2[]( |
| vec2(-1.0, -1.0), |
| vec2(1.0, -1.0), |
| vec2(0.0, 1.0) |
| ); |
| void main() { |
| if (gl_VertexIndex == 0) { |
| const uint t = v_in.u_buffer[0]; |
| debugPrintfEXT("Vertex shader %i, 0x%x", gl_VertexIndex, t); |
| } |
| gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0); |
| } |
| )glsl"; |
| |
| const char frag_shader[] = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 1, binding = 0) readonly buffer Input { uint u_buffer[]; } f_in; // texel_buffer[4] |
| layout(location = 0) out vec4 c_out; |
| void main() { |
| c_out = vec4(1.0); |
| const uint t = f_in.u_buffer[0]; |
| debugPrintfEXT("Fragment shader 0x%x\n", t); |
| } |
| )glsl"; |
| |
| vkt::SimpleGPL pipe(*this, pipeline_layout, vert_shader, frag_shader); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, |
| static_cast<uint32_t>(desc_sets.size()), desc_sets.data(), 0, nullptr); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("Vertex shader 0, 0x1030507"); |
| m_errorMonitor->SetDesiredInfo("Fragment shader 0x2040608"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, GPLFragmentIndependentSets) { |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| VkDeviceSize buffer_size = 4; |
| vkt::Buffer vs_buffer(*m_device, buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps); |
| vkt::Buffer fs_buffer(*m_device, buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps); |
| |
| OneOffDescriptorSet vertex_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr}}); |
| OneOffDescriptorSet fragment_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}); |
| |
| // Independent sets |
| const vkt::PipelineLayout pipeline_layout_vs(*m_device, {&vertex_set.layout_, nullptr}, {}, |
| VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT); |
| const vkt::PipelineLayout pipeline_layout_fs(*m_device, {nullptr, &fragment_set.layout_}, {}, |
| VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&vertex_set.layout_, &fragment_set.layout_}, {}, |
| VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT); |
| |
| vertex_set.WriteDescriptorBufferInfo(0, vs_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| vertex_set.UpdateDescriptorSets(); |
| fragment_set.WriteDescriptorBufferInfo(0, fs_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| fragment_set.UpdateDescriptorSets(); |
| |
| { |
| vvl::span<uint32_t> vert_data(static_cast<uint32_t *>(vs_buffer.Memory().Map()), |
| static_cast<uint32_t>(buffer_size) / sizeof(uint32_t)); |
| for (auto &v : vert_data) { |
| v = 0x01030507; |
| } |
| } |
| { |
| vvl::span<uint32_t> frag_data(static_cast<uint32_t *>(fs_buffer.Memory().Map()), |
| static_cast<uint32_t>(buffer_size) / sizeof(uint32_t)); |
| for (auto &v : frag_data) { |
| v = 0x02040608; |
| } |
| } |
| |
| const std::array<VkDescriptorSet, 2> desc_sets = {vertex_set.set_, fragment_set.set_}; |
| |
| CreatePipelineHelper vertex_input_lib(*this); |
| vertex_input_lib.InitVertexInputLibInfo(); |
| vertex_input_lib.CreateGraphicsPipeline(false); |
| |
| const char vertshader[] = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) readonly buffer Input { uint u_buffer[]; } v_in; // texel_buffer[4] |
| const vec2 vertices[3] = vec2[]( |
| vec2(-1.0, -1.0), |
| vec2(1.0, -1.0), |
| vec2(0.0, 1.0) |
| ); |
| void main() { |
| if (gl_VertexIndex == 0) { |
| const uint t = v_in.u_buffer[0]; |
| debugPrintfEXT("Vertex shader %i, 0x%x", gl_VertexIndex, t); |
| } |
| gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0); |
| } |
| )glsl"; |
| const auto vs_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, vertshader); |
| vkt::GraphicsPipelineLibraryStage vs_stage(vs_spv, VK_SHADER_STAGE_VERTEX_BIT); |
| |
| VkViewport viewport = {0, 0, 1, 1, 0, 1}; |
| VkRect2D scissor = {{0, 0}, {1, 1}}; |
| CreatePipelineHelper pre_raster_lib(*this); |
| pre_raster_lib.InitPreRasterLibInfo(&vs_stage.stage_ci); |
| pre_raster_lib.vp_state_ci_.pViewports = &viewport; |
| pre_raster_lib.vp_state_ci_.pScissors = &scissor; |
| pre_raster_lib.gp_ci_.layout = pipeline_layout_vs; |
| pre_raster_lib.CreateGraphicsPipeline(false); |
| |
| const char frag_shader[] = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 1, binding = 0) readonly buffer Input { uint u_buffer[]; } f_in; // texel_buffer[4] |
| layout(location = 0) out vec4 c_out; |
| void main() { |
| c_out = vec4(1.0); |
| const uint t = f_in.u_buffer[0]; |
| debugPrintfEXT("Fragment shader 0x%x\n", t); |
| } |
| )glsl"; |
| const auto fs_spv = GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, frag_shader); |
| vkt::GraphicsPipelineLibraryStage fs_stage(fs_spv, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| CreatePipelineHelper frag_shader_lib(*this); |
| frag_shader_lib.InitFragmentLibInfo(&fs_stage.stage_ci); |
| frag_shader_lib.gp_ci_.layout = pipeline_layout_fs; |
| frag_shader_lib.CreateGraphicsPipeline(false); |
| |
| CreatePipelineHelper frag_out_lib(*this); |
| frag_out_lib.InitFragmentOutputLibInfo(); |
| frag_out_lib.CreateGraphicsPipeline(false); |
| |
| VkPipeline libraries[4] = { |
| vertex_input_lib, |
| pre_raster_lib, |
| frag_shader_lib, |
| frag_out_lib, |
| }; |
| VkPipelineLibraryCreateInfoKHR link_info = vku::InitStructHelper(); |
| link_info.libraryCount = size32(libraries); |
| link_info.pLibraries = libraries; |
| |
| VkGraphicsPipelineCreateInfo exe_pipe_ci = vku::InitStructHelper(&link_info); |
| exe_pipe_ci.layout = pre_raster_lib.gp_ci_.layout; |
| vkt::Pipeline pipe(*m_device, exe_pipe_ci); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, |
| static_cast<uint32_t>(desc_sets.size()), desc_sets.data(), 0, nullptr); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("Vertex shader 0, 0x1030507"); |
| m_errorMonitor->SetDesiredInfo("Fragment shader 0x2040608"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ShaderObjectsGraphics) { |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitDynamicRenderTarget(); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("vertex %d with value %f", gl_VertexIndex, myfloat); |
| gl_Position = vec4(0.0, 0.0, 0.0, 0.0); |
| } |
| )glsl"; |
| const vkt::Shader vs(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, shader_source)); |
| const vkt::Shader fs(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea()); |
| m_command_buffer.BindShaders(vs, fs); |
| SetDefaultDynamicStatesAll(m_command_buffer); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("vertex 0 with value 3.141500"); |
| m_errorMonitor->SetDesiredInfo("vertex 1 with value 3.141500"); |
| m_errorMonitor->SetDesiredInfo("vertex 2 with value 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ShaderObjects) { |
| TEST_DESCRIPTION("Verify that all various types of output works as expect with shader object"); |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| int foo = -135; |
| int bar = 256; |
| vec4 floatvec = vec4(1.2f, 2.2f, 3.2f, 4.2f); |
| |
| debugPrintfEXT("Here are two float values %f, %f", 1.0, myfloat); |
| debugPrintfEXT("Here's a smaller float value %1.2f", myfloat); |
| debugPrintfEXT("Here's an integer %i with text before and after it", foo); |
| debugPrintfEXT("Here's an integer in octal %o and hex 0x%x", bar, bar); |
| debugPrintfEXT("%d is a negative integer", foo); |
| debugPrintfEXT("Here's a vector of floats %1.2v4f", floatvec); |
| debugPrintfEXT("Here's a float in sn %e", myfloat); |
| debugPrintfEXT("Here's a float in sn %1.2e", myfloat); |
| debugPrintfEXT("Here's a float in shortest %g", myfloat); |
| debugPrintfEXT("Here's a float in hex %1.9a", myfloat); |
| } |
| )glsl"; |
| const vkt::Shader cs(*m_device, VK_SHADER_STAGE_COMPUTE_BIT, GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, shader_source)); |
| |
| m_command_buffer.Begin(); |
| const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_COMPUTE_BIT}; |
| vk::CmdBindShadersEXT(m_command_buffer, 1, stages, &cs.handle()); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("Here are two float values 1.000000, 3.141500"); |
| m_errorMonitor->SetDesiredInfo("Here's a smaller float value 3.14"); |
| m_errorMonitor->SetDesiredInfo("Here's an integer -135 with text before and after it"); |
| m_errorMonitor->SetDesiredInfo("Here's an integer in octal 400 and hex 0x100"); |
| m_errorMonitor->SetDesiredInfo("-135 is a negative integer"); |
| m_errorMonitor->SetDesiredInfo("Here's a vector of floats 1.20, 2.20, 3.20, 4.20"); |
| m_errorMonitor->SetDesiredInfo("Here's a float in sn 3.141500e+00"); |
| m_errorMonitor->SetDesiredInfo("Here's a float in sn 3.14e+00"); |
| m_errorMonitor->SetDesiredInfo("Here's a float in shortest 3.1415"); |
| m_errorMonitor->SetDesiredInfo("Here's a float in hex 0x1.921cac000p+1"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ShaderObjectsInt64) { |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| debugPrintfEXT("Here's an unsigned long 0x%ul", bigvar); |
| u64vec4 vecul = u64vec4(bigvar, bigvar, bigvar, bigvar); |
| debugPrintfEXT("Here's a vector of ul %v4ul", vecul); |
| debugPrintfEXT("Unsigned long as decimal %lu and as hex 0x%lx", bigvar, bigvar); |
| } |
| )glsl"; |
| const vkt::Shader cs(*m_device, VK_SHADER_STAGE_COMPUTE_BIT, GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, shader_source)); |
| |
| m_command_buffer.Begin(); |
| const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_COMPUTE_BIT}; |
| vk::CmdBindShadersEXT(m_command_buffer, 1, stages, &cs.handle()); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("Here's an unsigned long 0x2000000000000001"); |
| m_errorMonitor->SetDesiredFailureMsg( |
| kInformationBit, "Here's a vector of ul 2000000000000001, 2000000000000001, 2000000000000001, 2000000000000001"); |
| m_errorMonitor->SetDesiredFailureMsg(kInformationBit, |
| "Unsigned long as decimal 2305843009213693953 and as hex 0x2000000000000001"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ShaderObjectsMultiDraw) { |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_MULTI_DRAW_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| AddRequiredFeature(vkt::Feature::multiDraw); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitDynamicRenderTarget(); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| // referencing gl_InstanceIndex appears to be required to ensure this shader runs multiple times |
| // when called from vkCmdDrawMultiEXT(). |
| if (gl_VertexIndex == 0 && gl_InstanceIndex < 10000) { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("Here are two float values %f, %f", 1.0, myfloat); |
| } |
| gl_Position = vec4(0.0, 0.0, 0.0, 0.0); |
| } |
| )glsl"; |
| const vkt::Shader vs(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, shader_source)); |
| const vkt::Shader fs(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl); |
| |
| VkMultiDrawInfoEXT multi_draws[3] = {}; |
| multi_draws[0].vertexCount = multi_draws[1].vertexCount = multi_draws[2].vertexCount = 3; |
| VkMultiDrawIndexedInfoEXT multi_draw_indices[3] = {}; |
| multi_draw_indices[0].indexCount = multi_draw_indices[1].indexCount = multi_draw_indices[2].indexCount = 3; |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea()); |
| m_command_buffer.BindShaders(vs, fs); |
| SetDefaultDynamicStatesAll(m_command_buffer); |
| vk::CmdDrawMultiEXT(m_command_buffer, 3, multi_draws, 1, 0, sizeof(VkMultiDrawInfoEXT)); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| |
| for (auto i = 0; i < 3; i++) { |
| m_errorMonitor->SetDesiredInfo("Here are two float values 1.000000, 3.141500"); |
| } |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| vkt::Buffer buffer(*m_device, 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| uint16_t *ptr = static_cast<uint16_t *>(buffer.Memory().Map()); |
| ptr[0] = 0; |
| ptr[1] = 1; |
| ptr[2] = 2; |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea()); |
| m_command_buffer.BindShaders(vs, fs); |
| SetDefaultDynamicStatesAll(m_command_buffer); |
| vk::CmdBindIndexBuffer(m_command_buffer, buffer, 0, VK_INDEX_TYPE_UINT16); |
| vk::CmdDrawMultiIndexedEXT(m_command_buffer, 3, multi_draw_indices, 1, 0, sizeof(VkMultiDrawIndexedInfoEXT), 0); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| |
| for (auto i = 0; i < 3; i++) { |
| m_errorMonitor->SetDesiredInfo("Here are two float values 1.000000, 3.141500"); |
| } |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MeshTaskShaderObjects) { |
| TEST_DESCRIPTION("Test debug printf in mesh and task shader objects."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_MESH_SHADER_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance4); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| AddRequiredFeature(vkt::Feature::multiview); |
| AddRequiredFeature(vkt::Feature::meshShader); |
| AddRequiredFeature(vkt::Feature::taskShader); |
| |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitDynamicRenderTarget(); |
| |
| const char *taskShaderText = R"glsl( |
| #version 460 |
| #extension GL_EXT_mesh_shader : require // Requires SPIR-V 1.5 (Vulkan 1.2) |
| #extension GL_EXT_debug_printf : enable |
| layout (local_size_x=1, local_size_y=1, local_size_z=1) in; |
| void main() { |
| debugPrintfEXT("hello from task shader"); |
| EmitMeshTasksEXT(1u, 1u, 1u); |
| } |
| )glsl"; |
| |
| const char *meshShaderText = R"glsl( |
| #version 460 |
| #extension GL_EXT_mesh_shader : require // Requires SPIR-V 1.5 (Vulkan 1.2) |
| #extension GL_EXT_debug_printf : enable |
| layout(max_vertices = 3, max_primitives=1) out; |
| layout(triangles) out; |
| void main() { |
| debugPrintfEXT("hello from mesh shader"); |
| } |
| )glsl"; |
| |
| const vkt::Shader ts(*m_device, VK_SHADER_STAGE_TASK_BIT_EXT, |
| GLSLToSPV(VK_SHADER_STAGE_TASK_BIT_EXT, taskShaderText, SPV_ENV_VULKAN_1_3)); |
| const vkt::Shader ms(*m_device, VK_SHADER_STAGE_MESH_BIT_EXT, |
| GLSLToSPV(VK_SHADER_STAGE_MESH_BIT_EXT, meshShaderText, SPV_ENV_VULKAN_1_3)); |
| const vkt::Shader fs(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea()); |
| SetDefaultDynamicStatesAll(m_command_buffer); |
| vk::CmdSetRasterizerDiscardEnableEXT(m_command_buffer, VK_TRUE); |
| m_command_buffer.BindMeshShaders(ts, ms, fs); |
| vk::CmdDrawMeshTasksEXT(m_command_buffer, 1, 1, 1); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("hello from task shader"); |
| m_errorMonitor->SetDesiredInfo("hello from mesh shader"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, VertexFragmentSeparateShader) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| const char vert_shader[] = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| |
| const vec2 vertices[3] = vec2[]( vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(0.0, 1.0) ); |
| void main() { |
| debugPrintfEXT("Vertex value is %i", 4); |
| gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0); |
| } |
| )glsl"; |
| const char frag_shader[] = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| |
| layout(location = 0) out vec4 c_out; |
| void main() { |
| debugPrintfEXT("Fragment value is %i", 8); |
| c_out = vec4(0.0); |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, vert_shader, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, frag_shader, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| VkViewport viewport = {0, 0, 1, 1, 0, 1}; |
| VkRect2D scissor = {{0, 0}, {1, 1}}; |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.vp_state_ci_.pViewports = &viewport; |
| pipe.vp_state_ci_.pScissors = &scissor; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| for (auto i = 0; i < 3; i++) { |
| m_errorMonitor->SetDesiredInfo("Vertex value is 4"); |
| } |
| m_errorMonitor->SetDesiredInfo("Fragment value is 8"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, VertexFragmentMultiEntrypoint) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| // void vert_main() { |
| // debugPrintfEXT("Vertex value is %i", 4); |
| // gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0); |
| // } |
| // layout(location = 0) out vec4 c_out; |
| // void frag_main() { |
| // debugPrintfEXT("Fragment value is %i", 8); |
| // c_out = vec4(0.0); |
| // } |
| const char *shader_source = R"( |
| OpCapability Shader |
| OpExtension "SPV_KHR_non_semantic_info" |
| %9 = OpExtInstImport "NonSemantic.DebugPrintf" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %frag_main "frag_main" %c_out |
| OpEntryPoint Vertex %vert_main "vert_main" %_ %gl_VertexIndex |
| OpExecutionMode %frag_main OriginUpperLeft |
| %vert_str = OpString "Vertex value is %i" |
| %frag_str = OpString "Fragment value is %i" |
| OpDecorate %c_out Location 0 |
| OpMemberDecorate %gl_PerVertex 0 BuiltIn Position |
| OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize |
| OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance |
| OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance |
| OpDecorate %gl_PerVertex Block |
| OpDecorate %gl_VertexIndex BuiltIn VertexIndex |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %int = OpTypeInt 32 1 |
| %int_4 = OpConstant %int 4 |
| %int_8 = OpConstant %int 8 |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %uint = OpTypeInt 32 0 |
| %uint_1 = OpConstant %uint 1 |
| %_arr_float_uint_1 = OpTypeArray %float %uint_1 |
| %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 |
| %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex |
| %_ = OpVariable %_ptr_Output_gl_PerVertex Output |
| %int_0 = OpConstant %int 0 |
| %v2float = OpTypeVector %float 2 |
| %uint_3 = OpConstant %uint 3 |
| %_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3 |
| %float_n1 = OpConstant %float -1 |
| %24 = OpConstantComposite %v2float %float_n1 %float_n1 |
| %float_1 = OpConstant %float 1 |
| %26 = OpConstantComposite %v2float %float_1 %float_n1 |
| %float_0 = OpConstant %float 0 |
| %28 = OpConstantComposite %v2float %float_0 %float_1 |
| %29 = OpConstantComposite %_arr_v2float_uint_3 %24 %26 %28 |
| %_ptr_Input_int = OpTypePointer Input %int |
| %gl_VertexIndex = OpVariable %_ptr_Input_int Input |
| %int_3 = OpConstant %int 3 |
| %_ptr_Function__arr_v2float_uint_3 = OpTypePointer Function %_arr_v2float_uint_3 |
| %_ptr_Function_v2float = OpTypePointer Function %v2float |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %c_out = OpVariable %_ptr_Output_v4float Output |
| %16 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 |
| %vert_main = OpFunction %void None %3 |
| %5 = OpLabel |
| %indexable = OpVariable %_ptr_Function__arr_v2float_uint_3 Function |
| %10 = OpExtInst %void %9 1 %vert_str %int_4 |
| %32 = OpLoad %int %gl_VertexIndex |
| %34 = OpSMod %int %32 %int_3 |
| OpStore %indexable %29 |
| %38 = OpAccessChain %_ptr_Function_v2float %indexable %34 |
| %39 = OpLoad %v2float %38 |
| %40 = OpCompositeExtract %float %39 0 |
| %41 = OpCompositeExtract %float %39 1 |
| %42 = OpCompositeConstruct %v4float %40 %41 %float_0 %float_1 |
| %44 = OpAccessChain %_ptr_Output_v4float %_ %int_0 |
| OpStore %44 %42 |
| OpReturn |
| OpFunctionEnd |
| %frag_main = OpFunction %void None %3 |
| %f5 = OpLabel |
| %f10 = OpExtInst %void %9 1 %frag_str %int_8 |
| OpStore %c_out %16 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| VkShaderObj vs(*m_device, shader_source, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM, nullptr, "vert_main"); |
| VkShaderObj fs(*m_device, shader_source, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM, nullptr, |
| "frag_main"); |
| |
| VkViewport viewport = {0, 0, 1, 1, 0, 1}; |
| VkRect2D scissor = {{0, 0}, {1, 1}}; |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.vp_state_ci_.pViewports = &viewport; |
| pipe.vp_state_ci_.pScissors = &scissor; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| for (auto i = 0; i < 3; i++) { |
| m_errorMonitor->SetDesiredInfo("Vertex value is 4"); |
| } |
| m_errorMonitor->SetDesiredInfo("Fragment value is 8"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ShaderObjectFragment) { |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitDynamicRenderTarget(); |
| |
| const char *fs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| const vkt::Shader vert_shader(*m_device, VK_SHADER_STAGE_VERTEX_BIT, |
| GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexDrawPassthroughGlsl)); |
| const vkt::Shader frag_shader(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT, GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, fs_source)); |
| |
| VkRenderingInfo renderingInfo = vku::InitStructHelper(); |
| renderingInfo.colorAttachmentCount = 0; |
| renderingInfo.layerCount = 1; |
| renderingInfo.renderArea = {{0, 0}, {1, 1}}; |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRendering(renderingInfo); |
| SetDefaultDynamicStatesExclude({VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT}); |
| m_command_buffer.BindShaders(vert_shader, frag_shader); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ShaderObjectCompute) { |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *cs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| const vkt::Shader comp_shader(*m_device, VK_SHADER_STAGE_COMPUTE_BIT, GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, cs_source)); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BindCompShader(comp_shader); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, SetupErrorVersion) { |
| TEST_DESCRIPTION("Verify DebugPrintF can gracefully fail if not using Vulkan 1.1+"); |
| SetTargetApiVersion(VK_API_VERSION_1_0); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| |
| VkValidationFeatureEnableEXT enables[] = {VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT}; |
| VkValidationFeatureDisableEXT disables[] = { |
| VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT, VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT, |
| VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT, VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT}; |
| VkValidationFeaturesEXT features = vku::InitStructHelper(); |
| features.enabledValidationFeatureCount = 1; |
| features.disabledValidationFeatureCount = 4; |
| features.pEnabledValidationFeatures = enables; |
| features.pDisabledValidationFeatures = disables; |
| RETURN_IF_SKIP(InitFramework(&features)); |
| |
| if (!CanEnableGpuAV(*this)) { |
| GTEST_SKIP() << "Requirements for GPU-AV are not met"; |
| } |
| |
| m_errorMonitor->SetDesiredError("requires Vulkan 1.1 or later"); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->VerifyFound(); |
| |
| // Still make sure we can use Vulkan as expected without errors |
| |
| InitRenderTarget(); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| } |
| |
| TEST_F(NegativeDebugPrintf, LocalSizeId) { |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredFeature(vkt::Feature::maintenance4); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"( |
| OpCapability Shader |
| OpExtension "SPV_KHR_non_semantic_info" |
| %30 = OpExtInstImport "NonSemantic.DebugPrintf" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID |
| OpExecutionModeId %main LocalSizeId %8 %9 %10 |
| %29 = OpString "TEST" |
| OpDecorate %8 SpecId 0 |
| OpDecorate %9 SpecId 1 |
| OpDecorate %10 SpecId 2 |
| OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId |
| %void = OpTypeVoid |
| %4 = OpTypeFunction %void |
| %uint = OpTypeInt 32 0 |
| %8 = OpSpecConstant %uint 1 |
| %9 = OpSpecConstant %uint 1 |
| %10 = OpSpecConstant %uint 1 |
| %bool = OpTypeBool |
| %v3uint = OpTypeVector %uint 3 |
| %_ptr_Input_v3uint = OpTypePointer Input %v3uint |
| %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input |
| %uint_0 = OpConstant %uint 0 |
| %_ptr_Input_uint = OpTypePointer Input %uint |
| %uint_1 = OpConstant %uint 1 |
| %main = OpFunction %void None %4 |
| %6 = OpLabel |
| %17 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0 |
| %18 = OpLoad %uint %17 |
| %19 = OpIEqual %bool %18 %uint_0 |
| OpSelectionMerge %21 None |
| OpBranchConditional %19 %20 %21 |
| %20 = OpLabel |
| %23 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_1 |
| %24 = OpLoad %uint %23 |
| %25 = OpIEqual %bool %24 %uint_0 |
| OpBranch %21 |
| %21 = OpLabel |
| %26 = OpPhi %bool %19 %6 %25 %20 |
| OpSelectionMerge %28 None |
| OpBranchConditional %26 %27 %28 |
| %27 = OpLabel |
| %31 = OpExtInst %void %30 1 %29 |
| OpBranch %28 |
| %28 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| uint32_t workgroup_size[3] = {32, 32, 1}; |
| VkSpecializationMapEntry entries[3]; |
| entries[0] = {0, 0, sizeof(uint32_t)}; |
| entries[1] = {1, sizeof(uint32_t), sizeof(uint32_t)}; |
| entries[2] = {2, sizeof(uint32_t) * 2, sizeof(uint32_t)}; |
| |
| VkSpecializationInfo specialization_info = {}; |
| specialization_info.mapEntryCount = 3; |
| specialization_info.pMapEntries = entries; |
| specialization_info.dataSize = sizeof(uint32_t) * 3; |
| specialization_info.pData = workgroup_size; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_3, SPV_SOURCE_ASM, |
| &specialization_info); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 32, 32, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("TEST"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Maintenance5) { |
| TEST_DESCRIPTION("Test SPIRV is still checked if using new pNext in VkPipelineShaderStageCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| std::vector<uint32_t> shader = GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, shader_source); |
| |
| 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_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; |
| pipe.CreateComputePipeline(false); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, UseAllDescriptorSlotsPipelineReserved) { |
| TEST_DESCRIPTION("Reserve a descriptor slot and proceed to use them all anyway so debug printf can't"); |
| RETURN_IF_SKIP(InitDebugPrintfFramework(nullptr, true)); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| // Add one to use the descriptor slot we tried to reserve |
| const uint32_t set_limit = m_device->Physical().limits_.maxBoundDescriptorSets + 1; |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| // First try to use too many sets in the pipeline layout |
| { |
| m_errorMonitor->SetDesiredWarning( |
| "This Pipeline Layout has too many descriptor sets that will not allow GPU shader instrumentation to be setup for " |
| "pipelines created with it"); |
| std::vector<const vkt::DescriptorSetLayout *> layouts(set_limit); |
| for (uint32_t i = 0; i < set_limit; i++) { |
| layouts[i] = &descriptor_set.layout_; |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, layouts); |
| m_errorMonitor->VerifyFound(); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipe_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| // Will not print out because no slot was possible to put output buffer |
| |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| } |
| |
| // Reduce by one (so there is room now) and print something |
| { |
| std::vector<const vkt::DescriptorSetLayout *> layouts(set_limit - 1); |
| for (uint32_t i = 0; i < set_limit - 1; i++) { |
| layouts[i] = &descriptor_set.layout_; |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, layouts); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipe_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeDebugPrintf, UseAllDescriptorSlotsPipelineNotReserved) { |
| TEST_DESCRIPTION("Do not reserve a descriptor slot and proceed to use them all anyway so debug printf can't"); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| const uint32_t set_limit = m_device->Physical().limits_.maxBoundDescriptorSets; |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| // First try to use too many sets in the pipeline layout |
| { |
| m_errorMonitor->SetDesiredWarning( |
| "This Pipeline Layout has too many descriptor sets that will not allow GPU shader instrumentation to be setup for " |
| "pipelines created with it"); |
| std::vector<const vkt::DescriptorSetLayout *> layouts(set_limit); |
| for (uint32_t i = 0; i < set_limit; i++) { |
| layouts[i] = &descriptor_set.layout_; |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, layouts); |
| m_errorMonitor->VerifyFound(); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipe_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| // Will not print out because no slot was possible to put output buffer |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| } |
| |
| // Reduce by one (so there is room now) and print something |
| { |
| std::vector<const vkt::DescriptorSetLayout *> layouts(set_limit - 1); |
| for (uint32_t i = 0; i < set_limit - 1; i++) { |
| layouts[i] = &descriptor_set.layout_; |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, layouts); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipe_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeDebugPrintf, UseAllDescriptorSlotsPipelineGraphics) { |
| TEST_DESCRIPTION("Do not reserve a descriptor slot and proceed to use them all anyway so debug printf can't"); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, shader_source, VK_SHADER_STAGE_VERTEX_BIT); |
| |
| const uint32_t set_limit = m_device->Physical().limits_.maxBoundDescriptorSets; |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| // First try to use too many sets in the pipeline layout |
| { |
| m_errorMonitor->SetDesiredWarning( |
| "This Pipeline Layout has too many descriptor sets that will not allow GPU shader instrumentation to be setup for " |
| "pipelines created with it"); |
| std::vector<const vkt::DescriptorSetLayout *> layouts(set_limit); |
| for (uint32_t i = 0; i < set_limit; i++) { |
| layouts[i] = &descriptor_set.layout_; |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, layouts); |
| m_errorMonitor->VerifyFound(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()}; |
| pipe.gp_ci_.layout = pipe_layout; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| // Will not print out because no slot was possible to put output buffer |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| } |
| |
| // Reduce by one (so there is room now) and print something |
| { |
| std::vector<const vkt::DescriptorSetLayout *> layouts(set_limit - 1); |
| for (uint32_t i = 0; i < set_limit - 1; i++) { |
| layouts[i] = &descriptor_set.layout_; |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, layouts); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()}; |
| pipe.gp_ci_.layout = pipe_layout; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeDebugPrintf, UseAllDescriptorSlotsPipelineGPL) { |
| TEST_DESCRIPTION("Do not reserve a descriptor slot and proceed to use them all anyway so debug printf can't"); |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| const uint32_t set_limit = m_device->Physical().limits_.maxBoundDescriptorSets; |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| // First try to use too many sets in the pipeline layout |
| { |
| m_errorMonitor->SetDesiredWarning( |
| "This Pipeline Layout has too many descriptor sets that will not allow GPU shader instrumentation to be setup for " |
| "pipelines created with it"); |
| std::vector<const vkt::DescriptorSetLayout *> layouts(set_limit); |
| for (uint32_t i = 0; i < set_limit; i++) { |
| layouts[i] = &descriptor_set.layout_; |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, layouts); |
| m_errorMonitor->VerifyFound(); |
| |
| vkt::SimpleGPL pipe(*this, pipe_layout, shader_source); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| // Will not print out because no slot was possible to put output buffer |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| } |
| |
| // Reduce by one (so there is room now) and print something |
| { |
| std::vector<const vkt::DescriptorSetLayout *> layouts(set_limit - 1); |
| for (uint32_t i = 0; i < set_limit - 1; i++) { |
| layouts[i] = &descriptor_set.layout_; |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, layouts); |
| vkt::SimpleGPL pipe(*this, pipe_layout, shader_source); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeDebugPrintf, UseAllDescriptorSlotsShaderObjectReserved) { |
| TEST_DESCRIPTION("Reserve a descriptor slot and proceed to use them all anyway so debug printf can't"); |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| RETURN_IF_SKIP(InitDebugPrintfFramework(nullptr, true)); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| auto cs_spirv = GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, shader_source); |
| |
| // Add one to use the descriptor slot we tried to reserve |
| const uint32_t set_limit = m_device->Physical().limits_.maxBoundDescriptorSets + 1; |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| std::vector<VkDescriptorSetLayout> layouts; |
| for (uint32_t i = 0; i < set_limit; i++) { |
| layouts.push_back(descriptor_set.layout_); |
| } |
| |
| // First try to use too many sets in the Shader Object |
| { |
| m_errorMonitor->SetDesiredWarning( |
| "This Shader Object has too many descriptor sets that will not allow GPU shader instrumentation to be setup for " |
| "VkShaderEXT created with it"); |
| |
| const vkt::Shader comp_shader(*m_device, |
| ShaderCreateInfo(cs_spirv, VK_SHADER_STAGE_COMPUTE_BIT, set_limit, layouts.data())); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BindCompShader(comp_shader); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| // Will not print out because no slot was possible to put output buffer |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| } |
| |
| // Reduce by one (so there is room now) and print something |
| { |
| uint32_t under_set_limit = set_limit - 1; |
| std::vector<const vkt::DescriptorSetLayout *> vkt_layouts; |
| for (uint32_t i = 0; i < under_set_limit; i++) { |
| vkt_layouts.push_back(&descriptor_set.layout_); |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, vkt_layouts); |
| |
| const vkt::Shader comp_shader(*m_device, |
| ShaderCreateInfo(cs_spirv, VK_SHADER_STAGE_COMPUTE_BIT, under_set_limit, layouts.data())); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BindCompShader(comp_shader); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeDebugPrintf, UseAllDescriptorSlotsShaderObjectNotReserved) { |
| TEST_DESCRIPTION("Dont reserve a descriptor slot and proceed to use them all anyway so debug printf can't"); |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| auto cs_spirv = GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, shader_source); |
| |
| const uint32_t set_limit = m_device->Physical().limits_.maxBoundDescriptorSets; |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| std::vector<VkDescriptorSetLayout> layouts; |
| for (uint32_t i = 0; i < set_limit; i++) { |
| layouts.push_back(descriptor_set.layout_); |
| } |
| |
| // First try to use too many sets in the Shader Object |
| { |
| m_errorMonitor->SetDesiredWarning( |
| "This Shader Object has too many descriptor sets that will not allow GPU shader instrumentation to be setup for " |
| "VkShaderEXT created with it"); |
| |
| const vkt::Shader comp_shader(*m_device, |
| ShaderCreateInfo(cs_spirv, VK_SHADER_STAGE_COMPUTE_BIT, set_limit, layouts.data())); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BindCompShader(comp_shader); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| // Will not print out because no slot was possible to put output buffer |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| } |
| |
| // Reduce by one (so there is room now) and print something |
| { |
| uint32_t under_set_limit = set_limit - 1; |
| std::vector<const vkt::DescriptorSetLayout *> vkt_layouts; |
| for (uint32_t i = 0; i < under_set_limit; i++) { |
| vkt_layouts.push_back(&descriptor_set.layout_); |
| } |
| vkt::PipelineLayout pipe_layout(*m_device, vkt_layouts); |
| |
| const vkt::Shader comp_shader(*m_device, |
| ShaderCreateInfo(cs_spirv, VK_SHADER_STAGE_COMPUTE_BIT, set_limit - 1, layouts.data())); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BindCompShader(comp_shader); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeDebugPrintf, ShaderObjectMultiCreate) { |
| TEST_DESCRIPTION("Make sure we instrument every index of VkShaderCreateInfoEXT"); |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitDynamicRenderTarget(); |
| |
| const char *vs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| vec2 vertices[3]; |
| void main(){ |
| vertices[0] = vec2(-1.0, -1.0); |
| vertices[1] = vec2( 1.0, -1.0); |
| vertices[2] = vec2( 0.0, 1.0); |
| debugPrintfEXT("vertex == %u", gl_VertexIndex); |
| gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0); |
| } |
| )glsl"; |
| |
| const char *fs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, vs_source); |
| const auto frag_spv = GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, fs_source); |
| |
| VkShaderCreateInfoEXT shader_create_infos[2]; |
| shader_create_infos[0] = ShaderCreateInfoLink(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT); |
| shader_create_infos[1] = ShaderCreateInfoLink(frag_spv, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| VkShaderEXT shaders[2]; |
| vk::CreateShadersEXT(*m_device, 2, shader_create_infos, nullptr, shaders); |
| |
| VkRenderingInfo rendering_info = vku::InitStructHelper(); |
| rendering_info.colorAttachmentCount = 0; |
| rendering_info.layerCount = 1; |
| rendering_info.renderArea = {{0, 0}, {1, 1}}; |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRendering(rendering_info); |
| SetDefaultDynamicStatesExclude({VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT}); |
| const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT}; |
| vk::CmdBindShadersEXT(m_command_buffer, 2, stages, shaders); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("vertex == 0"); |
| m_errorMonitor->SetDesiredInfo("vertex == 1"); |
| m_errorMonitor->SetDesiredInfo("vertex == 2"); |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| for (uint32_t i = 0; i < 2; ++i) { |
| vk::DestroyShaderEXT(*m_device, shaders[i], nullptr); |
| } |
| } |
| |
| TEST_F(NegativeDebugPrintf, ShaderObjectBoundDescriptor) { |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) buffer SSBO { uint x; }; |
| void main() { |
| debugPrintfEXT("x is undefined %u", x); |
| } |
| )glsl"; |
| auto cs_spirv = GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, shader_source); |
| |
| vkt::Buffer storage_buffer(*m_device, 4, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| descriptor_set.WriteDescriptorBufferInfo(0, storage_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| const vkt::Shader comp_shader(*m_device, |
| ShaderCreateInfo(cs_spirv, VK_SHADER_STAGE_COMPUTE_BIT, 1, &descriptor_set.layout_.handle())); |
| m_command_buffer.Begin(); |
| m_command_buffer.BindCompShader(comp_shader); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("x is undefined"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ShaderObjectUnusedBoundDescriptor) { |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) buffer SSBO { uint x; }; |
| void main() { |
| debugPrintfEXT("x is undefined %u", x); |
| } |
| )glsl"; |
| auto cs_spirv = GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, shader_source); |
| |
| vkt::Buffer storage_buffer(*m_device, 4, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); |
| OneOffDescriptorSet descriptor_set0(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| OneOffDescriptorSet descriptor_set1(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set0.layout_, &descriptor_set1.layout_}); |
| descriptor_set0.WriteDescriptorBufferInfo(0, storage_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| descriptor_set0.UpdateDescriptorSets(); |
| descriptor_set1.WriteDescriptorBufferInfo(0, storage_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| descriptor_set1.UpdateDescriptorSets(); |
| |
| VkDescriptorSetLayout layouts[2] = {descriptor_set0.layout_, descriptor_set1.layout_}; |
| const vkt::Shader comp_shader(*m_device, ShaderCreateInfo(cs_spirv, VK_SHADER_STAGE_COMPUTE_BIT, 2, layouts)); |
| m_command_buffer.Begin(); |
| m_command_buffer.BindCompShader(comp_shader); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set0.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("x is undefined"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, OverflowBuffer) { |
| TEST_DESCRIPTION("go over the VK_LAYER_PRINTF_BUFFER_SIZE limit"); |
| uint32_t value = 128; |
| const VkLayerSettingEXT settings = {OBJECT_LAYER_NAME, "printf_buffer_size", VK_LAYER_SETTING_TYPE_UINT32_EXT, 1, &value}; |
| VkLayerSettingsCreateInfoEXT layer_settings_create_info = {VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr, 1, |
| &settings}; |
| RETURN_IF_SKIP(InitDebugPrintfFramework(&layer_settings_create_info)); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; |
| void main() { |
| debugPrintfEXT("WorkGroup %v3u | Invocation %v3u\n", gl_WorkGroupID, gl_LocalInvocationID); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 4, 4, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("WorkGroup"); // actual message |
| m_errorMonitor->SetDesiredInfo("Debug Printf message was truncated"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, OverflowBufferLoop) { |
| TEST_DESCRIPTION("go over the VK_LAYER_PRINTF_BUFFER_SIZE limit... by a LOT"); |
| uint32_t value = 128; |
| const VkLayerSettingEXT settings = {OBJECT_LAYER_NAME, "printf_buffer_size", VK_LAYER_SETTING_TYPE_UINT32_EXT, 1, &value}; |
| VkLayerSettingsCreateInfoEXT layer_settings_create_info = {VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr, 1, |
| &settings}; |
| RETURN_IF_SKIP(InitDebugPrintfFramework(&layer_settings_create_info)); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; |
| void main() { |
| for (uint i = 0; i < 2048; i++) { |
| debugPrintfEXT("WorkGroup %v3u | Invocation %v3u\n", gl_WorkGroupID, gl_LocalInvocationID); |
| } |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 4, 4, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("WorkGroup"); // actual message |
| m_errorMonitor->SetDesiredInfo("Debug Printf message was truncated"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| void NegativeDebugPrintf::BasicFormattingTest(const char *shader, bool warning) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(warning ? kWarningBit : kErrorBit, "DEBUG-PRINTF-FORMATTING"); |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNoVectorSize) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("vector of %v"); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedLargeVectorSize) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec4 myVec = vec4(0.0); |
| debugPrintfEXT("vector of %v5f", myVec); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedSmallVectorSize) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec4 myVec = vec4(0.0); |
| debugPrintfEXT("vector of %v1f", myVec); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNoSpecifier1) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("vector of %v3 f", vec3(0)); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNoSpecifier2) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("vector of %1.2l", 0); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedUnknown1) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("vector of %q"); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedUnknown2) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("vector of %U", 3); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedUnknown3) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("vector of %1,2f", 4.0f); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedExtraArguments) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("%d %d", 0, 1, 2, 3); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNoModifiers) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("test", 3); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedIsloatedPercent) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("test % this"); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNotEnoughArguments) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("test %d %d %d", 3); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNoArguments) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("%d %d"); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNotVectorArg) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec3 foo = vec3(1); |
| debugPrintfEXT("%v3f %v3f %v3f", vec3(0), foo, foo.x); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNotVectorParam) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec3 foo = vec3(1); |
| debugPrintfEXT("%v3f %v3f %f", vec3(0), foo, foo); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedVectorSmall) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("%v3f", vec2(0)); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedVectorLarge) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("%v3f", vec4(0)); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedFloat1) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float foo = 1.0f; |
| debugPrintfEXT("%d", foo); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedFloat2) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| int foo = 4; |
| debugPrintfEXT("%f", foo); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedFloatVector1) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec3 foo = vec3(1); |
| debugPrintfEXT("%v3d", foo); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedFloatVector2) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| uvec3 foo = uvec3(1); |
| debugPrintfEXT("%v3f", foo); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Misformatted64Int1) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t foo = 0x2000000000000001ul; |
| debugPrintfEXT("%u", foo); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Misformatted64Int2) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| int foo = 4; |
| debugPrintfEXT("%lu", 4); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Misformatted64IntVector1) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| u64vec2 vecul = u64vec2(bigvar, bigvar); |
| debugPrintfEXT("0x%v2x", vecul); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Misformatted64IntVector2) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uvec2 foo = uvec2(1); |
| debugPrintfEXT("0x%v2lx", foo); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, Misformatted64Bool) { |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| bool foo = true; |
| debugPrintfEXT("%lu", foo); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source, true); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedEmptyString) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT(""); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNewLine) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| uint x = 3; |
| debugPrintfEXT("\n\t%v3f\t\n", x); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedVectorNewLine) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| vec3 x = vec3(0); |
| debugPrintfEXT("x = %v3\n", x); |
| } |
| )glsl"; |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedPointer) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_buffer_reference : enable |
| layout(buffer_reference) readonly buffer BDA { |
| uint payload; |
| }; |
| layout(set = 0, binding = 0) uniform foo { |
| BDA address; |
| }; |
| void main() { |
| debugPrintfEXT("address = 0x%lx", address); |
| } |
| )glsl"; |
| AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MisformattedNotPointer) { |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_ARB_gpu_shader_int64 : enable |
| void main() { |
| uint64_t bigvar = 0x2000000000000001ul; |
| debugPrintfEXT("address = %p", bigvar); |
| } |
| )glsl"; |
| AddRequiredFeature(vkt::Feature::shaderInt64); |
| BasicFormattingTest(shader_source); |
| } |
| |
| TEST_F(NegativeDebugPrintf, ValidationAbort) { |
| TEST_DESCRIPTION("Verify that aborting DebugPrintf is safe."); |
| SetTargetApiVersion(VK_API_VERSION_1_0); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME); |
| |
| VkValidationFeatureEnableEXT enables[] = {VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT}; |
| VkValidationFeaturesEXT features = vku::InitStructHelper(); |
| // Most tests don't need to reserve the slot, so keep it as an option for now |
| features.enabledValidationFeatureCount = 1; |
| features.disabledValidationFeatureCount = 0; |
| features.pEnabledValidationFeatures = enables; |
| RETURN_IF_SKIP(InitFramework(&features)); |
| |
| m_errorMonitor->SetDesiredError("DebugPrintf is being disabled"); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->VerifyFound(); |
| |
| // Still make sure we can use Vulkan as expected without errors |
| InitRenderTarget(); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DualPipelines) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe_debug(*this); |
| pipe_debug.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe_debug.CreateComputePipeline(); |
| |
| CreateComputePipelineHelper pipe_normal(*this); |
| pipe_normal.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_normal); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); // no print |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_debug); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); // print |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); // print |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_normal); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); // no print |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_debug); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); // print |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DualCommandBufferHalfPrint) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe_debug(*this); |
| pipe_debug.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe_debug.CreateComputePipeline(); |
| |
| CreateComputePipelineHelper pipe_normal(*this); |
| pipe_normal.CreateComputePipeline(); |
| |
| vkt::CommandBuffer cb0(*m_device, m_command_pool); |
| vkt::CommandBuffer cb1(*m_device, m_command_pool); |
| |
| cb0.Begin(); |
| vk::CmdBindPipeline(cb0, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_normal); |
| vk::CmdDispatch(cb0, 1, 1, 1); |
| cb0.End(); |
| |
| cb1.Begin(); |
| vk::CmdBindPipeline(cb1, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_debug); |
| vk::CmdDispatch(cb1, 1, 1, 1); |
| cb1.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| |
| VkCommandBuffer cbs[2] = {cb0, cb1}; |
| VkSubmitInfo submit = vku::InitStructHelper(); |
| submit.commandBufferCount = 2; |
| submit.pCommandBuffers = cbs; |
| vk::QueueSubmit(m_default_queue->handle(), 1, &submit, VK_NULL_HANDLE); |
| m_default_queue->Wait(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DualCommandBufferBothPrint) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(push_constant) uniform PushConstants { int x; } pc; |
| void main() { |
| debugPrintfEXT("int == %u", pc.x); |
| } |
| )glsl"; |
| |
| VkPushConstantRange pc_range = {VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t)}; |
| VkPipelineLayoutCreateInfo pipe_layout_ci = vku::InitStructHelper(); |
| pipe_layout_ci.pushConstantRangeCount = 1; |
| pipe_layout_ci.pPushConstantRanges = &pc_range; |
| vkt::PipelineLayout pipeline_layout(*m_device, pipe_layout_ci); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| vkt::CommandBuffer cb0(*m_device, m_command_pool); |
| vkt::CommandBuffer cb1(*m_device, m_command_pool); |
| |
| uint32_t data = 4; |
| cb0.Begin(); |
| vk::CmdPushConstants(cb0, pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &data); |
| vk::CmdBindPipeline(cb0, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(cb0, 1, 1, 1); |
| cb0.End(); |
| |
| cb1.Begin(); |
| data = 8; |
| vk::CmdPushConstants(cb1, pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &data); |
| vk::CmdBindPipeline(cb1, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(cb1, 1, 1, 1); |
| cb1.End(); |
| |
| m_errorMonitor->SetDesiredInfo("int == 4"); // cb0 |
| m_errorMonitor->SetDesiredInfo("int == 8"); // cb1 |
| |
| VkCommandBuffer cbs[2] = {cb0, cb1}; |
| VkSubmitInfo submit = vku::InitStructHelper(); |
| submit.commandBufferCount = 2; |
| submit.pCommandBuffers = cbs; |
| vk::QueueSubmit(m_default_queue->handle(), 1, &submit, VK_NULL_HANDLE); |
| m_default_queue->Wait(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DualCommandBufferEmpty) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe_debug(*this); |
| pipe_debug.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe_debug.CreateComputePipeline(); |
| |
| CreateComputePipelineHelper pipe_normal(*this); |
| pipe_normal.CreateComputePipeline(); |
| |
| vkt::CommandBuffer cb0(*m_device, m_command_pool); |
| vkt::CommandBuffer cb1(*m_device, m_command_pool); |
| vkt::CommandBuffer cb2(*m_device, m_command_pool); |
| |
| // Empty to make sure nothing breaks |
| cb0.Begin(); |
| cb0.End(); |
| |
| cb2.Begin(); |
| cb2.End(); |
| |
| cb1.Begin(); |
| vk::CmdBindPipeline(cb1, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_debug); |
| vk::CmdDispatch(cb1, 1, 1, 1); |
| cb1.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| |
| VkCommandBuffer cbs[3] = {cb0, cb1, cb2}; |
| VkSubmitInfo submit = vku::InitStructHelper(); |
| submit.commandBufferCount = 3; |
| submit.pCommandBuffers = cbs; |
| vk::QueueSubmit(m_default_queue->handle(), 1, &submit, VK_NULL_HANDLE); |
| m_default_queue->Wait(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DispatchIndirect) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| vkt::Buffer indirect_buffer(*m_device, sizeof(VkDrawIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, |
| kHostVisibleMemProps); |
| auto indirect_command = static_cast<VkDispatchIndirectCommand *>(indirect_buffer.Memory().Map()); |
| indirect_command->x = 1; |
| indirect_command->y = 1; |
| indirect_command->z = 1; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatchIndirect(m_command_buffer, indirect_buffer, 0); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DispatchBase) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.flags = VK_PIPELINE_CREATE_DISPATCH_BASE; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatchBase(m_command_buffer, 1, 1, 1, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DrawIndexed) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| const char *vs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| vec2 vertices[3]; |
| void main(){ |
| vertices[0] = vec2(-1.0, -1.0); |
| vertices[1] = vec2( 1.0, -1.0); |
| vertices[2] = vec2( 0.0, 1.0); |
| gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0); |
| debugPrintfEXT("gl_VertexIndex %u\n", gl_VertexIndex); |
| } |
| )glsl"; |
| const char *fs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(location = 0) out vec4 outColor; |
| void main() { |
| if (gl_FragCoord.x > 0 && gl_FragCoord.x < 1 && gl_FragCoord.y > 0 && gl_FragCoord.y < 1) { |
| debugPrintfEXT("Hit Fragment\n"); |
| } |
| outColor = gl_FragCoord; |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| |
| vkt::Buffer index_buffer = vkt::IndexBuffer<uint32_t>(*m_device, {0, 1, 2}); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindIndexBuffer(m_command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT32); |
| vk::CmdDrawIndexed(m_command_buffer, 3, 1, 0, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("gl_VertexIndex 0"); |
| m_errorMonitor->SetDesiredInfo("gl_VertexIndex 1"); |
| m_errorMonitor->SetDesiredInfo("gl_VertexIndex 2"); |
| m_errorMonitor->SetDesiredInfo("Hit Fragment"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DrawIndexedIndirect) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| const char *fs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(location = 0) out vec4 outColor; |
| void main() { |
| if (gl_FragCoord.x > 0 && gl_FragCoord.x < 1 && gl_FragCoord.y > 0 && gl_FragCoord.y < 1) { |
| debugPrintfEXT("Hit Fragment\n"); |
| } |
| outColor = gl_FragCoord; |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, kVertexDrawPassthroughGlsl, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| |
| vkt::Buffer index_buffer = vkt::IndexBuffer<uint32_t>(*m_device, {0, 1, 2}); |
| |
| vkt::Buffer indirect_buffer(*m_device, sizeof(VkDrawIndexedIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, |
| kHostVisibleMemProps); |
| auto indirect_command = static_cast<VkDrawIndexedIndirectCommand *>(indirect_buffer.Memory().Map()); |
| indirect_command->indexCount = 3; |
| indirect_command->instanceCount = 1; |
| indirect_command->firstIndex = 1; |
| indirect_command->vertexOffset = 1; |
| indirect_command->firstInstance = 1; |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindIndexBuffer(m_command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT32); |
| vk::CmdDrawIndexedIndirect(m_command_buffer, indirect_buffer, 0, 1, sizeof(VkDrawIndexedIndirectCommand)); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("Hit Fragment"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DrawIndirectCount) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredFeature(vkt::Feature::drawIndirectCount); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| const char *fs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(location = 0) out vec4 outColor; |
| void main() { |
| if (gl_FragCoord.x > 0 && gl_FragCoord.x < 1 && gl_FragCoord.y > 0 && gl_FragCoord.y < 1) { |
| debugPrintfEXT("Hit Fragment\n"); |
| } |
| outColor = gl_FragCoord; |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, kVertexDrawPassthroughGlsl, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| |
| vkt::Buffer indirect_buffer(*m_device, sizeof(VkDrawIndexedIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, |
| kHostVisibleMemProps); |
| auto indirect_command = static_cast<VkDrawIndexedIndirectCommand *>(indirect_buffer.Memory().Map()); |
| indirect_command->indexCount = 3; |
| indirect_command->instanceCount = 1; |
| indirect_command->firstIndex = 1; |
| indirect_command->vertexOffset = 1; |
| indirect_command->firstInstance = 1; |
| |
| vkt::Buffer count_buffer(*m_device, sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, kHostVisibleMemProps); |
| uint32_t *count_ptr = static_cast<uint32_t *>(count_buffer.Memory().Map()); |
| *count_ptr = 1; |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdDrawIndirectCount(m_command_buffer, indirect_buffer, 0, count_buffer, 0, 1, sizeof(VkDrawIndirectCommand)); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("Hit Fragment"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DrawIndexedIndirectCount) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredFeature(vkt::Feature::drawIndirectCount); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| const char *fs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(location = 0) out vec4 outColor; |
| void main() { |
| if (gl_FragCoord.x > 0 && gl_FragCoord.x < 1 && gl_FragCoord.y > 0 && gl_FragCoord.y < 1) { |
| debugPrintfEXT("Hit Fragment\n"); |
| } |
| outColor = gl_FragCoord; |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, kVertexDrawPassthroughGlsl, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| |
| vkt::Buffer index_buffer = vkt::IndexBuffer<uint32_t>(*m_device, {0, 1, 2}); |
| |
| vkt::Buffer indirect_buffer(*m_device, sizeof(VkDrawIndexedIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, |
| kHostVisibleMemProps); |
| auto indirect_command = static_cast<VkDrawIndexedIndirectCommand *>(indirect_buffer.Memory().Map()); |
| indirect_command->indexCount = 3; |
| indirect_command->instanceCount = 1; |
| indirect_command->firstIndex = 1; |
| indirect_command->vertexOffset = 1; |
| indirect_command->firstInstance = 1; |
| |
| vkt::Buffer count_buffer(*m_device, sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, kHostVisibleMemProps); |
| uint32_t *count_ptr = static_cast<uint32_t *>(count_buffer.Memory().Map()); |
| *count_ptr = 1; |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindIndexBuffer(m_command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT32); |
| vk::CmdDrawIndexedIndirectCount(m_command_buffer, indirect_buffer, 0, count_buffer, 0, 1, sizeof(VkDrawIndexedIndirectCommand)); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("Hit Fragment"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DeviceGeneratedCommandsCompute) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::deviceGeneratedCommands); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT dgc_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(dgc_props); |
| if ((dgc_props.supportedIndirectCommandsShaderStagesPipelineBinding & VK_SHADER_STAGE_COMPUTE_BIT) == 0) { |
| GTEST_SKIP() << "VK_SHADER_STAGE_COMPUTE_BIT is not supported."; |
| } |
| |
| VkIndirectCommandsLayoutTokenEXT token; |
| token = vku::InitStructHelper(); |
| token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT; |
| token.offset = 0; |
| |
| VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper(); |
| command_layout_ci.shaderStages = VK_SHADER_STAGE_COMPUTE_BIT; |
| command_layout_ci.pipelineLayout = VK_NULL_HANDLE; |
| command_layout_ci.tokenCount = 1; |
| command_layout_ci.pTokens = &token; |
| vkt::IndirectCommandsLayout command_layout(*m_device, command_layout_ci); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("gl_NumWorkGroups %v3u\n", gl_NumWorkGroups); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| pipe.CreateComputePipeline(); |
| |
| VkGeneratedCommandsPipelineInfoEXT pipeline_info = vku::InitStructHelper(); |
| pipeline_info.pipeline = pipe; |
| |
| VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper(); |
| allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; |
| vkt::Buffer block_buffer(*m_device, 64, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, kHostVisibleMemProps, &allocate_flag_info); |
| |
| VkDeviceSize pre_process_size = 0; |
| { |
| VkGeneratedCommandsMemoryRequirementsInfoEXT dgc_mem_reqs = vku::InitStructHelper(&pipeline_info); |
| dgc_mem_reqs.indirectCommandsLayout = command_layout; |
| dgc_mem_reqs.indirectExecutionSet = VK_NULL_HANDLE; |
| dgc_mem_reqs.maxSequenceCount = 1; |
| VkMemoryRequirements2 mem_reqs2 = vku::InitStructHelper(); |
| vk::GetGeneratedCommandsMemoryRequirementsEXT(device(), &dgc_mem_reqs, &mem_reqs2); |
| pre_process_size = mem_reqs2.memoryRequirements.size; |
| } |
| |
| VkBufferUsageFlags2CreateInfo buffer_usage_flags = vku::InitStructHelper(); |
| buffer_usage_flags.usage = VK_BUFFER_USAGE_2_PREPROCESS_BUFFER_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(&buffer_usage_flags); |
| buffer_ci.size = pre_process_size; |
| vkt::Buffer pre_process_buffer(*m_device, buffer_ci, 0, &allocate_flag_info); |
| |
| VkDispatchIndirectCommand *block_buffer_ptr = (VkDispatchIndirectCommand *)block_buffer.Memory().Map(); |
| block_buffer_ptr->x = 2; |
| block_buffer_ptr->y = 1; |
| block_buffer_ptr->z = 1; |
| |
| VkGeneratedCommandsInfoEXT generated_commands_info = vku::InitStructHelper(&pipeline_info); |
| generated_commands_info.shaderStages = VK_SHADER_STAGE_COMPUTE_BIT; |
| generated_commands_info.indirectExecutionSet = VK_NULL_HANDLE; |
| generated_commands_info.indirectCommandsLayout = command_layout; |
| generated_commands_info.indirectAddressSize = sizeof(VkDispatchIndirectCommand); |
| generated_commands_info.indirectAddress = block_buffer.Address(); |
| generated_commands_info.preprocessAddress = pre_process_buffer.Address(); |
| generated_commands_info.preprocessSize = pre_process_size; |
| generated_commands_info.sequenceCountAddress = 0; |
| generated_commands_info.maxSequenceCount = 1; |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdExecuteGeneratedCommandsEXT(m_command_buffer, false, &generated_commands_info); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("gl_NumWorkGroups 2, 1, 1"); |
| m_errorMonitor->SetDesiredInfo("gl_NumWorkGroups 2, 1, 1"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DeviceGeneratedCommandsGraphics) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::deviceGeneratedCommands); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT dgc_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(dgc_props); |
| if ((dgc_props.supportedIndirectCommandsShaderStagesPipelineBinding & VK_SHADER_STAGE_VERTEX_BIT) == 0) { |
| GTEST_SKIP() << "VK_SHADER_STAGE_VERTEX_BIT is not supported."; |
| } |
| |
| VkIndirectCommandsLayoutTokenEXT token; |
| token = vku::InitStructHelper(); |
| token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT; |
| token.offset = 0; |
| |
| VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper(); |
| command_layout_ci.shaderStages = VK_SHADER_STAGE_VERTEX_BIT; |
| command_layout_ci.pipelineLayout = VK_NULL_HANDLE; |
| command_layout_ci.tokenCount = 1; |
| command_layout_ci.pTokens = &token; |
| vkt::IndirectCommandsLayout command_layout(*m_device, command_layout_ci); |
| |
| const char *vs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("gl_VertexIndex %u\n", gl_VertexIndex); |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo()}; |
| pipe.rs_state_ci_.rasterizerDiscardEnable = VK_TRUE; |
| pipe.CreateGraphicsPipeline(); |
| |
| VkGeneratedCommandsPipelineInfoEXT pipeline_info = vku::InitStructHelper(); |
| pipeline_info.pipeline = pipe; |
| |
| VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper(); |
| allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; |
| vkt::Buffer block_buffer(*m_device, 64, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, kHostVisibleMemProps, &allocate_flag_info); |
| |
| VkDeviceSize pre_process_size = 0; |
| { |
| VkGeneratedCommandsMemoryRequirementsInfoEXT dgc_mem_reqs = vku::InitStructHelper(&pipeline_info); |
| dgc_mem_reqs.indirectCommandsLayout = command_layout; |
| dgc_mem_reqs.indirectExecutionSet = VK_NULL_HANDLE; |
| dgc_mem_reqs.maxSequenceCount = 1; |
| VkMemoryRequirements2 mem_reqs2 = vku::InitStructHelper(); |
| vk::GetGeneratedCommandsMemoryRequirementsEXT(device(), &dgc_mem_reqs, &mem_reqs2); |
| pre_process_size = mem_reqs2.memoryRequirements.size; |
| } |
| |
| VkBufferUsageFlags2CreateInfo buffer_usage_flags = vku::InitStructHelper(); |
| buffer_usage_flags.usage = VK_BUFFER_USAGE_2_PREPROCESS_BUFFER_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(&buffer_usage_flags); |
| buffer_ci.size = pre_process_size; |
| vkt::Buffer pre_process_buffer(*m_device, buffer_ci, 0, &allocate_flag_info); |
| |
| VkDrawIndirectCommand *block_buffer_ptr = (VkDrawIndirectCommand *)block_buffer.Memory().Map(); |
| block_buffer_ptr->vertexCount = 3; |
| block_buffer_ptr->instanceCount = 1; |
| block_buffer_ptr->firstVertex = 0; |
| block_buffer_ptr->firstInstance = 0; |
| |
| VkGeneratedCommandsInfoEXT generated_commands_info = vku::InitStructHelper(&pipeline_info); |
| generated_commands_info.shaderStages = VK_SHADER_STAGE_VERTEX_BIT; |
| generated_commands_info.indirectExecutionSet = VK_NULL_HANDLE; |
| generated_commands_info.indirectCommandsLayout = command_layout; |
| generated_commands_info.indirectAddressSize = sizeof(VkDrawIndirectCommand); |
| generated_commands_info.indirectAddress = block_buffer.Address(); |
| generated_commands_info.preprocessAddress = pre_process_buffer.Address(); |
| generated_commands_info.preprocessSize = pre_process_size; |
| generated_commands_info.sequenceCountAddress = 0; |
| generated_commands_info.maxSequenceCount = 1; |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdExecuteGeneratedCommandsEXT(m_command_buffer, false, &generated_commands_info); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("gl_VertexIndex 0"); |
| m_errorMonitor->SetDesiredInfo("gl_VertexIndex 1"); |
| m_errorMonitor->SetDesiredInfo("gl_VertexIndex 2"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // TODO - Currently can't use IES with GPU-AV due to us creating invalid Pipeline Layouts |
| // https://github.com/KhronosGroup/Vulkan-ValidationLayers/pull/8806 |
| TEST_F(NegativeDebugPrintf, DISABLED_DeviceGeneratedCommandsIES) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::deviceGeneratedCommands); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT dgc_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(dgc_props); |
| if ((dgc_props.supportedIndirectCommandsShaderStagesPipelineBinding & VK_SHADER_STAGE_COMPUTE_BIT) == 0) { |
| GTEST_SKIP() << "VK_SHADER_STAGE_COMPUTE_BIT is not supported."; |
| } |
| |
| VkIndirectCommandsExecutionSetTokenEXT exe_set_token = {VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXT, |
| VK_SHADER_STAGE_COMPUTE_BIT}; |
| VkIndirectCommandsLayoutTokenEXT tokens[2]; |
| tokens[0] = vku::InitStructHelper(); |
| tokens[0].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT; |
| tokens[0].data.pExecutionSet = &exe_set_token; |
| tokens[0].offset = 0; |
| tokens[1] = vku::InitStructHelper(); |
| tokens[1].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT; |
| tokens[1].offset = sizeof(uint32_t); |
| |
| VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper(); |
| command_layout_ci.shaderStages = VK_SHADER_STAGE_COMPUTE_BIT; |
| command_layout_ci.pipelineLayout = VK_NULL_HANDLE; |
| command_layout_ci.tokenCount = 2; |
| command_layout_ci.pTokens = tokens; |
| vkt::IndirectCommandsLayout command_layout(*m_device, command_layout_ci); |
| |
| const char *shader_source_1 = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("Init Pipeline\n"); |
| } |
| )glsl"; |
| const char *shader_source_2 = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("IndirectExecutionSet Pipeline 1\n"); |
| } |
| )glsl"; |
| const char *shader_source_3 = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("IndirectExecutionSet Pipeline 2\n"); |
| } |
| )glsl"; |
| |
| VkPipelineCreateFlags2CreateInfo pipe_flags2 = vku::InitStructHelper(); |
| pipe_flags2.flags = VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT; |
| CreateComputePipelineHelper init_pipe(*this, &pipe_flags2); |
| init_pipe.cs_ = VkShaderObj(*m_device, shader_source_1, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| init_pipe.CreateComputePipeline(); |
| |
| CreateComputePipelineHelper pipe_1(*this, &pipe_flags2); |
| pipe_1.cs_ = VkShaderObj(*m_device, shader_source_2, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| pipe_1.CreateComputePipeline(); |
| |
| CreateComputePipelineHelper pipe_2(*this, &pipe_flags2); |
| pipe_2.cs_ = VkShaderObj(*m_device, shader_source_3, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_1); |
| pipe_2.CreateComputePipeline(); |
| |
| vkt::IndirectExecutionSet exe_set(*m_device, init_pipe, 3); |
| VkWriteIndirectExecutionSetPipelineEXT write_exe_sets[2]; |
| write_exe_sets[0] = vku::InitStructHelper(); |
| write_exe_sets[0].index = 1; |
| write_exe_sets[0].pipeline = pipe_1; |
| write_exe_sets[1] = vku::InitStructHelper(); |
| write_exe_sets[1].index = 2; |
| write_exe_sets[1].pipeline = pipe_2; |
| vk::UpdateIndirectExecutionSetPipelineEXT(device(), exe_set, 2, write_exe_sets); |
| |
| VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper(); |
| allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; |
| vkt::Buffer block_buffer(*m_device, 64, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, kHostVisibleMemProps, &allocate_flag_info); |
| |
| VkDeviceSize pre_process_size = 0; |
| { |
| VkGeneratedCommandsMemoryRequirementsInfoEXT dgc_mem_reqs = vku::InitStructHelper(); |
| dgc_mem_reqs.indirectCommandsLayout = command_layout; |
| dgc_mem_reqs.indirectExecutionSet = exe_set; |
| dgc_mem_reqs.maxSequenceCount = 1; |
| VkMemoryRequirements2 mem_reqs2 = vku::InitStructHelper(); |
| vk::GetGeneratedCommandsMemoryRequirementsEXT(device(), &dgc_mem_reqs, &mem_reqs2); |
| pre_process_size = mem_reqs2.memoryRequirements.size; |
| } |
| |
| VkBufferUsageFlags2CreateInfo buffer_usage_flags = vku::InitStructHelper(); |
| buffer_usage_flags.usage = VK_BUFFER_USAGE_2_PREPROCESS_BUFFER_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(&buffer_usage_flags); |
| buffer_ci.size = pre_process_size; |
| vkt::Buffer pre_process_buffer(*m_device, buffer_ci, 0, &allocate_flag_info); |
| |
| uint32_t *block_buffer_ptr = (uint32_t *)block_buffer.Memory().Map(); |
| block_buffer_ptr[0] = 2; // pick pipeline 2 |
| VkDispatchIndirectCommand *indirect_command_ptr = (VkDispatchIndirectCommand *)(block_buffer_ptr + 1); |
| indirect_command_ptr->x = 1; |
| indirect_command_ptr->y = 1; |
| indirect_command_ptr->z = 1; |
| |
| VkGeneratedCommandsInfoEXT generated_commands_info = vku::InitStructHelper(); |
| generated_commands_info.shaderStages = VK_SHADER_STAGE_COMPUTE_BIT; |
| generated_commands_info.indirectExecutionSet = exe_set; |
| generated_commands_info.indirectCommandsLayout = command_layout; |
| generated_commands_info.indirectAddressSize = sizeof(uint32_t) + sizeof(VkDispatchIndirectCommand); |
| generated_commands_info.indirectAddress = block_buffer.Address(); |
| generated_commands_info.preprocessAddress = pre_process_buffer.Address(); |
| generated_commands_info.preprocessSize = pre_process_size; |
| generated_commands_info.sequenceCountAddress = 0; |
| generated_commands_info.maxSequenceCount = 1; |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, init_pipe); |
| vk::CmdExecuteGeneratedCommandsEXT(m_command_buffer, false, &generated_commands_info); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("IndirectExecutionSet Pipeline 2"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MultipleComputePasses) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8763"); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source_1 = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(binding = 0, set = 0) uniform UBO { |
| float x; |
| }; |
| void main() { |
| debugPrintfEXT("float x == %f", x); |
| } |
| )glsl"; |
| const char *shader_source_2 = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| debugPrintfEXT("float y == %f", 3.14f); |
| } |
| )glsl"; |
| |
| vkt::Buffer buffer_in(*m_device, 8, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer_in, 0, sizeof(uint32_t)); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| CreateComputePipelineHelper pipe1(*this); |
| pipe1.cs_ = VkShaderObj(*m_device, shader_source_1, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe1.cp_ci_.layout = pipeline_layout; |
| pipe1.CreateComputePipeline(); |
| |
| CreateComputePipelineHelper pipe2(*this); |
| pipe2.cs_ = VkShaderObj(*m_device, shader_source_2, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe2.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe1); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe2); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float x =="); |
| m_errorMonitor->SetDesiredInfo("float y =="); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, SpecConstant) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(constant_id = 0) const uint value = 22; // default |
| void main() { |
| debugPrintfEXT("value is = %u", value); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe_22(*this); |
| pipe_22.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe_22.CreateComputePipeline(); |
| |
| const uint32_t value_44 = 44; |
| const uint32_t value_88 = 88; |
| |
| VkSpecializationMapEntry entry = {0, 0, sizeof(uint32_t)}; |
| VkSpecializationInfo spec_info_44 = {1, &entry, sizeof(uint32_t), &value_44}; |
| VkSpecializationInfo spec_info_88 = {1, &entry, sizeof(uint32_t), &value_88}; |
| |
| CreateComputePipelineHelper pipe_44(*this); |
| pipe_44.cs_ = |
| VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, &spec_info_44); |
| pipe_44.CreateComputePipeline(); |
| |
| CreateComputePipelineHelper pipe_88(*this); |
| pipe_88.cs_ = |
| VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, &spec_info_88); |
| pipe_88.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_22); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_44); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_88); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("value is = 22"); |
| m_errorMonitor->SetDesiredInfo("value is = 44"); |
| m_errorMonitor->SetDesiredInfo("value is = 88"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, InlineUniformBlock) { |
| AddRequiredExtensions(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::inlineUniformBlock); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) uniform UBO0 { uint ubo_0; }; |
| layout(set = 0, binding = 1) uniform InlineUBO { uint dummy; uint inline_value; }; |
| layout(set = 0, binding = 2) uniform UBO2 { uint ubo_2; }; |
| void main() { |
| debugPrintfEXT("binding [0] = %u | [1] = %u | [2] = %u", ubo_0, inline_value, ubo_2); |
| } |
| )glsl"; |
| |
| vkt::Buffer buffer(*m_device, 16, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| VkDeviceAddress *buffer_ptr = (VkDeviceAddress *)buffer.Memory().Map(); |
| buffer_ptr[0] = 3; |
| |
| VkDescriptorPoolInlineUniformBlockCreateInfo pool_inline_info = vku::InitStructHelper(); |
| pool_inline_info.maxInlineUniformBlockBindings = 1; |
| |
| OneOffDescriptorSet descriptor_set(m_device, |
| { |
| {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, 8, VK_SHADER_STAGE_ALL, nullptr}, |
| {2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, |
| }, |
| 0, nullptr, 0, nullptr, &pool_inline_info); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer, 0, VK_WHOLE_SIZE); |
| descriptor_set.WriteDescriptorBufferInfo(2, buffer, 0, VK_WHOLE_SIZE); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| const uint32_t print_value = 5; |
| VkWriteDescriptorSetInlineUniformBlock write_inline_uniform = vku::InitStructHelper(); |
| write_inline_uniform.dataSize = 4; |
| write_inline_uniform.pData = &print_value; |
| |
| VkWriteDescriptorSet descriptor_writes = vku::InitStructHelper(&write_inline_uniform); |
| descriptor_writes.dstSet = descriptor_set.set_; |
| descriptor_writes.dstBinding = 1; |
| descriptor_writes.dstArrayElement = 4; // offset 4 bytes |
| descriptor_writes.descriptorCount = 4; // Write 4 bytes |
| descriptor_writes.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK; |
| vk::UpdateDescriptorSets(device(), 1, &descriptor_writes, 0, nullptr); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("binding [0] = 3 | [1] = 5 | [2] = 3"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, StorageBufferLength) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::scalarBlockLayout); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_scalar_block_layout : enable |
| |
| layout(set = 0, binding = 0, scalar) buffer SSBO { |
| float a; |
| float b; |
| vec4 c[]; // offset 8 |
| }; |
| |
| void main() { |
| debugPrintfEXT("c length = %u", c.length()); |
| } |
| )glsl"; |
| |
| vkt::Buffer buffer_large(*m_device, 256, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps); |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| // Will have a length of 8 |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer_large, 0, 136, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("c length = 8"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| // Will only have a length of 1 vec4 |
| vkt::Buffer buffer_small(*m_device, 24, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps); |
| descriptor_set.Clear(); |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer_small, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| // Need to rebind even for the length - https://gitlab.khronos.org/vulkan/vulkan/-/issues/4143 |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("c length = 1"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, StorageBufferLengthUpdateAfterBind) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::scalarBlockLayout); |
| AddRequiredFeature(vkt::Feature::descriptorBindingStorageBufferUpdateAfterBind); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kInformationBit); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| #extension GL_EXT_scalar_block_layout : enable |
| |
| layout(set = 0, binding = 0, scalar) buffer SSBO { |
| float a; |
| float b; |
| vec4 c[]; // offset 8 |
| }; |
| |
| void main() { |
| debugPrintfEXT("c length = %u", c.length()); |
| } |
| )glsl"; |
| |
| OneOffDescriptorIndexingSet descriptor_set(m_device, { |
| {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr, |
| VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT}, |
| }); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| vkt::Buffer buffer_large(*m_device, 256, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps); |
| // Will have a length of 8 |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer_large, 0, 136, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| m_errorMonitor->SetDesiredInfo("c length = 8"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| // Will only have a length of 1 vec4 |
| vkt::Buffer buffer_small(*m_device, 24, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps); |
| descriptor_set.Clear(); |
| descriptor_set.WriteDescriptorBufferInfo(0, buffer_small, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| m_errorMonitor->SetDesiredInfo("c length = 1"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, PushDescriptor) { |
| AddRequiredExtensions(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) uniform Push { |
| uint a; |
| }; |
| layout(set = 1, binding = 0) uniform Normal { |
| uint b; |
| }; |
| void main() { |
| uint c = a + b; |
| debugPrintfEXT("%u + %u == %u", a, b, c); |
| } |
| )glsl"; |
| |
| vkt::Buffer buffer_a(*m_device, 16, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| auto buffer_a_ptr = (uint32_t *)buffer_a.Memory().Map(); |
| buffer_a_ptr[0] = 5; |
| vkt::Buffer buffer_b(*m_device, 16, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| auto buffer_b_ptr = (uint32_t *)buffer_b.Memory().Map(); |
| buffer_b_ptr[0] = 7; |
| |
| VkDescriptorSetLayoutBinding bindning = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; |
| OneOffDescriptorSet descriptor_set_0(m_device, {bindning}, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT); |
| OneOffDescriptorSet descriptor_set_1(m_device, {bindning}); |
| vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set_0.layout_, &descriptor_set_1.layout_}); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| VkDescriptorBufferInfo buffer_info = {buffer_a, 0, VK_WHOLE_SIZE}; |
| VkWriteDescriptorSet descriptor_write = vku::InitStructHelper(); |
| descriptor_write.dstSet = descriptor_set_0.set_; |
| descriptor_write.dstBinding = 0; |
| descriptor_write.dstArrayElement = 0; |
| descriptor_write.descriptorCount = 1; |
| descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; |
| descriptor_write.pBufferInfo = &buffer_info; |
| vk::CmdPushDescriptorSetKHR(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_write); |
| |
| descriptor_set_1.WriteDescriptorBufferInfo(0, buffer_b, 0, VK_WHOLE_SIZE); |
| descriptor_set_1.UpdateDescriptorSets(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 1, 1, &descriptor_set_1.set_, 0, |
| nullptr); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("5 + 7 == 12"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DescriptorTemplates) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) uniform UBO { |
| uint value; |
| } data[2]; |
| void main() { |
| debugPrintfEXT("value == %u", data[1].value); |
| } |
| )glsl"; |
| |
| vkt::Buffer buffer(*m_device, 8, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| auto buffer_ptr = (uint32_t *)buffer.Memory().Map(); |
| buffer_ptr[0] = 42; |
| |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, VK_SHADER_STAGE_ALL, nullptr}}); |
| vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| |
| struct SimpleTemplateData { |
| VkDescriptorBufferInfo buffer_info; |
| }; |
| |
| VkDescriptorUpdateTemplateEntry update_template_entry = {}; |
| update_template_entry.dstBinding = 0; |
| update_template_entry.dstArrayElement = 0; |
| update_template_entry.descriptorCount = 2; |
| update_template_entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; |
| update_template_entry.offset = 0; |
| update_template_entry.stride = sizeof(SimpleTemplateData); |
| |
| VkDescriptorUpdateTemplateCreateInfo update_template_ci = vku::InitStructHelper(); |
| update_template_ci.descriptorUpdateEntryCount = 1; |
| update_template_ci.pDescriptorUpdateEntries = &update_template_entry; |
| update_template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; |
| update_template_ci.descriptorSetLayout = descriptor_set.layout_; |
| vkt::DescriptorUpdateTemplate update_template(*m_device, update_template_ci); |
| |
| SimpleTemplateData update_template_data[2]; |
| update_template_data[0].buffer_info = {buffer, 0, VK_WHOLE_SIZE}; |
| update_template_data[1].buffer_info = {buffer, 0, VK_WHOLE_SIZE}; |
| vk::UpdateDescriptorSetWithTemplate(device(), descriptor_set.set_, update_template, update_template_data); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("value == 42"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, PushDescriptorTemplates) { |
| AddRequiredExtensions(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) uniform UBO { |
| uint value; |
| }; |
| void main() { |
| debugPrintfEXT("value == %u", value); |
| } |
| )glsl"; |
| |
| vkt::Buffer buffer(*m_device, 8, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps); |
| auto buffer_ptr = (uint32_t *)buffer.Memory().Map(); |
| buffer_ptr[0] = 42; |
| |
| vkt::DescriptorSetLayout push_dsl(*m_device, {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}, |
| VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT); |
| vkt::PipelineLayout pipeline_layout(*m_device, {&push_dsl}); |
| |
| struct SimpleTemplateData { |
| VkDescriptorBufferInfo buffer_info; |
| }; |
| |
| VkDescriptorUpdateTemplateEntry update_template_entry = {}; |
| update_template_entry.dstBinding = 0; |
| update_template_entry.dstArrayElement = 0; |
| update_template_entry.descriptorCount = 1; |
| update_template_entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; |
| update_template_entry.offset = 0; |
| update_template_entry.stride = sizeof(SimpleTemplateData); |
| |
| VkDescriptorUpdateTemplateCreateInfo update_template_ci = vku::InitStructHelper(); |
| update_template_ci.descriptorUpdateEntryCount = 1; |
| update_template_ci.pDescriptorUpdateEntries = &update_template_entry; |
| update_template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS; |
| update_template_ci.descriptorSetLayout = push_dsl; |
| update_template_ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; |
| update_template_ci.pipelineLayout = pipeline_layout; |
| |
| vkt::DescriptorUpdateTemplate update_template(*m_device, update_template_ci); |
| |
| SimpleTemplateData update_template_data; |
| update_template_data.buffer_info = {buffer, 0, VK_WHOLE_SIZE}; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdPushDescriptorSetWithTemplateKHR(m_command_buffer, update_template, pipeline_layout, 0, &update_template_data); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("value == 42"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DuplicateMessageLimit) { |
| TEST_DESCRIPTION("Default settings have a limit of 10, which we want to ignore"); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| |
| void main() { |
| for (uint i = 0; i < 6; i++) { |
| debugPrintfEXT("here\n", i); |
| } |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("here", 6); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredInfo("here", 6); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DuplicateMessageLimitExplicit) { |
| TEST_DESCRIPTION("Explicitly try and set the limit, which we ignore"); |
| uint32_t value = 3; |
| const VkLayerSettingEXT settings[2] = { |
| {OBJECT_LAYER_NAME, "enable_message_limit", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}, |
| {OBJECT_LAYER_NAME, "duplicate_message_limit", VK_LAYER_SETTING_TYPE_UINT32_EXT, 1, &value}}; |
| VkLayerSettingsCreateInfoEXT layer_settings_create_info = {VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr, 2, |
| settings}; |
| RETURN_IF_SKIP(InitDebugPrintfFramework(&layer_settings_create_info)); |
| RETURN_IF_SKIP(InitState()); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| |
| void main() { |
| for (uint i = 0; i < 6; i++) { |
| debugPrintfEXT("here\n", i); |
| } |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("here", 6); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredInfo("here", 6); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DescriptorBuffer) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::descriptorBuffer); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_buffer_properties = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(descriptor_buffer_properties); |
| |
| vkt::Buffer buffer_data(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vkt::device_address); |
| uint32_t *data = (uint32_t *)buffer_data.Memory().Map(); |
| data[0] = 8; |
| data[1] = 12; |
| data[2] = 1; |
| |
| VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; |
| vkt::DescriptorSetLayout ds_layout(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); |
| |
| VkPipelineLayoutCreateInfo pipe_layout_ci = vku::InitStructHelper(); |
| pipe_layout_ci.setLayoutCount = 1; |
| pipe_layout_ci.pSetLayouts = &ds_layout.handle(); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipe_layout_ci); |
| |
| VkDeviceSize ds_layout_size = ds_layout.GetDescriptorBufferSize(); |
| ds_layout_size = Align(ds_layout_size, descriptor_buffer_properties.descriptorBufferOffsetAlignment); |
| vkt::Buffer descriptor_buffer(*m_device, ds_layout_size, VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT, |
| vkt::device_address); |
| |
| vkt::DescriptorGetInfo get_info(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, buffer_data, 16); |
| void *mapped_descriptor_data = descriptor_buffer.Memory().Map(); |
| vk::GetDescriptorEXT(device(), get_info, descriptor_buffer_properties.storageBufferDescriptorSize, mapped_descriptor_data); |
| |
| const char *cs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout (set = 0, binding = 0) buffer SSBO_0 { |
| uint a; |
| uint b; |
| uint c; |
| }; |
| |
| void main() { |
| c = a + b; |
| debugPrintfEXT("c == %u\n", c); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2); |
| pipe.cp_ci_.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| |
| VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = vku::InitStructHelper(); |
| descriptor_buffer_binding_info.address = descriptor_buffer.Address(); |
| descriptor_buffer_binding_info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT; |
| vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1, &descriptor_buffer_binding_info); |
| |
| uint32_t buffer_index = 0; |
| VkDeviceSize buffer_offset = 0; |
| vk::CmdSetDescriptorBufferOffsetsEXT(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &buffer_index, |
| &buffer_offset); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("c == 20"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| |
| // One more time, but bind prior the pipeline |
| data[0] = 4; |
| data[1] = 6; |
| data[2] = 1; |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1, &descriptor_buffer_binding_info); |
| vk::CmdSetDescriptorBufferOffsetsEXT(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &buffer_index, |
| &buffer_offset); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| m_errorMonitor->SetDesiredInfo("c == 10"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DescriptorBufferGPL) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| AddRequiredFeature(vkt::Feature::descriptorBuffer); |
| AddRequiredFeature(vkt::Feature::fragmentStoresAndAtomics); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_buffer_properties = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(descriptor_buffer_properties); |
| |
| vkt::Buffer buffer_data(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vkt::device_address); |
| uint32_t *data = (uint32_t *)buffer_data.Memory().Map(); |
| data[0] = 8; |
| data[1] = 12; |
| data[2] = 1; |
| |
| VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; |
| vkt::DescriptorSetLayout ds_layout(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); |
| |
| VkPipelineLayoutCreateInfo pipe_layout_ci = vku::InitStructHelper(); |
| pipe_layout_ci.setLayoutCount = 1; |
| pipe_layout_ci.pSetLayouts = &ds_layout.handle(); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipe_layout_ci); |
| |
| VkDeviceSize ds_layout_size = ds_layout.GetDescriptorBufferSize(); |
| ds_layout_size = Align(ds_layout_size, descriptor_buffer_properties.descriptorBufferOffsetAlignment); |
| vkt::Buffer descriptor_buffer(*m_device, ds_layout_size, VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT, |
| vkt::device_address); |
| |
| vkt::DescriptorGetInfo get_info(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, buffer_data, 16); |
| void *mapped_descriptor_data = descriptor_buffer.Memory().Map(); |
| vk::GetDescriptorEXT(device(), get_info, descriptor_buffer_properties.storageBufferDescriptorSize, mapped_descriptor_data); |
| |
| const char *fs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout (set = 0, binding = 0) buffer SSBO_0 { |
| uint a; |
| uint b; |
| uint c; |
| }; |
| |
| void main() { |
| c = a + b; |
| if (gl_FragCoord.x > 10 && gl_FragCoord.x < 11 && gl_FragCoord.y > 10 && gl_FragCoord.y < 11) { |
| debugPrintfEXT("c == %u\n", c); |
| } |
| } |
| )glsl"; |
| |
| CreatePipelineHelper vertex_input_lib(*this); |
| vertex_input_lib.InitVertexInputLibInfo(); |
| vertex_input_lib.CreateGraphicsPipeline(false); |
| |
| CreatePipelineHelper pre_raster_lib(*this); |
| { |
| const auto vs_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexDrawPassthroughGlsl); |
| vkt::GraphicsPipelineLibraryStage vs_stage(vs_spv, VK_SHADER_STAGE_VERTEX_BIT); |
| pre_raster_lib.InitPreRasterLibInfo(&vs_stage.stage_ci); |
| pre_raster_lib.gp_ci_.layout = pipeline_layout; |
| pre_raster_lib.CreateGraphicsPipeline(false); |
| } |
| |
| CreatePipelineHelper frag_shader_lib(*this); |
| { |
| const auto fs_spv = GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, fs_source); |
| vkt::GraphicsPipelineLibraryStage fs_stage(fs_spv, VK_SHADER_STAGE_FRAGMENT_BIT); |
| frag_shader_lib.InitFragmentLibInfo(&fs_stage.stage_ci); |
| frag_shader_lib.gp_ci_.layout = pipeline_layout; |
| frag_shader_lib.CreateGraphicsPipeline(false); |
| } |
| |
| CreatePipelineHelper frag_out_lib(*this); |
| frag_out_lib.InitFragmentOutputLibInfo(); |
| frag_out_lib.CreateGraphicsPipeline(false); |
| |
| VkPipeline libraries[4] = { |
| vertex_input_lib, |
| pre_raster_lib, |
| frag_shader_lib, |
| frag_out_lib, |
| }; |
| VkPipelineLibraryCreateInfoKHR link_info = vku::InitStructHelper(); |
| link_info.libraryCount = size32(libraries); |
| link_info.pLibraries = libraries; |
| |
| VkGraphicsPipelineCreateInfo exe_pipe_ci = vku::InitStructHelper(&link_info); |
| exe_pipe_ci.layout = pipeline_layout; |
| exe_pipe_ci.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; |
| vkt::Pipeline exe_pipe(*m_device, exe_pipe_ci); |
| |
| m_command_buffer.Begin(); |
| |
| VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = vku::InitStructHelper(); |
| descriptor_buffer_binding_info.address = descriptor_buffer.Address(); |
| descriptor_buffer_binding_info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT; |
| vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1, &descriptor_buffer_binding_info); |
| |
| uint32_t buffer_index = 0; |
| VkDeviceSize buffer_offset = 0; |
| vk::CmdSetDescriptorBufferOffsetsEXT(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &buffer_index, |
| &buffer_offset); |
| |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, exe_pipe); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("c == 20"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DescriptorBufferShaderObject) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| AddRequiredFeature(vkt::Feature::descriptorBuffer); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_buffer_properties = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(descriptor_buffer_properties); |
| |
| vkt::Buffer buffer_data(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vkt::device_address); |
| uint32_t *data = (uint32_t *)buffer_data.Memory().Map(); |
| data[0] = 8; |
| data[1] = 12; |
| data[2] = 1; |
| |
| VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; |
| vkt::DescriptorSetLayout ds_layout(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); |
| |
| VkPipelineLayoutCreateInfo pipe_layout_ci = vku::InitStructHelper(); |
| pipe_layout_ci.setLayoutCount = 1; |
| pipe_layout_ci.pSetLayouts = &ds_layout.handle(); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipe_layout_ci); |
| |
| VkDeviceSize ds_layout_size = ds_layout.GetDescriptorBufferSize(); |
| ds_layout_size = Align(ds_layout_size, descriptor_buffer_properties.descriptorBufferOffsetAlignment); |
| vkt::Buffer descriptor_buffer(*m_device, ds_layout_size, VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT, |
| vkt::device_address); |
| |
| vkt::DescriptorGetInfo get_info(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, buffer_data, 16); |
| void *mapped_descriptor_data = descriptor_buffer.Memory().Map(); |
| vk::GetDescriptorEXT(device(), get_info, descriptor_buffer_properties.storageBufferDescriptorSize, mapped_descriptor_data); |
| |
| const char *cs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout (set = 0, binding = 0) buffer SSBO_0 { |
| uint a; |
| uint b; |
| uint c; |
| }; |
| |
| void main() { |
| c = a + b; |
| debugPrintfEXT("c == %u\n", c); |
| } |
| )glsl"; |
| |
| const vkt::Shader cs(*m_device, VK_SHADER_STAGE_COMPUTE_BIT, GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, cs_source), |
| &ds_layout.handle()); |
| |
| m_command_buffer.Begin(); |
| const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_COMPUTE_BIT}; |
| vk::CmdBindShadersEXT(m_command_buffer, 1, stages, &cs.handle()); |
| |
| VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = vku::InitStructHelper(); |
| descriptor_buffer_binding_info.address = descriptor_buffer.Address(); |
| descriptor_buffer_binding_info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT; |
| vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1, &descriptor_buffer_binding_info); |
| |
| uint32_t buffer_index = 0; |
| VkDeviceSize buffer_offset = 0; |
| vk::CmdSetDescriptorBufferOffsetsEXT(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &buffer_index, |
| &buffer_offset); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| |
| m_errorMonitor->SetDesiredInfo("c == 20"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DescriptorBufferPushConstantOnly) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::descriptorBuffer); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; |
| vkt::DescriptorSetLayout ds_layout(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); |
| |
| VkPushConstantRange pc_range = {VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t)}; |
| VkPipelineLayoutCreateInfo pipe_layout_ci = vku::InitStructHelper(); |
| pipe_layout_ci.pushConstantRangeCount = 1; |
| pipe_layout_ci.pPushConstantRanges = &pc_range; |
| pipe_layout_ci.setLayoutCount = 1; |
| pipe_layout_ci.pSetLayouts = &ds_layout.handle(); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipe_layout_ci); |
| |
| const char *cs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(push_constant) uniform PushConstants { |
| int x; |
| } pc; |
| void main() { |
| debugPrintfEXT("int == %u", pc.x); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2); |
| pipe.cp_ci_.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| uint32_t data = 4; |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdPushConstants(m_command_buffer, pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &data); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("int == 4"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DescriptorBufferMixClassic) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::descriptorBuffer); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_buffer_properties = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(descriptor_buffer_properties); |
| |
| const char *cs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout (set = 0, binding = 0) buffer SSBO_0 { |
| uint a; |
| uint b; |
| uint c; |
| }; |
| |
| void main() { |
| c = a + b; |
| debugPrintfEXT("c == %u\n", c); |
| } |
| )glsl"; |
| |
| const VkDeviceSize offset = 256; // minStorageBufferOffsetAlignment required to be at most 256 |
| vkt::Buffer buffer_data(*m_device, 1024, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vkt::device_address); |
| uint32_t *data = (uint32_t *)buffer_data.Memory().Map(); |
| data[0] = 8; |
| data[1] = 12; |
| data[2] = 1; |
| data[(offset / 4) + 0] = 3; |
| data[(offset / 4) + 1] = 7; |
| data[(offset / 4) + 2] = 1; |
| |
| VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; |
| vkt::DescriptorSetLayout ds_layout_db(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); |
| |
| VkPipelineLayoutCreateInfo pipe_layout_ci = vku::InitStructHelper(); |
| pipe_layout_ci.setLayoutCount = 1; |
| pipe_layout_ci.pSetLayouts = &ds_layout_db.handle(); |
| vkt::PipelineLayout pipeline_layout_db(*m_device, pipe_layout_ci); |
| |
| VkDeviceSize ds_layout_size = ds_layout_db.GetDescriptorBufferSize(); |
| ds_layout_size = Align(ds_layout_size, descriptor_buffer_properties.descriptorBufferOffsetAlignment); |
| vkt::Buffer descriptor_buffer(*m_device, ds_layout_size, VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT, |
| vkt::device_address); |
| vkt::DescriptorGetInfo get_info(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, buffer_data, 16); |
| void *mapped_descriptor_data = descriptor_buffer.Memory().Map(); |
| vk::GetDescriptorEXT(device(), get_info, descriptor_buffer_properties.storageBufferDescriptorSize, mapped_descriptor_data); |
| |
| CreateComputePipelineHelper pipe_db(*this); |
| pipe_db.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2); |
| pipe_db.cp_ci_.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; |
| pipe_db.cp_ci_.layout = pipeline_layout_db; |
| pipe_db.CreateComputePipeline(); |
| |
| // Classic |
| vkt::DescriptorSetLayout ds_layout_classic(*m_device, binding); |
| OneOffDescriptorSet ds_classic(m_device, { |
| {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, |
| }); |
| vkt::PipelineLayout pipeline_layout_classic(*m_device, {&ds_classic.layout_}); |
| ds_classic.WriteDescriptorBufferInfo(0, buffer_data, offset, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| ds_classic.UpdateDescriptorSets(); |
| |
| CreateComputePipelineHelper pipe_classic(*this); |
| pipe_classic.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2); |
| pipe_classic.cp_ci_.layout = pipeline_layout_classic; |
| pipe_classic.CreateComputePipeline(); |
| |
| VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = vku::InitStructHelper(); |
| descriptor_buffer_binding_info.address = descriptor_buffer.Address(); |
| descriptor_buffer_binding_info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT; |
| uint32_t buffer_index = 0; |
| VkDeviceSize buffer_offset = 0; |
| |
| m_command_buffer.Begin(); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_classic); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout_classic, 0, 1, &ds_classic.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_db); |
| vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1, &descriptor_buffer_binding_info); |
| vk::CmdSetDescriptorBufferOffsetsEXT(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout_db, 0, 1, &buffer_index, |
| &buffer_offset); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_classic); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout_classic, 0, 1, &ds_classic.set_, 0, |
| nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_db); |
| vk::CmdBindDescriptorBuffersEXT(m_command_buffer, 1, &descriptor_buffer_binding_info); |
| vk::CmdSetDescriptorBufferOffsetsEXT(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout_db, 0, 1, &buffer_index, |
| &buffer_offset); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("c == 20", 2); |
| m_errorMonitor->SetDesiredInfo("c == 10", 2); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DescriptorBufferMultipleCommandBuffers) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::descriptorBuffer); |
| AddRequiredFeature(vkt::Feature::bufferDeviceAddress); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_buffer_properties = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(descriptor_buffer_properties); |
| |
| vkt::Buffer buffer1_data(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vkt::device_address); |
| vkt::Buffer buffer2_data(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vkt::device_address); |
| uint32_t *data = (uint32_t *)buffer1_data.Memory().Map(); |
| data[0] = 8; |
| data[1] = 12; |
| data[2] = 1; |
| data = (uint32_t *)buffer2_data.Memory().Map(); |
| data[0] = 7; |
| data[1] = 3; |
| data[2] = 1; |
| |
| VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; |
| vkt::DescriptorSetLayout ds_layout(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); |
| |
| VkPipelineLayoutCreateInfo pipe_layout_ci = vku::InitStructHelper(); |
| pipe_layout_ci.setLayoutCount = 1; |
| pipe_layout_ci.pSetLayouts = &ds_layout.handle(); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipe_layout_ci); |
| |
| VkDeviceSize ds_layout_size = ds_layout.GetDescriptorBufferSize(); |
| ds_layout_size = Align(ds_layout_size, descriptor_buffer_properties.descriptorBufferOffsetAlignment); |
| vkt::Buffer descriptor_buffer(*m_device, ds_layout_size * 2, VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT, |
| vkt::device_address); |
| |
| uint8_t *mapped_descriptor_data = (uint8_t *)descriptor_buffer.Memory().Map(); |
| { |
| vkt::DescriptorGetInfo get_info(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, buffer1_data, 16); |
| vk::GetDescriptorEXT(device(), get_info, descriptor_buffer_properties.storageBufferDescriptorSize, mapped_descriptor_data); |
| } |
| { |
| vkt::DescriptorGetInfo get_info(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, buffer2_data, 16); |
| vk::GetDescriptorEXT(device(), get_info, descriptor_buffer_properties.storageBufferDescriptorSize, |
| mapped_descriptor_data + ds_layout_size); |
| } |
| |
| const char *cs_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout (set = 0, binding = 0) buffer SSBO_0 { |
| uint a; |
| uint b; |
| uint c; |
| }; |
| |
| void main() { |
| c = a + b; |
| debugPrintfEXT("c == %u\n", c); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_2); |
| pipe.cp_ci_.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = vku::InitStructHelper(); |
| descriptor_buffer_binding_info.address = descriptor_buffer.Address(); |
| descriptor_buffer_binding_info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT; |
| uint32_t buffer_index = 0; |
| VkDeviceSize buffer_offset = 0; |
| |
| vkt::CommandBuffer cb0(*m_device, m_command_pool); |
| vkt::CommandBuffer cb1(*m_device, m_command_pool); |
| |
| cb0.Begin(); |
| vk::CmdBindPipeline(cb0, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorBuffersEXT(cb0, 1, &descriptor_buffer_binding_info); |
| vk::CmdSetDescriptorBufferOffsetsEXT(cb0, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &buffer_index, &buffer_offset); |
| vk::CmdDispatch(cb0, 1, 1, 1); |
| cb0.End(); |
| cb1.Begin(); |
| vk::CmdBindPipeline(cb1, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorBuffersEXT(cb1, 1, &descriptor_buffer_binding_info); |
| buffer_offset = ds_layout_size; |
| vk::CmdSetDescriptorBufferOffsetsEXT(cb1, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &buffer_index, &buffer_offset); |
| vk::CmdDispatch(cb1, 1, 1, 1); |
| cb1.End(); |
| |
| m_errorMonitor->SetDesiredInfo("c == 20"); |
| m_errorMonitor->SetDesiredInfo("c == 10"); |
| m_default_queue->Submit({cb0, cb1}); |
| m_default_queue->Wait(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DrawMeshTasksIndirectCountEXT) { |
| TEST_DESCRIPTION("Test debug printf in mesh shaders."); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_MESH_SHADER_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::meshShader); |
| AddRequiredFeature(vkt::Feature::shaderDrawParameters); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); |
| InitRenderTarget(); |
| |
| const char *mesh_source = R"glsl( |
| #version 460 |
| #extension GL_EXT_mesh_shader : enable |
| #extension GL_EXT_debug_printf : enable |
| layout(triangles, max_vertices = 3, max_primitives = 1) out; |
| |
| void main() { |
| debugPrintfEXT("gl_DrawID = %d\n", gl_DrawID); |
| SetMeshOutputsEXT(3, 1); |
| gl_MeshVerticesEXT[0].gl_Position = vec4(0); |
| gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2); |
| } |
| )glsl"; |
| |
| const auto mesh_code = GLSLToSPV(VK_SHADER_STAGE_MESH_BIT_EXT, mesh_source, SPV_ENV_VULKAN_1_2); |
| |
| VkShaderCreateInfoEXT mesh_ci = vku::InitStructHelper(); |
| mesh_ci.flags = VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT; |
| mesh_ci.stage = VK_SHADER_STAGE_MESH_BIT_EXT; |
| mesh_ci.nextStage = VK_SHADER_STAGE_FRAGMENT_BIT; |
| mesh_ci.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT; |
| mesh_ci.codeSize = mesh_code.size() * sizeof(mesh_code[0]); |
| mesh_ci.pCode = mesh_code.data(); |
| mesh_ci.pName = "main"; |
| const vkt::Shader mesh(*m_device, mesh_ci); |
| const vkt::Shader frag(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT, |
| GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl, SPV_ENV_VULKAN_1_2)); |
| |
| vkt::Buffer count_buffer(*m_device, 64, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, kHostVisibleMemProps); |
| uint32_t *count_ptr = static_cast<uint32_t *>(count_buffer.Memory().Map()); |
| *count_ptr = 1; |
| |
| vkt::Buffer draw_buffer(*m_device, sizeof(VkDrawMeshTasksIndirectCommandEXT), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, |
| kHostVisibleMemProps); |
| auto *draw_ptr = static_cast<VkDrawMeshTasksIndirectCommandEXT *>(draw_buffer.Memory().Map()); |
| draw_ptr->groupCountX = 1; |
| draw_ptr->groupCountY = 1; |
| draw_ptr->groupCountZ = 1; |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea()); |
| SetDefaultDynamicStatesExclude(); |
| const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_MESH_BIT_EXT, VK_SHADER_STAGE_FRAGMENT_BIT}; |
| const VkShaderEXT shaders[] = {VK_NULL_HANDLE, mesh, frag}; |
| vk::CmdBindShadersEXT(m_command_buffer, 3u, stages, shaders); |
| vk::CmdDrawMeshTasksIndirectCountEXT(m_command_buffer, draw_buffer, 0u, count_buffer, 0u, 1u, |
| sizeof(VkDrawMeshTasksIndirectCommandEXT)); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("gl_DrawID = 0"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DisableShaderValidation) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::fragmentStoresAndAtomics); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| VkLayerSettingEXT layer_settings[2] = {{OBJECT_LAYER_NAME, "check_shaders", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkFalse}, |
| {OBJECT_LAYER_NAME, "printf_enable", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}}; |
| VkLayerSettingsCreateInfoEXT layer_setting_ci = {VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr, 2, layer_settings}; |
| RETURN_IF_SKIP(InitFramework(&layer_setting_ci)); |
| if (!CanEnableGpuAV(*this)) { |
| GTEST_SKIP() << "Requirements for GPU-AV are not met"; |
| } |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| const char *frag_shader = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) buffer SSBO { |
| uint x; // something to trigger pipeline validation |
| }; |
| void main() { |
| uint myValue = 42; |
| x = myValue; |
| // only will print once |
| if (gl_FragCoord.x > 10 && gl_FragCoord.x < 11 && gl_FragCoord.y > 10 && gl_FragCoord.y < 12) { |
| debugPrintfEXT("myValue == %u", myValue); |
| } |
| } |
| )glsl"; |
| |
| OneOffDescriptorSet ds(m_device, { |
| {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, |
| }); |
| vkt::PipelineLayout pipeline_layout(*m_device, {&ds.layout_}); |
| vkt::Buffer buffer(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); |
| ds.WriteDescriptorBufferInfo(0, buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| ds.UpdateDescriptorSets(); |
| |
| VkShaderObj vs(*m_device, kVertexDrawPassthroughGlsl, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, frag_shader, VK_SHADER_STAGE_FRAGMENT_BIT); |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.gp_ci_.layout = pipeline_layout; |
| pipe.CreateGraphicsPipeline(); |
| |
| vkt::SimpleGPL pipe_gpl(*this, pipeline_layout, kVertexDrawPassthroughGlsl, frag_shader); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &ds.set_, 0, nullptr); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_gpl); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("myValue == 42"); // normal |
| m_errorMonitor->SetDesiredInfo("myValue == 42"); // gpl |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, DisableShaderValidationShaderObject) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::shaderObject); |
| VkLayerSettingEXT layer_settings[2] = {{OBJECT_LAYER_NAME, "check_shaders", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkFalse}, |
| {OBJECT_LAYER_NAME, "printf_enable", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}}; |
| VkLayerSettingsCreateInfoEXT layer_setting_ci = {VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr, 2, layer_settings}; |
| RETURN_IF_SKIP(InitFramework(&layer_setting_ci)); |
| if (!CanEnableGpuAV(*this)) { |
| GTEST_SKIP() << "Requirements for GPU-AV are not met"; |
| } |
| RETURN_IF_SKIP(InitState()); |
| |
| OneOffDescriptorSet ds(m_device, { |
| {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, |
| }); |
| vkt::PipelineLayout pipeline_layout(*m_device, {&ds.layout_}); |
| vkt::Buffer buffer(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); |
| ds.WriteDescriptorBufferInfo(0, buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| ds.UpdateDescriptorSets(); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| layout(set = 0, binding = 0) buffer SSBO { |
| uint x; // something to trigger pipeline validation |
| }; |
| void main() { |
| uint myValue = 42; |
| x = myValue; |
| debugPrintfEXT("myValue == %u", myValue); |
| } |
| )glsl"; |
| |
| const vkt::Shader cs(*m_device, VK_SHADER_STAGE_COMPUTE_BIT, GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, shader_source), |
| &ds.layout_.handle()); |
| |
| m_command_buffer.Begin(); |
| const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_COMPUTE_BIT}; |
| vk::CmdBindShadersEXT(m_command_buffer, 1, stages, &cs.handle()); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &ds.set_, 0, nullptr); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("myValue == 42"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeDebugPrintf, MidCommandBuffer) { |
| RETURN_IF_SKIP(InitDebugPrintfFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| // Make sure doing everything inside the command buffer is still ok |
| m_command_buffer.Begin(); |
| |
| const char *shader_source = R"glsl( |
| #version 450 |
| #extension GL_EXT_debug_printf : enable |
| void main() { |
| float myfloat = 3.1415f; |
| debugPrintfEXT("float == %f", myfloat); |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_command_buffer.End(); |
| |
| m_errorMonitor->SetDesiredInfo("float == 3.141500"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |