blob: 225630fcbc048447a43ca3d71163f8dc6b7fdb70 [file] [log] [blame]
/*
* Copyright (c) 2015-2024 The Khronos Group Inc.
* Copyright (c) 2015-2024 Valve Corporation
* Copyright (c) 2015-2024 LunarG, Inc.
* Copyright (c) 2015-2024 Google, Inc.
* Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
#include "../framework/shader_object_helper.h"
class NegativeShaderPushConstants : public VkLayerTest {};
TEST_F(NegativeShaderPushConstants, NotDeclared) {
TEST_DESCRIPTION(
"Create a graphics pipeline in which a push constant range containing a push constant block member is not declared in the "
"layout.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
char const *vsSource = R"glsl(
#version 450
layout(push_constant, std430) uniform foo { float x; } consts;
void main(){
gl_Position = vec4(consts.x);
}
)glsl";
VkShaderObj vs(this, vsSource, VK_SHADER_STAGE_VERTEX_BIT);
// Set up a push constant range
VkPushConstantRange push_constant_range = {};
// Set to the wrong stage to challenge core_validation
push_constant_range.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
push_constant_range.size = 4;
const vkt::PipelineLayout pipeline_layout(*m_device, {}, {push_constant_range});
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {}, {push_constant_range});
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-07987");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeShaderPushConstants, PipelineRange) {
TEST_DESCRIPTION("Invalid use of VkPushConstantRange structs.");
RETURN_IF_SKIP(Init());
// will be at least 256 as required from the spec
const uint32_t maxPushConstantsSize = m_device->Physical().limits_.maxPushConstantsSize;
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
VkPushConstantRange push_constant_range = {0, 0, 4};
VkPipelineLayoutCreateInfo pipeline_layout_info{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0, 0, nullptr, 1, &push_constant_range};
// stageFlags of 0
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-stageFlags-requiredbitmask");
vk::CreatePipelineLayout(device(), &pipeline_layout_info, NULL, &pipeline_layout);
m_errorMonitor->VerifyFound();
// offset over limit
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, maxPushConstantsSize, 8};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-offset-00294");
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00298");
vk::CreatePipelineLayout(device(), &pipeline_layout_info, NULL, &pipeline_layout);
m_errorMonitor->VerifyFound();
// offset not a multiple of 4
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 1, 8};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-offset-00295");
vk::CreatePipelineLayout(device(), &pipeline_layout_info, NULL, &pipeline_layout);
m_errorMonitor->VerifyFound();
// size of 0
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, 0};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00296");
vk::CreatePipelineLayout(device(), &pipeline_layout_info, NULL, &pipeline_layout);
m_errorMonitor->VerifyFound();
// size not a multiple of 4
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, 7};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00297");
vk::CreatePipelineLayout(device(), &pipeline_layout_info, NULL, &pipeline_layout);
m_errorMonitor->VerifyFound();
// size over limit
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, maxPushConstantsSize + 4};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00298");
vk::CreatePipelineLayout(device(), &pipeline_layout_info, NULL, &pipeline_layout);
m_errorMonitor->VerifyFound();
// size over limit of non-zero offset
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 4, maxPushConstantsSize};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00298");
vk::CreatePipelineLayout(device(), &pipeline_layout_info, NULL, &pipeline_layout);
m_errorMonitor->VerifyFound();
// Sanity check its a valid range before making duplicate
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, maxPushConstantsSize};
ASSERT_EQ(VK_SUCCESS, vk::CreatePipelineLayout(device(), &pipeline_layout_info, NULL, &pipeline_layout));
vk::DestroyPipelineLayout(device(), pipeline_layout, nullptr);
// Duplicate ranges
VkPushConstantRange push_constant_range_duplicate[2] = {push_constant_range, push_constant_range};
pipeline_layout_info.pushConstantRangeCount = 2;
pipeline_layout_info.pPushConstantRanges = push_constant_range_duplicate;
m_errorMonitor->SetDesiredError("VUID-VkPipelineLayoutCreateInfo-pPushConstantRanges-00292");
vk::CreatePipelineLayout(device(), &pipeline_layout_info, nullptr, &pipeline_layout);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeShaderPushConstants, PipelineRangeShaderObject) {
TEST_DESCRIPTION("Invalid use of VkPushConstantRange structs.");
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
RETURN_IF_SKIP(Init());
vkt::Shader shader;
VkPushConstantRange push_constant_range = {0, 0, 4};
const auto spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
VkShaderCreateInfoEXT ci_info = ShaderCreateInfo(spv, VK_SHADER_STAGE_VERTEX_BIT, 0, nullptr, 1, &push_constant_range);
// stageFlags of 0
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-stageFlags-requiredbitmask");
shader.init(*m_device, ci_info);
m_errorMonitor->VerifyFound();
// will be at least 256 as required from the spec
const uint32_t maxPushConstantsSize = m_device->Physical().limits_.maxPushConstantsSize;
// offset over limit
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, maxPushConstantsSize, 8};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-offset-00294");
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00298");
shader.init(*m_device, ci_info);
m_errorMonitor->VerifyFound();
// offset not a multiple of 4
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 1, 8};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-offset-00295");
shader.init(*m_device, ci_info);
m_errorMonitor->VerifyFound();
// size of 0
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, 0};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00296");
shader.init(*m_device, ci_info);
m_errorMonitor->VerifyFound();
// size not a multiple of 4
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, 7};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00297");
shader.init(*m_device, ci_info);
m_errorMonitor->VerifyFound();
// size over limit
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, maxPushConstantsSize + 4};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00298");
shader.init(*m_device, ci_info);
m_errorMonitor->VerifyFound();
// size over limit of non-zero offset
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 4, maxPushConstantsSize};
m_errorMonitor->SetDesiredError("VUID-VkPushConstantRange-size-00298");
shader.init(*m_device, ci_info);
m_errorMonitor->VerifyFound();
push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, maxPushConstantsSize};
// Duplicate ranges
VkPushConstantRange push_constant_range_duplicate[2] = {push_constant_range, push_constant_range};
ci_info.pushConstantRangeCount = 2;
ci_info.pPushConstantRanges = push_constant_range_duplicate;
m_errorMonitor->SetDesiredError("VUID-VkShaderCreateInfoEXT-pPushConstantRanges-10063");
shader.init(*m_device, ci_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeShaderPushConstants, NotInLayout) {
TEST_DESCRIPTION(
"Test that an error is produced for a shader consuming push constants which are not provided in the pipeline layout");
RETURN_IF_SKIP(Init());
InitRenderTarget();
char const *vsSource = R"glsl(
#version 450
layout(push_constant, std430) uniform foo { float x; } consts;
void main(){
gl_Position = vec4(consts.x);
}
)glsl";
VkShaderObj vs(this, vsSource, VK_SHADER_STAGE_VERTEX_BIT);
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {});
/* should have generated an error -- no push constant ranges provided! */
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-07987");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeShaderPushConstants, Range) {
TEST_DESCRIPTION("Invalid use of VkPushConstantRange values in vkCmdPushConstants.");
RETURN_IF_SKIP(InitFramework());
PFN_vkSetPhysicalDeviceLimitsEXT fpvkSetPhysicalDeviceLimitsEXT = nullptr;
PFN_vkGetOriginalPhysicalDeviceLimitsEXT fpvkGetOriginalPhysicalDeviceLimitsEXT = nullptr;
if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceLimitsEXT, fpvkGetOriginalPhysicalDeviceLimitsEXT)) {
GTEST_SKIP() << "Failed to load device profile layer.";
}
// Set limit to be same max as the shader usages
const uint32_t maxPushConstantsSize = 16;
VkPhysicalDeviceProperties props;
fpvkGetOriginalPhysicalDeviceLimitsEXT(Gpu(), &props.limits);
props.limits.maxPushConstantsSize = maxPushConstantsSize;
fpvkSetPhysicalDeviceLimitsEXT(Gpu(), &props.limits);
RETURN_IF_SKIP(InitState());
InitRenderTarget();
char const *const vsSource = R"glsl(
#version 450
layout(push_constant, std430) uniform foo { float x[4]; } constants;
void main(){
gl_Position = vec4(constants.x[0]);
}
)glsl";
VkShaderObj const vs(this, vsSource, VK_SHADER_STAGE_VERTEX_BIT);
VkShaderObj const fs(this, kFragmentMinimalGlsl, VK_SHADER_STAGE_FRAGMENT_BIT);
// Set up a push constant range
VkPushConstantRange push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, maxPushConstantsSize};
const vkt::PipelineLayout pipeline_layout(*m_device, {}, {push_constant_range});
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {}, {push_constant_range});
pipe.CreateGraphicsPipeline();
const float data[16] = {}; // dummy data to match shader size
m_command_buffer.Begin();
// size of 0
m_errorMonitor->SetDesiredError("VUID-vkCmdPushConstants-size-arraylength");
vk::CmdPushConstants(m_command_buffer.handle(), pipe.pipeline_layout_.handle(), VK_SHADER_STAGE_VERTEX_BIT, 0, 0, data);
m_errorMonitor->VerifyFound();
// offset not a multiple of 4
m_errorMonitor->SetDesiredError("VUID-vkCmdPushConstants-offset-00368");
vk::CmdPushConstants(m_command_buffer.handle(), pipe.pipeline_layout_.handle(), VK_SHADER_STAGE_VERTEX_BIT, 1, 4, data);
m_errorMonitor->VerifyFound();
// size not a multiple of 4
m_errorMonitor->SetDesiredError("VUID-vkCmdPushConstants-size-00369");
vk::CmdPushConstants(m_command_buffer.handle(), pipe.pipeline_layout_.handle(), VK_SHADER_STAGE_VERTEX_BIT, 0, 5, data);
m_errorMonitor->VerifyFound();
// offset at limit
m_errorMonitor->SetDesiredError("VUID-vkCmdPushConstants-offset-00370");
m_errorMonitor->SetDesiredError("VUID-vkCmdPushConstants-size-00371");
vk::CmdPushConstants(m_command_buffer.handle(), pipe.pipeline_layout_.handle(), VK_SHADER_STAGE_VERTEX_BIT,
maxPushConstantsSize, 4, data);
m_errorMonitor->VerifyFound();
// size at limit
m_errorMonitor->SetDesiredError("VUID-vkCmdPushConstants-size-00371");
vk::CmdPushConstants(m_command_buffer.handle(), pipe.pipeline_layout_.handle(), VK_SHADER_STAGE_VERTEX_BIT, 0,
maxPushConstantsSize + 4, data);
m_errorMonitor->VerifyFound();
// Size at limit, should be valid
vk::CmdPushConstants(m_command_buffer.handle(), pipe.pipeline_layout_.handle(), VK_SHADER_STAGE_VERTEX_BIT, 0,
maxPushConstantsSize, data);
m_command_buffer.End();
}
TEST_F(NegativeShaderPushConstants, DrawWithoutUpdate) {
TEST_DESCRIPTION("Not every bytes in used push constant ranges has been set before Draw ");
RETURN_IF_SKIP(Init());
InitRenderTarget();
// push constant range: 0-99
char const *const vsSource = R"glsl(
#version 450
layout(push_constant, std430) uniform foo {
bool b;
float f2[3];
vec3 v;
vec4 v2[2];
mat3 m;
} constants;
void func1( float f ){
// use the whole v2[1]. byte: 48-63.
vec2 v2 = constants.v2[1].yz;
}
void main(){
// use only v2[0].z. byte: 40-43.
func1( constants.v2[0].z);
// index of m is variable. The all m is used. byte: 64-99.
for(int i=1;i<2;++i) {
vec3 v3 = constants.m[i];
}
}
)glsl";
// push constant range: 0 - 95
char const *const fsSource = R"glsl(
#version 450
struct foo1{
int i[4];
}f;
layout(push_constant, std430) uniform foo {
float x[2][2][2];
foo1 s;
foo1 ss[3];
} constants;
void main(){
// use s. byte: 32-47.
f = constants.s;
// use every i[3] in ss. byte: 60-63, 76-79, 92-95.
for(int i=1;i<2;++i) {
int ii = constants.ss[i].i[3];
}
}
)glsl";
VkShaderObj const vs(this, vsSource, VK_SHADER_STAGE_VERTEX_BIT);
VkShaderObj const fs(this, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT);
VkPushConstantRange push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 128};
VkPushConstantRange push_constant_range_small = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 4, 4};
VkPipelineLayoutCreateInfo pipeline_layout_info = vku::InitStructHelper();
pipeline_layout_info.pushConstantRangeCount = 1;
pipeline_layout_info.pPushConstantRanges = &push_constant_range;
vkt::PipelineLayout pipeline_layout(*m_device, pipeline_layout_info);
CreatePipelineHelper g_pipe(*this);
g_pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
g_pipe.pipeline_layout_ci_ = pipeline_layout_info;
g_pipe.CreateGraphicsPipeline();
pipeline_layout_info.pPushConstantRanges = &push_constant_range_small;
vkt::PipelineLayout pipeline_layout_small(*m_device, pipeline_layout_info);
CreatePipelineHelper g_pipe_small_range(*this);
g_pipe_small_range.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
g_pipe_small_range.pipeline_layout_ci_ = pipeline_layout_info;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-10069");
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-10069");
g_pipe_small_range.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-maintenance4-08602"); // vertex
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-maintenance4-08602"); // fragment
vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, g_pipe.Handle());
vk::CmdBindDescriptorSets(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, g_pipe.pipeline_layout_.handle(), 0, 1,
&g_pipe.descriptor_set_->set_, 0, nullptr);
vk::CmdDraw(m_command_buffer.handle(), 1, 0, 0, 0);
m_errorMonitor->VerifyFound();
const float dummy_values[128] = {};
// NOTE: these are commented out due to ambiguity around VUID 02698 and push constant lifetimes
// See https://gitlab.khronos.org/vulkan/vulkan/-/issues/2602 and
// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/2689
// for more details.
// m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-maintenance4-08602");
// vk::CmdPushConstants(m_command_buffer.handle(), g_pipe.pipeline_layout_.handle(),
// VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 96, dummy_values);
// vk::CmdDraw(m_command_buffer.handle(), 1, 0, 0, 0);
// m_errorMonitor->VerifyFound();
// m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-maintenance4-08602");
// vk::CmdPushConstants(m_command_buffer.handle(), pipeline_layout_small, VK_SHADER_STAGE_VERTEX_BIT, 4, 4, dummy_values);
// vk::CmdDraw(m_command_buffer.handle(), 1, 0, 0, 0);
// m_errorMonitor->VerifyFound();
vk::CmdPushConstants(m_command_buffer.handle(), pipeline_layout.handle(),
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 32, 68, dummy_values);
vk::CmdDraw(m_command_buffer.handle(), 1, 0, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeShaderPushConstants, MultipleEntryPoint) {
TEST_DESCRIPTION("Test push-constant detect the write entrypoint with the push constants.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
// #version 460
// layout(push_constant) uniform Material {
// vec4 color;
// }constants;
// void main() {
// gl_Position = constants.color;
// }
//
// #version 460
// layout(location = 0) out vec4 uFragColor;
// void main(){
// uFragColor = vec4(0.0);
// }
const char *source = R"(
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main_f "main" %4
OpEntryPoint Vertex %main_v "main" %2
OpExecutionMode %main_f OriginUpperLeft
OpMemberDecorate %builtin_vert 0 BuiltIn Position
OpMemberDecorate %builtin_vert 1 BuiltIn PointSize
OpMemberDecorate %builtin_vert 2 BuiltIn ClipDistance
OpMemberDecorate %builtin_vert 3 BuiltIn CullDistance
OpDecorate %builtin_vert Block
OpMemberDecorate %struct_pc 0 Offset 0
OpDecorate %struct_pc Block
OpDecorate %4 Location 0
%void = OpTypeVoid
%8 = OpTypeFunction %void
%float = OpTypeFloat 32
; Vertex types
%v4float = OpTypeVector %float 4
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%array = OpTypeArray %float %uint_1
%builtin_vert = OpTypeStruct %v4float %float %array %array
%ptr_builtin_vert = OpTypePointer Output %builtin_vert
%2 = OpVariable %ptr_builtin_vert Output
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%struct_pc = OpTypeStruct %v4float
%ptr_pc_struct = OpTypePointer PushConstant %struct_pc
%18 = OpVariable %ptr_pc_struct PushConstant
%ptr_pc_vec4 = OpTypePointer PushConstant %v4float
%ptr_output_vert = OpTypePointer Output %v4float
; Fragment types
%ptr_output_frag = OpTypePointer Output %v4float
%4 = OpVariable %ptr_output_frag Output
%float_0 = OpConstant %float 0
%23 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
%main_v = OpFunction %void None %8
%24 = OpLabel
%25 = OpAccessChain %ptr_pc_vec4 %18 %int_0
%26 = OpLoad %v4float %25
%27 = OpAccessChain %ptr_output_vert %2 %int_0
OpStore %27 %26
OpReturn
OpFunctionEnd
%main_f = OpFunction %void None %8
%28 = OpLabel
OpStore %4 %23
OpReturn
OpFunctionEnd
)";
// Push constant are in the vertex Entrypoint
VkPushConstantRange push_constant_range = {VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16};
VkPipelineLayoutCreateInfo pipeline_layout_info = vku::InitStructHelper();
pipeline_layout_info.pushConstantRangeCount = 1;
pipeline_layout_info.pPushConstantRanges = &push_constant_range;
vkt::PipelineLayout pipeline_layout(*m_device, pipeline_layout_info);
VkShaderObj const vs(this, source, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM);
VkShaderObj const fs(this, source, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM);
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
pipe.gp_ci_.layout = pipeline_layout.handle();
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-07987");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
// Make sure Vertex is ok when used
push_constant_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
vkt::PipelineLayout pipeline_layout_good(*m_device, pipeline_layout_info);
pipe.gp_ci_.layout = pipeline_layout_good.handle();
pipe.CreateGraphicsPipeline();
}
// This is not working because of a bug in the Spec Constant logic
// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/5911
TEST_F(NegativeShaderPushConstants, DISABLED_SpecConstantSize) {
TEST_DESCRIPTION("Use SpecConstant to adjust size of Push Constant Block");
RETURN_IF_SKIP(Init());
const char *cs_source = R"glsl(
#version 460
layout (constant_id = 0) const int my_array_size = 1;
layout (push_constant) uniform my_buf {
float my_array[my_array_size];
} pc;
void main() {
float a = pc.my_array[0];
}
)glsl";
uint32_t data = 32;
VkSpecializationMapEntry entry;
entry.constantID = 0;
entry.offset = 0;
entry.size = sizeof(uint32_t);
VkSpecializationInfo specialization_info = {};
specialization_info.mapEntryCount = 1;
specialization_info.pMapEntries = &entry;
specialization_info.dataSize = sizeof(uint32_t);
specialization_info.pData = &data;
// With spec constant set, this should be 32, not 16
VkPushConstantRange push_constant_range = {VK_SHADER_STAGE_COMPUTE_BIT, 0, 16};
const vkt::PipelineLayout pipeline_layout(*m_device, {}, {push_constant_range});
CreateComputePipelineHelper pipe(*this);
pipe.cs_ = std::make_unique<VkShaderObj>(this, cs_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL,
&specialization_info);
pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {}, {push_constant_range});
m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-layout-07987");
pipe.CreateComputePipeline();
m_errorMonitor->VerifyFound();
}