Skip to content
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
9 changes: 0 additions & 9 deletions layers/core_checks/cc_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,15 +1076,6 @@ bool CoreChecks::PreCallValidateCmdClearDepthStencilImage(VkCommandBuffer comman
return skip;
}

// Returns true if sub_rect is entirely contained within rect
static inline bool ContainsRect(VkRect2D rect, VkRect2D sub_rect) {
if ((sub_rect.offset.x < rect.offset.x) || (sub_rect.offset.x + sub_rect.extent.width > rect.offset.x + rect.extent.width) ||
(sub_rect.offset.y < rect.offset.y) || (sub_rect.offset.y + sub_rect.extent.height > rect.offset.y + rect.extent.height)) {
return false;
}
return true;
}

bool CoreChecks::ValidateClearAttachmentExtent(const vvl::CommandBuffer &cb_state, const VkRect2D &render_area,
uint32_t render_pass_layer_count, uint32_t rect_count,
const VkClearRect *clear_rects, const Location &loc) const {
Expand Down
13 changes: 6 additions & 7 deletions layers/core_checks/cc_render_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,8 @@ bool CoreChecks::ValidateCmdBeginRenderPass(VkCommandBuffer commandBuffer, const
uint32_t clear_op_size = 0; // Make sure pClearValues is at least as large as last LOAD_OP_CLEAR

// Handle extension struct from EXT_sample_locations
const auto *sample_locations_begin_info =
vku::FindStructInPNextChain<VkRenderPassSampleLocationsBeginInfoEXT>(pRenderPassBegin->pNext);
if (sample_locations_begin_info) {
if (const auto* sample_locations_begin_info =
vku::FindStructInPNextChain<VkRenderPassSampleLocationsBeginInfoEXT>(pRenderPassBegin->pNext)) {
for (uint32_t i = 0; i < sample_locations_begin_info->attachmentInitialSampleLocationsCount; ++i) {
const Location sampler_loc =
rp_begin_loc.pNext(Struct::VkRenderPassSampleLocationsBeginInfoEXT, Field::pAttachmentInitialSampleLocations, i);
Expand Down Expand Up @@ -616,8 +615,8 @@ bool CoreChecks::ValidateCmdBeginRenderPass(VkCommandBuffer commandBuffer, const
"maintenance7 were not enabled.");
}

const auto counters_begin_info = vku::FindStructInPNextChain<VkRenderPassPerformanceCountersByRegionBeginInfoARM>(pRenderPassBegin->pNext);
if (counters_begin_info) {
if (const auto counters_begin_info =
vku::FindStructInPNextChain<VkRenderPassPerformanceCountersByRegionBeginInfoARM>(pRenderPassBegin->pNext)) {
const LogObjectList objlist(cb_state.Handle(), rp_state->Handle());
uint32_t layer_or_view_count = 0;
if (rp_state->has_multiview_enabled) {
Expand Down Expand Up @@ -3847,8 +3846,8 @@ bool CoreChecks::PreCallValidateCmdBeginRendering(VkCommandBuffer commandBuffer,
pRenderingInfo->viewMask, phys_dev_props_core11.maxMultiviewViewCount);
}

const auto counters_begin_info = vku::FindStructInPNextChain<VkRenderPassPerformanceCountersByRegionBeginInfoARM>(pRenderingInfo->pNext);
if (counters_begin_info) {
if (const auto counters_begin_info =
vku::FindStructInPNextChain<VkRenderPassPerformanceCountersByRegionBeginInfoARM>(pRenderingInfo->pNext)) {
const LogObjectList objlist(cb_state->Handle());
uint32_t layer_or_view_count = 0;
if (enabled_features.multiview) {
Expand Down
89 changes: 89 additions & 0 deletions layers/stateless/sl_render_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "utils/math_utils.h"
#include "utils/image_utils.h"
#include "utils/sync_utils.h"
#include "utils/vk_api_utils.h"

namespace stateless {

Expand Down Expand Up @@ -579,6 +580,82 @@ bool Device::ValidateRenderPassStripeBeginInfo(VkCommandBuffer commandBuffer, co
return skip;
}

bool Device::ValidateMultiviewPerViewRenderAreasRenderPassBeginInfo(
VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* rp_begin_info, const VkRenderingInfo* rendering_info,
const VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM& multiview_per_view_info, const Location& loc) const {
bool skip = false;
if (multiview_per_view_info.perViewRenderAreaCount != 0 && !enabled_features.multiviewPerViewRenderAreas) {
const char* vuid = rp_begin_info ? "VUID-VkRenderPassBeginInfo-perViewRenderAreaCount-07859"
: "VUID-VkRenderingInfo-perViewRenderAreaCount-07857";
skip |= LogError(vuid, commandBuffer,
loc.pNext(Struct::VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM).dot(Field::perViewRenderAreaCount),
"is %" PRIu32 " but the multiviewPerViewRenderAreas feature was not enabled.",
multiview_per_view_info.perViewRenderAreaCount);
}

if (rendering_info) {
const uint32_t msb = (uint32_t)MostSignificantBit(rendering_info->viewMask);
if (multiview_per_view_info.perViewRenderAreaCount != msb + 1) {
skip |= LogError(
"VUID-VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM-pNext-07866", commandBuffer,
loc.pNext(Struct::VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM).dot(Field::perViewRenderAreaCount),
"(%" PRIu32 ") must be VkRenderingInfo::viewMask (0x%" PRIx32 ") most significant bit index (%" PRIu32 ") + 1",
multiview_per_view_info.perViewRenderAreaCount, rendering_info->viewMask, msb);
}
}

const VkRect2D full_render_area = rendering_info ? rendering_info->renderArea : rp_begin_info->renderArea;

for (uint32_t i = 0; i < multiview_per_view_info.perViewRenderAreaCount; i++) {
const VkRect2D view_rect = multiview_per_view_info.pPerViewRenderAreas[i];
if (view_rect.offset.x < 0) {
skip |= LogError("VUID-VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM-offset-07861", commandBuffer,
loc.pNext(Struct::VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM)
.dot(Field::pPerViewRenderAreas, i)
.dot(Field::offset)
.dot(Field::x),
"(%" PRId32 ") is less than zero.", view_rect.offset.x);
}
if (view_rect.offset.y < 0) {
skip |= LogError("VUID-VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM-offset-07862", commandBuffer,
loc.pNext(Struct::VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM)
.dot(Field::pPerViewRenderAreas, i)
.dot(Field::offset)
.dot(Field::y),
"(%" PRId32 ") is less than zero.", view_rect.offset.y);
}
if ((view_rect.offset.x + view_rect.extent.width) > phys_dev_props.limits.maxFramebufferWidth) {
skip |= LogError("VUID-VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM-offset-07863", commandBuffer,
loc.pNext(Struct::VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM)
.dot(Field::pPerViewRenderAreas, i)
.dot(Field::offset)
.dot(Field::x),
"%" PRId32 " + extent.width (%" PRIu32 ") greater than maxFramebufferWidth (%" PRIu32 ").",
view_rect.offset.x, view_rect.extent.width, phys_dev_props.limits.maxFramebufferWidth);
}
if ((view_rect.offset.y + view_rect.extent.height) > phys_dev_props.limits.maxFramebufferHeight) {
skip |= LogError("VUID-VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM-offset-07864", commandBuffer,
loc.pNext(Struct::VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM)
.dot(Field::pPerViewRenderAreas, i)
.dot(Field::offset)
.dot(Field::y),
"%" PRId32 " + extent.height (%" PRIu32 ") greater than maxFramebufferHeight (%" PRIu32 ").",
view_rect.offset.y, view_rect.extent.height, phys_dev_props.limits.maxFramebufferHeight);
}

if (!ContainsRect(full_render_area, view_rect)) {
const char* vuid = rp_begin_info ? "VUID-VkRenderPassBeginInfo-perViewRenderAreaCount-07860"
: "VUID-VkRenderingInfo-perViewRenderAreaCount-07858";
skip |=
LogError(vuid, commandBuffer,
loc.pNext(Struct::VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM).dot(Field::pPerViewRenderAreas, i),
"(%s) is not contained in %s::renderArea (%s)", string_VkRect2D(view_rect).c_str(),
rendering_info ? "VkRenderingInfo" : "VkRenderPassBeginInfo", string_VkRect2D(full_render_area).c_str());
}
}
return skip;
}

bool Device::ValidateCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *const rp_begin,
const ErrorObject &error_obj) const {
bool skip = false;
Expand All @@ -592,6 +669,12 @@ bool Device::ValidateCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkR
const Location loc = error_obj.location.dot(Field::pRenderPassBegin);
skip |= ValidateRenderPassStripeBeginInfo(commandBuffer, rp_begin->pNext, rp_begin->renderArea, loc);

if (const auto multiview_per_view_info =
vku::FindStructInPNextChain<VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM>(rp_begin->pNext)) {
skip |=
ValidateMultiviewPerViewRenderAreasRenderPassBeginInfo(commandBuffer, rp_begin, nullptr, *multiview_per_view_info, loc);
}

return skip;
}

Expand Down Expand Up @@ -735,6 +818,12 @@ bool Device::manual_PreCallValidateCmdBeginRendering(VkCommandBuffer commandBuff
}
}

if (const auto multiview_per_view_info =
vku::FindStructInPNextChain<VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM>(pRenderingInfo->pNext)) {
skip |= ValidateMultiviewPerViewRenderAreasRenderPassBeginInfo(commandBuffer, nullptr, pRenderingInfo,
*multiview_per_view_info, rendering_info_loc);
}

skip |= ValidateRenderPassStripeBeginInfo(commandBuffer, pRenderingInfo->pNext, pRenderingInfo->renderArea, rendering_info_loc);
skip |= ValidateBeginRenderingColorAttachment(commandBuffer, *pRenderingInfo, rendering_info_loc);
skip |= ValidateBeginRenderingDepthAttachment(commandBuffer, *pRenderingInfo, rendering_info_loc);
Expand Down
3 changes: 3 additions & 0 deletions layers/stateless/stateless_validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,9 @@ class Device : public vvl::base::Device {
const VkClearColorValue *pColor, uint32_t rangeCount,
const VkImageSubresourceRange *pRanges, const Context &context) const;

bool ValidateMultiviewPerViewRenderAreasRenderPassBeginInfo(
VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* rp_begin_info, const VkRenderingInfo* rendering_info,
const VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM& multiview_per_view_info, const Location& loc) const;
bool ValidateRenderPassStripeBeginInfo(VkCommandBuffer commandBuffer, const void *pNext, const VkRect2D render_area,
const Location &loc) const;
bool ValidateCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *const rp_begin,
Expand Down
9 changes: 9 additions & 0 deletions layers/utils/vk_api_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ static inline VkOffset3D CastTo3D(const VkOffset2D &d2) {
return d3;
}

// Returns true if sub_rect is entirely contained within rect
static inline bool ContainsRect(VkRect2D rect, VkRect2D sub_rect) {
if ((sub_rect.offset.x < rect.offset.x) || (sub_rect.offset.x + sub_rect.extent.width > rect.offset.x + rect.extent.width) ||
(sub_rect.offset.y < rect.offset.y) || (sub_rect.offset.y + sub_rect.extent.height > rect.offset.y + rect.extent.height)) {
return false;
}
return true;
}

static constexpr VkPipelineStageFlags2 kFramebufferStagePipelineStageFlags =
(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
Expand Down
92 changes: 92 additions & 0 deletions tests/unit/multiview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
* http://www.apache.org/licenses/LICENSE-2.0
*/

#include <vulkan/vulkan_core.h>
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
#include "../framework/descriptor_helper.h"
#include "../framework/render_pass_helper.h"
#include "binding.h"
#include "utils/convert_utils.h"

class NegativeMultiview : public VkLayerTest {};
Expand Down Expand Up @@ -1282,6 +1284,96 @@ TEST_F(NegativeMultiview, ShaderLayerBuiltInDynamicRendering) {
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeMultiview, MultiviewPerViewRenderAreasFeature) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_MULTIVIEW_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::multiview);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());

vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView image_view = image.CreateView(VK_IMAGE_VIEW_TYPE_2D_ARRAY);

VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
color_attachment.imageView = image_view;
color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;

VkRect2D view_render_area = {{0, 0}, {32, 32}};
VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM multiview_pre_view = vku::InitStructHelper();
multiview_pre_view.perViewRenderAreaCount = 1;
multiview_pre_view.pPerViewRenderAreas = &view_render_area;

VkRenderingInfo rendering_info = vku::InitStructHelper(&multiview_pre_view);
rendering_info.renderArea = {{0, 0}, {32, 32}};
rendering_info.layerCount = 1u;
rendering_info.colorAttachmentCount = 1u;
rendering_info.pColorAttachments = &color_attachment;
rendering_info.viewMask = 0x1;

m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkRenderingInfo-perViewRenderAreaCount-07857");
m_command_buffer.BeginRendering(rendering_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}

TEST_F(NegativeMultiview, MultiviewPerViewRenderAreas) {
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_KHR_MULTIVIEW_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::multiview);
AddRequiredFeature(vkt::Feature::dynamicRendering);
AddRequiredFeature(vkt::Feature::multiviewPerViewRenderAreas);
RETURN_IF_SKIP(Init());

vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView image_view = image.CreateView(VK_IMAGE_VIEW_TYPE_2D_ARRAY);

VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
color_attachment.imageView = image_view;
color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;

VkRect2D view_render_area[2] = {{{-1, 0}, {16, 16}}, {{0, -1}, {16, 16}}};
VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM multiview_pre_view = vku::InitStructHelper();
multiview_pre_view.perViewRenderAreaCount = 2;
multiview_pre_view.perViewRenderAreaCount = 2;
multiview_pre_view.pPerViewRenderAreas = view_render_area;

VkRenderingInfo rendering_info = vku::InitStructHelper(&multiview_pre_view);
rendering_info.renderArea = {{-1, -1}, {31, 31}};
rendering_info.layerCount = 1u;
rendering_info.colorAttachmentCount = 1u;
rendering_info.pColorAttachments = &color_attachment;
rendering_info.viewMask = 0x3;

m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM-offset-07861");
m_errorMonitor->SetDesiredError("VUID-VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM-offset-07862");
m_command_buffer.BeginRendering(rendering_info);
m_errorMonitor->VerifyFound();

view_render_area[0] = {{0, 0}, {16, 16}};
view_render_area[1] = {{0, 0}, {32, 16}};

m_errorMonitor->SetDesiredError("VUID-VkRenderingInfo-perViewRenderAreaCount-07858");
m_command_buffer.BeginRendering(rendering_info);
m_errorMonitor->VerifyFound();

multiview_pre_view.perViewRenderAreaCount = 1;
m_errorMonitor->SetDesiredError("VUID-VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM-pNext-07866");
m_command_buffer.BeginRendering(rendering_info);
m_errorMonitor->VerifyFound();

m_command_buffer.End();
}

TEST_F(NegativeMultiview, MeshShader) {
TEST_DESCRIPTION("https://gitlab.khronos.org/vulkan/vulkan/-/issues/4194");
SetTargetApiVersion(VK_API_VERSION_1_2);
Expand Down