layers: Add fix for lx172 to catch invalid line widths.
Validate line wdith in both vkCreateGraphicsPipelines and in
vkCmdSetLineWidth. Also, add a warning in vkCmdSetLineWidth
if the user calls it but doesn't enable dynamic line width.
Also, updated demos to fix missing lineWidth setting as well.
Change-Id: I62118da9cb5282fcc22b1506e9be2db82b5f4a40
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 655a455..3f627b9 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -403,6 +403,7 @@
rs_state.sType =
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rs_state.depthBiasEnable = VK_TRUE;
+ rs_state.lineWidth = 1.0f;
pipelineobj.SetRasterization(&rs_state);
}
// Viewport and scissors must stay in synch or other errors will occur than
@@ -4068,6 +4069,199 @@
vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
}
+TEST_F(VkLayerTest, PSOLineWidthInvalid) {
+ VkResult err;
+
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ "Attempt to set lineWidth to 0");
+
+ ASSERT_NO_FATAL_FAILURE(InitState());
+ ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
+
+ VkDescriptorPoolSize ds_type_count = {};
+ ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ ds_type_count.descriptorCount = 1;
+
+ VkDescriptorPoolCreateInfo ds_pool_ci = {};
+ ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ ds_pool_ci.maxSets = 1;
+ ds_pool_ci.poolSizeCount = 1;
+ ds_pool_ci.pPoolSizes = &ds_type_count;
+
+ VkDescriptorPool ds_pool;
+ err =
+ vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
+ ASSERT_VK_SUCCESS(err);
+
+ VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
+ dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ dsl_binding.descriptorCount = 1;
+ dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
+
+ VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
+ ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ ds_layout_ci.bindingCount = 1;
+ ds_layout_ci.pBindings = &dsl_binding;
+
+ VkDescriptorSetLayout ds_layout;
+ err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL,
+ &ds_layout);
+ ASSERT_VK_SUCCESS(err);
+
+ VkDescriptorSet descriptorSet;
+ VkDescriptorSetAllocateInfo alloc_info = {};
+ alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ alloc_info.descriptorSetCount = 1;
+ alloc_info.descriptorPool = ds_pool;
+ alloc_info.pSetLayouts = &ds_layout;
+ err = vkAllocateDescriptorSets(m_device->device(), &alloc_info,
+ &descriptorSet);
+ ASSERT_VK_SUCCESS(err);
+
+ VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
+ pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipeline_layout_ci.setLayoutCount = 1;
+ pipeline_layout_ci.pSetLayouts = &ds_layout;
+
+ VkPipelineLayout pipeline_layout;
+ err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL,
+ &pipeline_layout);
+ ASSERT_VK_SUCCESS(err);
+
+ VkPipelineViewportStateCreateInfo vp_state_ci = {};
+ vp_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp_state_ci.scissorCount = 1;
+ vp_state_ci.pScissors = NULL;
+ vp_state_ci.viewportCount = 1;
+ vp_state_ci.pViewports = NULL;
+
+ VkDynamicState dynamic_states[3] = {VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR,
+ VK_DYNAMIC_STATE_LINE_WIDTH};
+ // Set scissor as dynamic to avoid that error
+ VkPipelineDynamicStateCreateInfo dyn_state_ci = {};
+ dyn_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn_state_ci.dynamicStateCount = 2;
+ dyn_state_ci.pDynamicStates = dynamic_states;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2];
+ memset(&shaderStages, 0, 2 * sizeof(VkPipelineShaderStageCreateInfo));
+
+ VkShaderObj vs(m_device, bindStateVertShaderText,
+ VK_SHADER_STAGE_VERTEX_BIT, this);
+ VkShaderObj fs(m_device, bindStateFragShaderText,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ this); // TODO - We shouldn't need a fragment shader
+ // but add it to be able to run on more devices
+ shaderStages[0] = vs.GetStageCreateInfo();
+ shaderStages[1] = fs.GetStageCreateInfo();
+
+ VkPipelineVertexInputStateCreateInfo vi_ci = {};
+ vi_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vi_ci.pNext = nullptr;
+ vi_ci.vertexBindingDescriptionCount = 0;
+ vi_ci.pVertexBindingDescriptions = nullptr;
+ vi_ci.vertexAttributeDescriptionCount = 0;
+ vi_ci.pVertexAttributeDescriptions = nullptr;
+
+ VkPipelineInputAssemblyStateCreateInfo ia_ci = {};
+ ia_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia_ci.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+
+ VkPipelineRasterizationStateCreateInfo rs_ci = {};
+ rs_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs_ci.pNext = nullptr;
+
+ // Check too low (line width of 0.0f).
+ rs_ci.lineWidth = 0.0f;
+
+ VkPipelineColorBlendAttachmentState att = {};
+ att.blendEnable = VK_FALSE;
+ att.colorWriteMask = 0xf;
+
+ VkPipelineColorBlendStateCreateInfo cb_ci = {};
+ cb_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ cb_ci.pNext = nullptr;
+ cb_ci.attachmentCount = 1;
+ cb_ci.pAttachments = &att;
+
+ VkGraphicsPipelineCreateInfo gp_ci = {};
+ gp_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+ gp_ci.stageCount = 2;
+ gp_ci.pStages = shaderStages;
+ gp_ci.pVertexInputState = &vi_ci;
+ gp_ci.pInputAssemblyState = &ia_ci;
+ gp_ci.pViewportState = &vp_state_ci;
+ gp_ci.pRasterizationState = &rs_ci;
+ gp_ci.pColorBlendState = &cb_ci;
+ gp_ci.pDynamicState = &dyn_state_ci;
+ gp_ci.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
+ gp_ci.layout = pipeline_layout;
+ gp_ci.renderPass = renderPass();
+
+ VkPipelineCacheCreateInfo pc_ci = {};
+ pc_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+
+ VkPipeline pipeline;
+ VkPipelineCache pipelineCache;
+
+ err =
+ vkCreatePipelineCache(m_device->device(), &pc_ci, NULL, &pipelineCache);
+ ASSERT_VK_SUCCESS(err);
+ err = vkCreateGraphicsPipelines(m_device->device(), pipelineCache, 1,
+ &gp_ci, NULL, &pipeline);
+
+ m_errorMonitor->VerifyFound();
+
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ "Attempt to set lineWidth to 65536");
+
+ // Check too high (line width of 65536.0f).
+ rs_ci.lineWidth = 65536.0f;
+
+ err =
+ vkCreatePipelineCache(m_device->device(), &pc_ci, NULL, &pipelineCache);
+ ASSERT_VK_SUCCESS(err);
+ err = vkCreateGraphicsPipelines(m_device->device(), pipelineCache, 1,
+ &gp_ci, NULL, &pipeline);
+
+ m_errorMonitor->VerifyFound();
+
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ "Attempt to set lineWidth to 0");
+
+ dyn_state_ci.dynamicStateCount = 3;
+
+ rs_ci.lineWidth = 1.0f;
+
+ err =
+ vkCreatePipelineCache(m_device->device(), &pc_ci, NULL, &pipelineCache);
+ ASSERT_VK_SUCCESS(err);
+ err = vkCreateGraphicsPipelines(m_device->device(), pipelineCache, 1,
+ &gp_ci, NULL, &pipeline);
+ BeginCommandBuffer();
+ vkCmdBindPipeline(m_commandBuffer->GetBufferHandle(),
+ VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
+
+ // Check too low with dynamic setting.
+ vkCmdSetLineWidth(m_commandBuffer->GetBufferHandle(), 0.0f);
+ m_errorMonitor->VerifyFound();
+
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ "Attempt to set lineWidth to 65536");
+
+ // Check too high with dynamic setting.
+ vkCmdSetLineWidth(m_commandBuffer->GetBufferHandle(), 65536.0f);
+ m_errorMonitor->VerifyFound();
+ EndCommandBuffer();
+
+ vkDestroyPipelineCache(m_device->device(), pipelineCache, NULL);
+ vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);
+ vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
+ vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
+}
+
TEST_F(VkLayerTest, NullRenderPass) {
// Bind a NULL RenderPass
m_errorMonitor->SetDesiredFailureMsg(