blob: 36f2ad7ecdb5a778d028773b2e489dc15dfaa291 [file]
/* Copyright (c) 2026 The Khronos Group Inc.
* Copyright (c) 2026 Valve Corporation
* Copyright (c) 2026 LunarG, 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "layer_validation_tests.h"
#include "pipeline_helper.h"
#include "descriptor_helper.h"
#include "shader_object_helper.h"
class PositiveGpuAVScoped : public GpuAVTest {};
TEST_F(PositiveGpuAVScoped, SelectInstrumentedShaders) {
TEST_DESCRIPTION("Use a bad vertex shader, but don't select it for validation and make sure we don't get a buffer oob warning");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredFeature(vkt::Feature::robustBufferAccess);
AddRequiredFeature(vkt::Feature::vertexPipelineStoresAndAtomics);
AddRequiredFeature(vkt::Feature::fragmentStoresAndAtomics);
std::vector<VkLayerSettingEXT> layer_settings = {
{OBJECT_LAYER_NAME, "gpuav_select_instrumented_shaders", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}};
RETURN_IF_SKIP(InitGpuAvFramework(layer_settings));
// Robust buffer access will be on by default
VkCommandPoolCreateFlags pool_flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
InitState(nullptr, nullptr, pool_flags);
InitRenderTarget();
vkt::Buffer write_buffer(*m_device, 4, 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_});
descriptor_set.WriteDescriptorBufferInfo(0, write_buffer, 0, 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
descriptor_set.UpdateDescriptorSets();
const char vertshader[] = R"glsl(
#version 450
layout(set = 0, binding = 0) buffer StorageBuffer { uint data[]; } Data;
void main() {
Data.data[4] = 0xdeadca71;
}
)glsl";
// Don't instrument buggy vertex shader
VkShaderObj vs(*m_device, vertshader, VK_SHADER_STAGE_VERTEX_BIT);
// Instrument non-buggy fragment shader
VkValidationFeatureEnableEXT enabled[] = {VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT};
VkValidationFeaturesEXT features = vku::InitStructHelper();
features.enabledValidationFeatureCount = 1;
features.pEnabledValidationFeatures = enabled;
VkShaderObj fs(*m_device, vertshader, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, nullptr, "main",
&features);
CreatePipelineHelper pipe(*this);
pipe.shader_stages_.clear();
pipe.shader_stages_.push_back(vs.GetStageCreateInfo());
pipe.shader_stages_.push_back(fs.GetStageCreateInfo());
pipe.gp_ci_.layout = pipeline_layout;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
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();
// Should not get a warning since buggy vertex shader wasn't instrumented
m_errorMonitor->ExpectSuccess(kWarningBit | kErrorBit);
m_default_queue->SubmitAndWait(m_command_buffer);
}
TEST_F(PositiveGpuAVScoped, DispatchShaderObjectAndPipeline) {
TEST_DESCRIPTION("GPU validation: Validate selection of which shaders get instrumented for GPU-AV");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::dynamicRendering);
AddRequiredFeature(vkt::Feature::shaderObject);
AddRequiredFeature(vkt::Feature::robustBufferAccess);
std::vector<VkLayerSettingEXT> layer_settings = {
{OBJECT_LAYER_NAME, "gpuav_select_instrumented_shaders", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}};
RETURN_IF_SKIP(InitGpuAvFramework(layer_settings));
RETURN_IF_SKIP(InitState());
const char comp_src[] = R"glsl(
#version 450
layout(local_size_x=16, local_size_x=1, local_size_x=1) in;
void main() {
}
)glsl";
const auto comp_spv = GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, comp_src);
VkShaderCreateInfoEXT comp_create_info = ShaderCreateInfo(comp_spv, VK_SHADER_STAGE_COMPUTE_BIT);
VkValidationFeatureEnableEXT enabled[] = {VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT};
VkValidationFeaturesEXT features = vku::InitStructHelper();
features.enabledValidationFeatureCount = 1;
features.pEnabledValidationFeatures = enabled;
comp_create_info.pNext = &features;
const vkt::Shader compShader(*m_device, comp_create_info);
CreateComputePipelineHelper compute_pipe(*this);
compute_pipe.cs_ = VkShaderObj(*m_device, comp_src, VK_SHADER_STAGE_COMPUTE_BIT);
compute_pipe.CreateComputePipeline();
vkt::Buffer indirect_dispatch_parameters_buffer(*m_device, sizeof(VkDispatchIndirectCommand),
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, kHostVisibleMemProps);
auto& indirect_dispatch_parameters =
*static_cast<VkDispatchIndirectCommand*>(indirect_dispatch_parameters_buffer.Memory().Map());
indirect_dispatch_parameters.x = 1u;
indirect_dispatch_parameters.y = 1u;
indirect_dispatch_parameters.z = 1u;
m_command_buffer.Begin();
SetDefaultDynamicStatesExclude();
m_command_buffer.BindCompShader(compShader);
vk::CmdDispatchIndirect(m_command_buffer, indirect_dispatch_parameters_buffer, 0u);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipe);
vk::CmdDispatchIndirect(m_command_buffer, indirect_dispatch_parameters_buffer, 0u);
m_command_buffer.End();
}