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

Add missing swapchain maintenance validation #9107

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
18 changes: 18 additions & 0 deletions layers/core_checks/cc_wsi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,8 @@ bool CoreChecks::PreCallValidateQueuePresentKHR(VkQueue queue, const VkPresentIn
skip |= sem_submit_state.ValidateWaitSemaphore(present_info_loc.dot(Field::pWaitSemaphores, i), *semaphore_state, 0);
}

uint32_t swapchain_with_present_modes = pPresentInfo->swapchainCount;
uint32_t swapchain_without_present_modes = pPresentInfo->swapchainCount;
for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
auto swapchain_data = Get<vvl::Swapchain>(pPresentInfo->pSwapchains[i]);
ASSERT_AND_CONTINUE(swapchain_data);
Expand Down Expand Up @@ -866,7 +868,23 @@ bool CoreChecks::PreCallValidateQueuePresentKHR(VkQueue queue, const VkPresentIn
"image on queue that cannot present to this surface.");
}
}

if (vku::FindStructInPNextChain<VkSwapchainPresentModesCreateInfoEXT>(swapchain_data->create_info.pNext)) {
swapchain_with_present_modes = i;
} else {
swapchain_without_present_modes = i;
}
}
if (swapchain_with_present_modes < pPresentInfo->swapchainCount &&
swapchain_without_present_modes < pPresentInfo->swapchainCount) {
skip |= LogError(
"VUID-VkPresentInfoKHR-pSwapchains-09199", device, error_obj.location,
"pSwapchains[%" PRIu32 "] (%s) was created with VkSwapchainPresentModesCreateInfoEXT, but pSwapchains[%" PRIu32
"] (%s) was not.",
swapchain_with_present_modes, FormatHandle(pPresentInfo->pSwapchains[swapchain_with_present_modes]).c_str(),
swapchain_without_present_modes, FormatHandle(pPresentInfo->pSwapchains[swapchain_without_present_modes]).c_str());
}

if (pPresentInfo->pNext) {
// Verify ext struct
const auto *present_regions = vku::FindStructInPNextChain<VkPresentRegionsKHR>(pPresentInfo->pNext);
Expand Down
63 changes: 63 additions & 0 deletions layers/stateless/sl_wsi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,48 @@ bool StatelessValidation::manual_PreCallValidateAcquireNextImage2KHR(VkDevice de
return skip;
}

bool StatelessValidation::ValidateSwapchainCreateInfoMaintenance1(const VkSwapchainCreateInfoKHR &create_info,
const Location &loc) const {
bool skip = false;

if (enabled_features.swapchainMaintenance1) {
return skip;
}

if (vku::FindStructInPNextChain<VkSwapchainPresentModesCreateInfoEXT>(create_info.pNext)) {
skip |= LogError("VUID-VkSwapchainCreateInfoKHR-swapchainMaintenance1-10155", device, loc.dot(Field::pNext),
"contains VkSwapchainPresentModesCreateInfoEXT, but swapchainMaintenance1 is not enabled");
}

if (const auto *present_scaling_create_info =
vku::FindStructInPNextChain<VkSwapchainPresentScalingCreateInfoEXT>(create_info.pNext)) {
if (present_scaling_create_info->scalingBehavior != 0) {
skip |= LogError("VUID-VkSwapchainPresentScalingCreateInfoEXT-swapchainMaintenance1-10154", device,
loc.pNext(Struct::VkSwapchainPresentScalingCreateInfoEXT, Field::scalingBehavior),
" is %s, but swapchainMaintenance1 is not enabled",
string_VkPresentScalingFlagsEXT(present_scaling_create_info->scalingBehavior).c_str());
} else if (present_scaling_create_info->presentGravityX != 0) {
skip |= LogError("VUID-VkSwapchainPresentScalingCreateInfoEXT-swapchainMaintenance1-10154", device,
loc.pNext(Struct::VkSwapchainPresentScalingCreateInfoEXT, Field::presentGravityX),
" is %s, but swapchainMaintenance1 is not enabled",
string_VkPresentGravityFlagsEXT(present_scaling_create_info->presentGravityX).c_str());
} else if (present_scaling_create_info->presentGravityY != 0) {
skip |= LogError("VUID-VkSwapchainPresentScalingCreateInfoEXT-swapchainMaintenance1-10154", device,
loc.pNext(Struct::VkSwapchainPresentScalingCreateInfoEXT, Field::presentGravityY),
" is %s, but swapchainMaintenance1 is not enabled",
string_VkPresentGravityFlagsEXT(present_scaling_create_info->presentGravityY).c_str());
}
}

if (create_info.flags & VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT) {
skip |= LogError("VUID-VkSwapchainCreateInfoKHR-swapchainMaintenance1-10157", device, loc.dot(Field::flags),
"is %s, but swapchainMaintenance1 is not enabled",
string_VkSwapchainCreateFlagsKHR(create_info.flags).c_str());
}

return skip;
}

bool StatelessValidation::ValidateSwapchainCreateInfo(const VkSwapchainCreateInfoKHR &create_info, const Location &loc) const {
bool skip = false;

Expand Down Expand Up @@ -151,6 +193,21 @@ bool StatelessValidation::ValidateSwapchainCreateInfo(const VkSwapchainCreateInf
}
}

skip |= ValidateSwapchainCreateInfoMaintenance1(create_info, loc);

return skip;
}

bool StatelessValidation::manual_PreCallValidateReleaseSwapchainImagesEXT(VkDevice device,
const VkReleaseSwapchainImagesInfoEXT *pReleaseInfo,
const ErrorObject &error_obj) const {
bool skip = false;

if (!enabled_features.swapchainMaintenance1) {
skip |= LogError("VUID-vkReleaseSwapchainImagesEXT-swapchainMaintenance1-10159", device, error_obj.location,
"swapchainMaintenance1 is not enabled");
}

return skip;
}

Expand Down Expand Up @@ -191,6 +248,12 @@ bool StatelessValidation::manual_PreCallValidateQueuePresentKHR(VkQueue queue, c
}
}

if (vku::FindStructInPNextChain<VkSwapchainPresentFenceInfoEXT>(pPresentInfo->pNext) &&
!enabled_features.swapchainMaintenance1) {
skip |= LogError("VUID-VkPresentInfoKHR-swapchainMaintenance1-10158", device, error_obj.location.dot(Field::pNext),
"contains VkSwapchainPresentFenceInfoEXT, but swapchainMaintenance1 is not enabled");
}

for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
for (uint32_t j = i + 1; j < pPresentInfo->swapchainCount; ++j) {
if (pPresentInfo->pSwapchains[i] == pPresentInfo->pSwapchains[j]) {
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 @@ -397,7 +397,10 @@ class StatelessValidation : public ValidationObject {
bool ValidateGeometryNV(const VkGeometryNV &geometry, VkAccelerationStructureNV object_handle, const Location &loc) const;
bool ValidateAccelerationStructureInfoNV(const VkAccelerationStructureInfoNV &info, VkAccelerationStructureNV object_handle,
const Location &loc) const;
bool ValidateSwapchainCreateInfoMaintenance1(const VkSwapchainCreateInfoKHR &create_info, const Location &loc) const;
bool ValidateSwapchainCreateInfo(const VkSwapchainCreateInfoKHR &create_info, const Location &loc) const;
bool manual_PreCallValidateReleaseSwapchainImagesEXT(VkDevice device, const VkReleaseSwapchainImagesInfoEXT *pReleaseInfo,
const ErrorObject &error_obj) const;

bool OutputExtensionError(const Location &loc, const vvl::Extensions &exentsions) const;

Expand Down
26 changes: 13 additions & 13 deletions layers/vulkan/generated/feature_requirements_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4357,21 +4357,21 @@ FeatureAndName AddFeature(APIVersion api_version, vkt::Feature feature, void **i
}
#ifdef VK_ENABLE_BETA_EXTENSIONS

case Feature::constantAlphaColorBlendFactors : {
auto vk_struct = const_cast<VkPhysicalDevicePortabilitySubsetFeaturesKHR *>(
vku::FindStructInPNextChain<VkPhysicalDevicePortabilitySubsetFeaturesKHR>(*inout_pnext_chain));
if (!vk_struct) {
vk_struct = new VkPhysicalDevicePortabilitySubsetFeaturesKHR;
*vk_struct = vku::InitStructHelper();
if (*inout_pnext_chain) {
vvl::PnextChainAdd(*inout_pnext_chain, vk_struct);
} else {
*inout_pnext_chain = vk_struct;
}
case Feature::constantAlphaColorBlendFactors : {
auto vk_struct = const_cast<VkPhysicalDevicePortabilitySubsetFeaturesKHR *>(
vku::FindStructInPNextChain<VkPhysicalDevicePortabilitySubsetFeaturesKHR>(*inout_pnext_chain));
if (!vk_struct) {
vk_struct = new VkPhysicalDevicePortabilitySubsetFeaturesKHR;
*vk_struct = vku::InitStructHelper();
if (*inout_pnext_chain) {
vvl::PnextChainAdd(*inout_pnext_chain, vk_struct);
} else {
*inout_pnext_chain = vk_struct;
}
return {&vk_struct->constantAlphaColorBlendFactors,
"VkPhysicalDevicePortabilitySubsetFeaturesKHR::constantAlphaColorBlendFactors"};
}
return {&vk_struct->constantAlphaColorBlendFactors,
"VkPhysicalDevicePortabilitySubsetFeaturesKHR::constantAlphaColorBlendFactors"};
}
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS

Expand Down
1 change: 1 addition & 0 deletions layers/vulkan/generated/stateless_validation_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23625,6 +23625,7 @@ bool StatelessValidation::PreCallValidateReleaseSwapchainImagesEXT(VkDevice devi
"VUID-VkReleaseSwapchainImagesInfoEXT-imageIndexCount-arraylength",
"VUID-VkReleaseSwapchainImagesInfoEXT-pImageIndices-parameter");
}
if (!skip) skip |= manual_PreCallValidateReleaseSwapchainImagesEXT(device, pReleaseInfo, error_obj);
return skip;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def __init__(self,
'vkGetDeviceMicromapCompatibilityEXT',
'vkGetMicromapBuildSizesEXT',
'vkWriteMicromapsPropertiesEXT',
'vkReleaseSwapchainImagesEXT',
]

# Commands to ignore
Expand Down
153 changes: 153 additions & 0 deletions tests/unit/wsi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1900,6 +1900,7 @@ TEST_F(NegativeWsi, SwapchainMaintenance1ExtensionAcquire) {
AddRequiredExtensions(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
AddSurfaceExtension();
AddRequiredFeature(vkt::Feature::swapchainMaintenance1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is needed for PositiveWsi.CreateSwapchainWithPresentModeInfo and PositiveWsi.PresentFenceWaitsForSubmission

RETURN_IF_SKIP(Init());

if (IsPlatformMockICD()) {
Expand Down Expand Up @@ -2210,6 +2211,7 @@ TEST_F(NegativeWsi, SwapchainMaintenance1ExtensionCaps) {
AddRequiredExtensions(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::swapchainMaintenance1);
AddSurfaceExtension();

RETURN_IF_SKIP(InitFramework());
Expand Down Expand Up @@ -2346,6 +2348,7 @@ TEST_F(NegativeWsi, SwapchainMaintenance1ExtensionRelease) {
AddRequiredExtensions(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
AddSurfaceExtension();
AddRequiredFeature(vkt::Feature::swapchainMaintenance1);
RETURN_IF_SKIP(Init());
if (IsPlatformMockICD()) {
GTEST_SKIP() << "Test not supported by MockICD";
Expand Down Expand Up @@ -3536,6 +3539,156 @@ TEST_F(NegativeWsi, SurfaceCounters) {
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeWsi, PresentInfoSwapchainsDifferentPresentModes) {
TEST_DESCRIPTION("Submit VkPresentInfo where one swapchain has VkSwapchainPresentModesCreateInfoEXT and the other does not");

AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at CI, the logic in AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME); should automatically include VK_KHR_get_physical_device_properties2 but the call under is using vkGetPhysicalDeviceFeatures2

I think the simple fix is just for anything it using Swapchain Maintenance 1 to just include SetTargetApiVersion(VK_API_VERSION_1_1); with it to not hit this issue (there is no way a 1.0 device is going to try and ship this extension)

AddRequiredFeature(vkt::Feature::swapchainMaintenance1);
AddSurfaceExtension();
RETURN_IF_SKIP(Init());
RETURN_IF_SKIP(InitSurface());
InitSwapchainInfo();

SurfaceContext surface_context{};
vkt::Surface surface2{};
if (CreateSurface(surface_context, surface2) != VK_SUCCESS) {
GTEST_SKIP() << "Cannot create required surface";
}

VkSwapchainCreateInfoKHR swapchain_ci = vku::InitStructHelper();
swapchain_ci.surface = m_surface.Handle();
swapchain_ci.minImageCount = m_surface_capabilities.minImageCount;
swapchain_ci.imageFormat = m_surface_formats[0].format;
swapchain_ci.imageColorSpace = m_surface_formats[0].colorSpace;
swapchain_ci.imageExtent = {m_surface_capabilities.minImageExtent.width, m_surface_capabilities.minImageExtent.height};
swapchain_ci.imageArrayLayers = 1u;
swapchain_ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchain_ci.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
swapchain_ci.compositeAlpha = m_surface_composite_alpha;
swapchain_ci.presentMode = m_surface_non_shared_present_mode;
swapchain_ci.clipped = VK_FALSE;
swapchain_ci.oldSwapchain = 0u;

vkt::Swapchain swapchain1(*m_device, swapchain_ci);
VkSwapchainPresentModesCreateInfoEXT present_modes_ci = vku::InitStructHelper();
present_modes_ci.presentModeCount = 1u;
present_modes_ci.pPresentModes = &swapchain_ci.presentMode;
swapchain_ci.surface = surface2.Handle();
swapchain_ci.pNext = &present_modes_ci;
vkt::Swapchain swapchain2(*m_device, swapchain_ci);

vkt::Semaphore image_acquired1(*m_device);
vkt::Semaphore image_acquired2(*m_device);
const uint32_t image_index1 = swapchain1.AcquireNextImage(image_acquired1, kWaitTimeout);
const uint32_t image_index2 = swapchain2.AcquireNextImage(image_acquired2, kWaitTimeout);

const VkImageMemoryBarrier present_transitions[] = {
TransitionToPresent(swapchain1.GetImages()[image_index1], VK_IMAGE_LAYOUT_UNDEFINED, 0),
TransitionToPresent(swapchain2.GetImages()[image_index2], VK_IMAGE_LAYOUT_UNDEFINED, 0),
};
m_command_buffer.Begin();
vk::CmdPipelineBarrier(m_command_buffer.handle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
0u, nullptr, 0u, nullptr, 2u, present_transitions);
m_command_buffer.End();

VkSemaphore acquire_semaphores[] = {image_acquired1.handle(), image_acquired2.handle()};
VkPipelineStageFlags wait_masks[] = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};

vkt::Semaphore semaphore(*m_device);

VkSubmitInfo submit_info = vku::InitStructHelper();
submit_info.waitSemaphoreCount = 2u;
submit_info.pWaitSemaphores = acquire_semaphores;
submit_info.pWaitDstStageMask = wait_masks;
submit_info.commandBufferCount = 1u;
submit_info.pCommandBuffers = &m_command_buffer.handle();
submit_info.signalSemaphoreCount = 1u;
submit_info.pSignalSemaphores = &semaphore.handle();
vk::QueueSubmit(m_default_queue->handle(), 1u, &submit_info, VK_NULL_HANDLE);

VkSwapchainKHR swapchains[] = {swapchain1.handle(), swapchain2.handle()};
uint32_t image_indices[] = {image_index1, image_index2};

VkPresentInfoKHR present = vku::InitStructHelper();
present.waitSemaphoreCount = 1u;
present.pWaitSemaphores = &semaphore.handle();
present.pSwapchains = swapchains;
present.pImageIndices = image_indices;
present.swapchainCount = 2;
m_errorMonitor->SetDesiredError("VUID-VkPresentInfoKHR-pSwapchains-09199");
vk::QueuePresentKHR(m_default_queue->handle(), &present);
m_errorMonitor->VerifyFound();
vk::DeviceWaitIdle(device());
}

TEST_F(NegativeWsi, ReleaseSwapchainImagesWithoutFeature) {
TEST_DESCRIPTION("Submit VkPresentInfo where one swapchain has VkSwapchainPresentModesCreateInfoEXT and the other does not");

AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
AddSurfaceExtension();
RETURN_IF_SKIP(Init());
RETURN_IF_SKIP(InitSwapchain());

vkt::Semaphore acquire_semaphore(*m_device);
const uint32_t image_index = m_swapchain.AcquireNextImage(acquire_semaphore, kWaitTimeout);

VkReleaseSwapchainImagesInfoEXT release_info = vku::InitStructHelper();
release_info.swapchain = m_swapchain.handle();
release_info.imageIndexCount = 1u;
release_info.pImageIndices = &image_index;

m_errorMonitor->SetDesiredError("VUID-vkReleaseSwapchainImagesEXT-swapchainMaintenance1-10159");
vk::ReleaseSwapchainImagesEXT(device(), &release_info);
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeWsi, SwapchainCreateMissingMaintenanc1Feature) {
TEST_DESCRIPTION("Submit VkPresentInfo where one swapchain has VkSwapchainPresentModesCreateInfoEXT and the other does not");

AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
AddSurfaceExtension();
RETURN_IF_SKIP(Init());
RETURN_IF_SKIP(InitSurface());
InitSwapchainInfo();

VkSwapchainPresentModesCreateInfoEXT present_modes_create_info = vku::InitStructHelper();
present_modes_create_info.presentModeCount = 1u;
present_modes_create_info.pPresentModes = &m_surface_non_shared_present_mode;

VkSwapchainCreateInfoKHR swapchain_ci = vku::InitStructHelper(&present_modes_create_info);
swapchain_ci.surface = m_surface.Handle();
swapchain_ci.minImageCount = m_surface_capabilities.minImageCount;
swapchain_ci.imageFormat = m_surface_formats[0].format;
swapchain_ci.imageColorSpace = m_surface_formats[0].colorSpace;
swapchain_ci.imageExtent = {m_surface_capabilities.minImageExtent.width, m_surface_capabilities.minImageExtent.height};
swapchain_ci.imageArrayLayers = 1u;
swapchain_ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchain_ci.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
swapchain_ci.compositeAlpha = m_surface_composite_alpha;
swapchain_ci.presentMode = m_surface_non_shared_present_mode;
swapchain_ci.clipped = VK_FALSE;
swapchain_ci.oldSwapchain = 0u;

m_errorMonitor->SetDesiredError("VUID-VkSwapchainCreateInfoKHR-swapchainMaintenance1-10155");
m_swapchain.Init(*m_device, swapchain_ci);
m_errorMonitor->VerifyFound();

VkSwapchainPresentScalingCreateInfoEXT present_scaling_ci = vku::InitStructHelper();
present_scaling_ci.scalingBehavior = VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT;
swapchain_ci.pNext = &present_scaling_ci;
m_errorMonitor->SetDesiredError("VUID-VkSwapchainPresentScalingCreateInfoEXT-swapchainMaintenance1-10154");
m_swapchain.Init(*m_device, swapchain_ci);
m_errorMonitor->VerifyFound();

swapchain_ci.pNext = nullptr;
swapchain_ci.flags = VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT;
m_errorMonitor->SetDesiredError("VUID-VkSwapchainCreateInfoKHR-swapchainMaintenance1-10157");
m_swapchain.Init(*m_device, swapchain_ci);
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeWsi, ImageCompressionPropertiesSwapchainWithoutFeature) {
TEST_DESCRIPTION("Use image compression control swapchain pNext without feature enabled");

Expand Down
3 changes: 3 additions & 0 deletions tests/unit/wsi_positive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,7 @@ TEST_F(PositiveWsi, CreateSwapchainWithPresentModeInfo) {

AddSurfaceExtension();
AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::swapchainMaintenance1);
RETURN_IF_SKIP(Init());
RETURN_IF_SKIP(InitSurface());
InitSwapchainInfo();
Expand Down Expand Up @@ -1349,6 +1350,7 @@ TEST_F(PositiveWsi, PresentFenceWaitsForSubmission) {
AddSurfaceExtension();
AddRequiredExtensions(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::swapchainMaintenance1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PresentFenceRetiresPresentQueueOperation also needs this

RETURN_IF_SKIP(Init());
RETURN_IF_SKIP(InitSwapchain());

Expand Down Expand Up @@ -1422,6 +1424,7 @@ TEST_F(PositiveWsi, PresentFenceRetiresPresentQueueOperation) {
AddSurfaceExtension();
AddRequiredExtensions(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::swapchainMaintenance1);
RETURN_IF_SKIP(Init());
RETURN_IF_SKIP(InitSwapchain());

Expand Down
Loading