Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

layers: Combine vkCmdSetDiscardRectangleEXT check #9210

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 35 additions & 30 deletions layers/core_checks/cc_cmd_buffer_dynamic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <vulkan/vk_enum_string_helper.h>
#include "core_validation.h"
#include "drawdispatch/drawdispatch_vuids.h"
#include "generated/error_location_helper.h"
#include "generated/vk_extension_helper.h"
#include "generated/dispatch_functions.h"
#include "state_tracker/image_state.h"
Expand Down Expand Up @@ -390,6 +391,39 @@ bool CoreChecks::ValidateGraphicsDynamicStateSetStatus(const LastBound& last_bou
if (last_bound_state.IsDiscardRectangleEnable()) {
skip |=
ValidateDynamicStateIsSet(last_bound_state, state_status_cb, CB_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT, vuid);

if (has_dynamic_state(CB_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT)) {
// For pipelines with VkPipelineDiscardRectangleStateCreateInfoEXT, we compare against discardRectangleCount,
// but for Shader Objects we compare against maxDiscardRectangles (details in
// https://gitlab.khronos.org/vulkan/vulkan/-/issues/3400)
uint32_t rect_limit = phys_dev_ext_props.discard_rectangle_props.maxDiscardRectangles;
bool use_max_limit = true;
if (has_pipeline) {
if (const auto* discard_rectangle_state =
vku::FindStructInPNextChain<VkPipelineDiscardRectangleStateCreateInfoEXT>(
last_bound_state.pipeline_state->GetCreateInfoPNext())) {
rect_limit = discard_rectangle_state->discardRectangleCount;
use_max_limit = false;
}
}

// vkCmdSetDiscardRectangleEXT needs to be set on each rectangle
for (uint32_t i = 0; i < rect_limit; i++) {
if (!cb_state.dynamic_state_value.discard_rectangles.test(i)) {
const vvl::Field limit_name =
use_max_limit ? vvl::Field::maxDiscardRectangles : vvl::Field::discardRectangleCount;
const char* vuid2 =
use_max_limit ? vuid.set_discard_rectangle_09236 : vuid.dynamic_discard_rectangle_07751;
skip |= LogError(vuid2, cb_state.Handle(), vuid.loc(),
"vkCmdSetDiscardRectangleEXT was not set for discard rectangle index %" PRIu32
" for this command buffer. It needs to be set once for each rectangle in %s (%" PRIu32
").%s",
i, String(limit_name), rect_limit,
cb_state.DescribeInvalidatedState(CB_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT).c_str());
break;
}
}
}
}
}

Expand Down Expand Up @@ -550,14 +584,6 @@ bool CoreChecks::ValidateGraphicsDynamicStatePipelineSetStatus(const LastBound&
vuid.dynamic_line_stipple_enable_07638);
}

// VK_EXT_discard_rectangles
{
if (last_bound_state.IsDiscardRectangleEnable()) {
skip |= ValidateDynamicStateIsSet(state_status_cb, CB_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT, cb_state, objlist, loc,
vuid.dynamic_discard_rectangle_07751);
}
}

// VK_EXT_vertex_input_dynamic_state
{
if (!pipeline.IsDynamic(CB_DYNAMIC_STATE_VERTEX_INPUT_EXT) &&
Expand Down Expand Up @@ -598,21 +624,6 @@ bool CoreChecks::ValidateGraphicsDynamicStateValue(const LastBound& last_bound_s
const vvl::CommandBuffer& cb_state = last_bound_state.cb_state;
const LogObjectList objlist(cb_state.Handle(), pipeline.Handle());

// vkCmdSetDiscardRectangleEXT needs to be set on each rectangle
const auto* discard_rectangle_state =
vku::FindStructInPNextChain<VkPipelineDiscardRectangleStateCreateInfoEXT>(pipeline.GetCreateInfoPNext());
if (discard_rectangle_state && pipeline.IsDynamic(CB_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT)) {
for (uint32_t i = 0; i < discard_rectangle_state->discardRectangleCount; i++) {
if (!cb_state.dynamic_state_value.discard_rectangles.test(i)) {
skip |= LogError(vuid.dynamic_discard_rectangle_07751, objlist, vuid.loc(),
"vkCmdSetDiscardRectangleEXT was not set for discard rectangle index %" PRIu32
" for this command buffer.%s",
i, cb_state.DescribeInvalidatedState(CB_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT).c_str());
break;
}
}
}

// must set the state for all active color attachments in the current subpass
for (const uint32_t& color_index : cb_state.active_color_attachments_index) {
if (pipeline.IsDynamic(CB_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT) &&
Expand Down Expand Up @@ -1616,13 +1627,7 @@ bool CoreChecks::ValidateDrawDynamicStateShaderObject(const LastBound& last_boun
}
}
}
if (IsExtEnabled(device_extensions.vk_ext_discard_rectangles)) {
if (cb_state.IsDynamicStateSet(CB_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT) &&
cb_state.dynamic_state_value.discard_rectangle_enable) {
skip |= ValidateDynamicStateIsSet(cb_state.dynamic_state_status.cb, CB_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT, cb_state,
objlist, loc, vuid.set_discard_rectangle_09236);
}
}

if (!phys_dev_ext_props.fragment_shading_rate_props.primitiveFragmentShadingRateWithMultipleViewports) {
for (uint32_t stage = 0; stage < kShaderObjectStageCount; ++stage) {
const auto shader_object = last_bound_state.GetShaderState(static_cast<ShaderObjectStage>(stage));
Expand Down
45 changes: 41 additions & 4 deletions tests/unit/dynamic_state.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* 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.
* Copyright (c) 2015-2025 The Khronos Group Inc.
* Copyright (c) 2015-2025 Valve Corporation
* Copyright (c) 2015-2025 LunarG, Inc.
* Copyright (c) 2015-2025 Google, Inc.
* Modifications Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -2853,6 +2853,43 @@ TEST_F(NegativeDynamicState, DiscardRectanglesNotSet) {
m_command_buffer.End();
}

TEST_F(NegativeDynamicState, DiscardRectanglesNotSetMaxDiscardRectangles) {
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();

VkPhysicalDeviceDiscardRectanglePropertiesEXT discard_rectangle_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(discard_rectangle_properties);
std::vector<VkRect2D> discard_rectangles(discard_rectangle_properties.maxDiscardRectangles);

if (discard_rectangle_properties.maxDiscardRectangles < 2) {
GTEST_SKIP() << "maxDiscardRectangles too small";
}

CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
// VkPipelineDiscardRectangleStateCreateInfoEXT is not used now
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
pipe.CreateGraphicsPipeline();

m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
vk::CmdSetDiscardRectangleEnableEXT(m_command_buffer.handle(), VK_TRUE);

m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-rasterizerDiscardEnable-09236");
vk::CmdDraw(m_command_buffer.handle(), 3, 1, 0, 0);
m_errorMonitor->VerifyFound();

vk::CmdSetDiscardRectangleEXT(m_command_buffer.handle(), 0, discard_rectangles.size() - 1, discard_rectangles.data());
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-rasterizerDiscardEnable-09236");
vk::CmdDraw(m_command_buffer.handle(), 3, 1, 0, 0);
m_errorMonitor->VerifyFound();

m_command_buffer.EndRenderPass();
m_command_buffer.End();
}

TEST_F(NegativeDynamicState, DiscardRectanglesEnableNotSet) {
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
Expand Down
63 changes: 50 additions & 13 deletions tests/unit/shader_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1616,20 +1616,19 @@ TEST_F(NegativeShaderObject, MissingCmdSetDiscardRectangleModeEXT) {
GTEST_SKIP() << "need VK_EXT_discard_rectangles version 2";
}
InitDynamicRenderTarget();
VkPhysicalDeviceDiscardRectanglePropertiesEXT discard_rectangle_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(discard_rectangle_properties);
std::vector<VkRect2D> discard_rectangles(discard_rectangle_properties.maxDiscardRectangles);

const vkt::Shader vertShader(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl));

const vkt::Shader fragShader(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT,
GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl));
const vkt::Shader vert_shader(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl));
const vkt::Shader frag_shader(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT,
GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl));
m_command_buffer.Begin();
m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea());
SetDefaultDynamicStatesExclude();
vk::CmdSetDiscardRectangleEnableEXT(m_command_buffer.handle(), VK_TRUE);
VkRect2D discardRectangle;
discardRectangle.offset = {};
discardRectangle.extent = {100u, 100u};
vk::CmdSetDiscardRectangleEXT(m_command_buffer.handle(), 0u, 1u, &discardRectangle);
m_command_buffer.BindVertFragShader(vertShader, fragShader);
vk::CmdSetDiscardRectangleEXT(m_command_buffer.handle(), 0u, discard_rectangles.size(), discard_rectangles.data());
m_command_buffer.BindVertFragShader(vert_shader, frag_shader);
vk::CmdDraw(m_command_buffer.handle(), 4, 1, 0, 0);
m_command_buffer.EndRendering();
m_command_buffer.End();
Expand All @@ -1649,23 +1648,61 @@ TEST_F(NegativeShaderObject, MissingCmdSetDiscardRectangleEXT) {
}
InitDynamicRenderTarget();

const vkt::Shader vertShader(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl));
const vkt::Shader vert_shader(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl));

const vkt::Shader fragShader(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT,
GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl));
const vkt::Shader frag_shader(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT,
GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl));
m_command_buffer.Begin();
m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea());
SetDefaultDynamicStatesExclude();
vk::CmdSetDiscardRectangleEnableEXT(m_command_buffer.handle(), VK_TRUE);
vk::CmdSetDiscardRectangleModeEXT(m_command_buffer.handle(), VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT);
m_command_buffer.BindVertFragShader(vertShader, fragShader);
m_command_buffer.BindVertFragShader(vert_shader, frag_shader);
vk::CmdDraw(m_command_buffer.handle(), 4, 1, 0, 0);
m_command_buffer.EndRendering();
m_command_buffer.End();

m_errorMonitor->VerifyFound();
}

TEST_F(NegativeShaderObject, MissingCmdSetDiscardRectangleMaxDiscardRectangles) {
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(InitBasicShaderObject());
if (!DeviceExtensionSupported(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME, 2)) {
GTEST_SKIP() << "need VK_EXT_discard_rectangles version 2";
}
InitDynamicRenderTarget();

VkPhysicalDeviceDiscardRectanglePropertiesEXT discard_rectangle_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(discard_rectangle_properties);
if (discard_rectangle_properties.maxDiscardRectangles < 2) {
GTEST_SKIP() << "Need at least maxDiscardRectangles of 2";
}

const uint32_t count = discard_rectangle_properties.maxDiscardRectangles - 1;
std::vector<VkRect2D> discard_rectangles(count);

const vkt::Shader vert_shader(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl));
const vkt::Shader frag_shader(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT,
GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl));

m_command_buffer.Begin();
m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea());
SetDefaultDynamicStatesExclude();
vk::CmdSetDiscardRectangleEnableEXT(m_command_buffer.handle(), VK_TRUE);
vk::CmdSetDiscardRectangleModeEXT(m_command_buffer.handle(), VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT);
m_command_buffer.BindVertFragShader(vert_shader, frag_shader);

vk::CmdSetDiscardRectangleEXT(m_command_buffer.handle(), 0u, count, discard_rectangles.data());

m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-rasterizerDiscardEnable-09236");
vk::CmdDraw(m_command_buffer.handle(), 4, 1, 0, 0);
m_errorMonitor->VerifyFound();

m_command_buffer.EndRendering();
m_command_buffer.End();
}

TEST_F(NegativeShaderObject, MissingCmdSetDepthClampEnableEXT) {
TEST_DESCRIPTION("Draw with shader objects without setting vkCmdSetDepthClampEnableEXT().");

Expand Down
16 changes: 8 additions & 8 deletions tests/unit/shader_object_positive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1649,21 +1649,21 @@ TEST_F(PositiveShaderObject, DiscardRectangleModeEXT) {
GTEST_SKIP() << "need VK_EXT_discard_rectangles version 2";
}
InitDynamicRenderTarget();
VkPhysicalDeviceDiscardRectanglePropertiesEXT discard_rectangle_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(discard_rectangle_properties);
std::vector<VkRect2D> discard_rectangles(discard_rectangle_properties.maxDiscardRectangles);

const vkt::Shader vertShader(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl));
const vkt::Shader vert_shader(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl));

const vkt::Shader fragShader(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT,
GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl));
const vkt::Shader frag_shader(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT,
GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl));
m_command_buffer.Begin();
m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea());
SetDefaultDynamicStatesExclude();
vk::CmdSetDiscardRectangleEnableEXT(m_command_buffer.handle(), VK_TRUE);
VkRect2D discardRectangle;
discardRectangle.offset = {};
discardRectangle.extent = {100u, 100u};
vk::CmdSetDiscardRectangleEXT(m_command_buffer.handle(), 0u, 1u, &discardRectangle);
vk::CmdSetDiscardRectangleEXT(m_command_buffer.handle(), 0u, discard_rectangles.size(), discard_rectangles.data());
vk::CmdSetDiscardRectangleModeEXT(m_command_buffer.handle(), VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT);
m_command_buffer.BindVertFragShader(vertShader, fragShader);
m_command_buffer.BindVertFragShader(vert_shader, frag_shader);
vk::CmdDraw(m_command_buffer.handle(), 4, 1, 0, 0);
m_command_buffer.EndRendering();
m_command_buffer.End();
Expand Down
Loading