|
1 | 1 | /* |
2 | | - * Copyright (c) 2020-2025 The Khronos Group Inc. |
3 | | - * Copyright (c) 2020-2025 Valve Corporation |
4 | | - * Copyright (c) 2020-2025 LunarG, Inc. |
5 | | - * Copyright (c) 2020-2025 Google, Inc. |
| 2 | + * Copyright (c) 2020-2026 The Khronos Group Inc. |
| 3 | + * Copyright (c) 2020-2026 Valve Corporation |
| 4 | + * Copyright (c) 2020-2026 LunarG, Inc. |
| 5 | + * Copyright (c) 2020-2026 Google, Inc. |
6 | 6 | * |
7 | 7 | * Licensed under the Apache License, Version 2.0 (the "License"); |
8 | 8 | * you may not use this file except in compliance with the License. |
|
15 | 15 | #include "../framework/layer_validation_tests.h" |
16 | 16 | #include "../framework/pipeline_helper.h" |
17 | 17 | #include "../framework/buffer_helper.h" |
| 18 | +#include "../framework/shader_helper.h" |
18 | 19 |
|
19 | 20 | class PositiveGpuAVVertexAttributeFetch : public GpuAVTest {}; |
20 | 21 |
|
@@ -70,3 +71,152 @@ TEST_F(PositiveGpuAVVertexAttributeFetch, IndirectDrawZeroStride) { |
70 | 71 | m_default_queue->SubmitAndWait(m_command_buffer); |
71 | 72 | m_errorMonitor->VerifyFound(); |
72 | 73 | } |
| 74 | + |
| 75 | +TEST_F(PositiveGpuAVVertexAttributeFetch, NoVertexInput) { |
| 76 | + TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/11475"); |
| 77 | + RETURN_IF_SKIP(InitGpuAvFramework()); |
| 78 | + RETURN_IF_SKIP(InitState()); |
| 79 | + InitRenderTarget(); |
| 80 | + |
| 81 | + const char* vs_source = R"glsl( |
| 82 | + #version 450 |
| 83 | + layout (location = 0) out vec3 outEyespacePosition; |
| 84 | + layout (location = 1) out vec2 outTexcoords; |
| 85 | +
|
| 86 | + void main() { |
| 87 | + outEyespacePosition = vec3(0); |
| 88 | + outTexcoords = vec2(0); |
| 89 | + } |
| 90 | + )glsl"; |
| 91 | + VkShaderObj vs(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT); |
| 92 | + |
| 93 | + const char* fs_source = R"glsl( |
| 94 | + #version 450 |
| 95 | + layout (location = 0) in vec3 inEyeSpacePosition; |
| 96 | + layout (location = 0) out vec4 outColour; |
| 97 | +
|
| 98 | + void main() { |
| 99 | + outColour = vec4(0); |
| 100 | + } |
| 101 | + )glsl"; |
| 102 | + VkShaderObj fs(*m_device, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| 103 | + |
| 104 | + CreatePipelineHelper pipe(*this); |
| 105 | + VkVertexInputBindingDescription input_binding = {0, 0, VK_VERTEX_INPUT_RATE_VERTEX}; |
| 106 | + VkVertexInputAttributeDescription input_attrib = {1, 0, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 0}; |
| 107 | + pipe.vi_ci_.pVertexBindingDescriptions = &input_binding; |
| 108 | + pipe.vi_ci_.vertexBindingDescriptionCount = 1; |
| 109 | + pipe.vi_ci_.pVertexAttributeDescriptions = &input_attrib; |
| 110 | + pipe.vi_ci_.vertexAttributeDescriptionCount = 1; |
| 111 | + pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| 112 | + pipe.CreateGraphicsPipeline(); |
| 113 | + |
| 114 | + VkCommandBufferBeginInfo begin_info = vku::InitStructHelper(); |
| 115 | + m_command_buffer.Begin(&begin_info); |
| 116 | + m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| 117 | + vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| 118 | + |
| 119 | + vkt::Buffer index_buffer = vkt::IndexBuffer<uint32_t>(*m_device, {0, 666, 42}); |
| 120 | + vkt::Buffer vertex_buffer = vkt::VertexBuffer<float>(*m_device, {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}); |
| 121 | + VkDeviceSize vertex_buffer_offset = 0; |
| 122 | + vk::CmdBindIndexBuffer(m_command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT32); |
| 123 | + vk::CmdBindVertexBuffers(m_command_buffer, 0, 1, &vertex_buffer.handle(), &vertex_buffer_offset); |
| 124 | + |
| 125 | + vk::CmdDrawIndexed(m_command_buffer, 3, 1, 0, 0, 0); |
| 126 | + |
| 127 | + m_command_buffer.EndRenderPass(); |
| 128 | + m_command_buffer.End(); |
| 129 | + |
| 130 | + m_default_queue->SubmitAndWait(m_command_buffer); |
| 131 | + m_errorMonitor->VerifyFound(); |
| 132 | +} |
| 133 | + |
| 134 | +TEST_F(PositiveGpuAVVertexAttributeFetch, NoVertexInputWithBuiltin) { |
| 135 | + TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/11475"); |
| 136 | + SetTargetApiVersion(VK_API_VERSION_1_2); |
| 137 | + AddRequiredFeature(vkt::Feature::shaderDrawParameters); |
| 138 | + RETURN_IF_SKIP(InitGpuAvFramework()); |
| 139 | + RETURN_IF_SKIP(InitState()); |
| 140 | + InitRenderTarget(); |
| 141 | + |
| 142 | + // Declares the variable for builtin [VertexIndex, InstanceIndex, BaseVertex] but never accesses them |
| 143 | + const char* vs_source = R"( |
| 144 | + OpCapability DrawParameters |
| 145 | + OpCapability Shader |
| 146 | + OpMemoryModel Logical GLSL450 |
| 147 | + OpEntryPoint Vertex %main "main" %entryPointParam_main_outEyespacePosition %entryPointParam_main_outTexcoords |
| 148 | + OpDecorate %entryPointParam_main_outEyespacePosition Location 0 |
| 149 | + OpDecorate %entryPointParam_main_outTexcoords Location 1 |
| 150 | + OpDecorate %gl_Position BuiltIn Position |
| 151 | + OpDecorate %gl_VertexIndex BuiltIn VertexIndex |
| 152 | + OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex |
| 153 | + OpDecorate %15 BuiltIn BaseVertex |
| 154 | + %float = OpTypeFloat 32 |
| 155 | + %v3float = OpTypeVector %float 3 |
| 156 | +%_ptr_Output_v3float = OpTypePointer Output %v3float |
| 157 | + %v2float = OpTypeVector %float 2 |
| 158 | +%_ptr_Output_v2float = OpTypePointer Output %v2float |
| 159 | + %v4float = OpTypeVector %float 4 |
| 160 | +%_ptr_Output_v4float = OpTypePointer Output %v4float |
| 161 | + %int = OpTypeInt 32 1 |
| 162 | +%_ptr_Input_int = OpTypePointer Input %int |
| 163 | + %void = OpTypeVoid |
| 164 | + %18 = OpTypeFunction %void |
| 165 | + %float_0 = OpConstant %float 0 |
| 166 | + %20 = OpConstantComposite %v3float %float_0 %float_0 %float_0 |
| 167 | + %23 = OpConstantComposite %v2float %float_0 %float_0 |
| 168 | +%entryPointParam_main_outEyespacePosition = OpVariable %_ptr_Output_v3float Output |
| 169 | +%entryPointParam_main_outTexcoords = OpVariable %_ptr_Output_v2float Output |
| 170 | +%gl_Position = OpVariable %_ptr_Output_v4float Output |
| 171 | +%gl_VertexIndex = OpVariable %_ptr_Input_int Input |
| 172 | +%gl_InstanceIndex = OpVariable %_ptr_Input_int Input |
| 173 | + %15 = OpVariable %_ptr_Input_int Input |
| 174 | + %main = OpFunction %void None %18 |
| 175 | + %19 = OpLabel |
| 176 | + OpStore %entryPointParam_main_outEyespacePosition %20 |
| 177 | + OpStore %entryPointParam_main_outTexcoords %23 |
| 178 | + OpReturn |
| 179 | + OpFunctionEnd |
| 180 | + )"; |
| 181 | + VkShaderObj vs(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_2, SPV_SOURCE_ASM); |
| 182 | + |
| 183 | + const char* fs_source = R"glsl( |
| 184 | + #version 450 |
| 185 | + layout (location = 0) in vec3 inEyeSpacePosition; |
| 186 | + layout (location = 0) out vec4 outColour; |
| 187 | +
|
| 188 | + void main() { |
| 189 | + outColour = vec4(0); |
| 190 | + } |
| 191 | + )glsl"; |
| 192 | + VkShaderObj fs(*m_device, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_2); |
| 193 | + |
| 194 | + CreatePipelineHelper pipe(*this); |
| 195 | + VkVertexInputBindingDescription input_binding = {0, 0, VK_VERTEX_INPUT_RATE_VERTEX}; |
| 196 | + VkVertexInputAttributeDescription input_attrib = {1, 0, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 0}; |
| 197 | + pipe.vi_ci_.pVertexBindingDescriptions = &input_binding; |
| 198 | + pipe.vi_ci_.vertexBindingDescriptionCount = 1; |
| 199 | + pipe.vi_ci_.pVertexAttributeDescriptions = &input_attrib; |
| 200 | + pipe.vi_ci_.vertexAttributeDescriptionCount = 1; |
| 201 | + pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| 202 | + pipe.CreateGraphicsPipeline(); |
| 203 | + |
| 204 | + VkCommandBufferBeginInfo begin_info = vku::InitStructHelper(); |
| 205 | + m_command_buffer.Begin(&begin_info); |
| 206 | + m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| 207 | + vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| 208 | + |
| 209 | + vkt::Buffer index_buffer = vkt::IndexBuffer<uint32_t>(*m_device, {0, 666, 42}); |
| 210 | + vkt::Buffer vertex_buffer = vkt::VertexBuffer<float>(*m_device, {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}); |
| 211 | + VkDeviceSize vertex_buffer_offset = 0; |
| 212 | + vk::CmdBindIndexBuffer(m_command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT32); |
| 213 | + vk::CmdBindVertexBuffers(m_command_buffer, 0, 1, &vertex_buffer.handle(), &vertex_buffer_offset); |
| 214 | + |
| 215 | + vk::CmdDrawIndexed(m_command_buffer, 3, 1, 0, 0, 0); |
| 216 | + |
| 217 | + m_command_buffer.EndRenderPass(); |
| 218 | + m_command_buffer.End(); |
| 219 | + |
| 220 | + m_default_queue->SubmitAndWait(m_command_buffer); |
| 221 | + m_errorMonitor->VerifyFound(); |
| 222 | +} |
0 commit comments