Test VIEW_INDEX_FROM_DEVICE_INDEX_BIT with GPL
Add testing of VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT
with graphics pipeline libraries where this flag is set for both
pre-rasterization and fragment pipelines.
VK-GL-CTS issue: 4591
Components: Vulkan
Affects:
dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.*
Change-Id: I80ccdbeab46103c3ed28fb71a55be2cf96a008e1
diff --git a/android/cts/main/vk-main-2024-03-01/pipeline/pipeline-library.txt b/android/cts/main/vk-main-2024-03-01/pipeline/pipeline-library.txt
index 2e5330c..565a2bf 100644
--- a/android/cts/main/vk-main-2024-03-01/pipeline/pipeline-library.txt
+++ b/android/cts/main/vk-main-2024-03-01/pipeline/pipeline-library.txt
@@ -10428,6 +10428,8 @@
dEQP-VK.pipeline.pipeline_library.graphics_library.fast.maintenance5
dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.common_frag_pipeline_library
dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.null_rendering_create_info
+dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.view_index_from_device_index_in_all_stages
+dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.view_index_from_device_index_in_mesh_stages
dEQP-VK.pipeline.pipeline_library.image_2d_view_3d_image.fragment.combined_image_sampler.mip0_layer0_sparse
dEQP-VK.pipeline.pipeline_library.image_2d_view_3d_image.fragment.combined_image_sampler.mip0_layer63_sparse
dEQP-VK.pipeline.pipeline_library.image_2d_view_3d_image.fragment.combined_image_sampler.mip2_layer0_sparse
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineLibraryTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineLibraryTests.cpp
index 5fb2e86..c306bf0 100644
--- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineLibraryTests.cpp
+++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineLibraryTests.cpp
@@ -39,6 +39,7 @@
#include "vkRayTracingUtil.hpp"
#include "vktTestCase.hpp"
#include "vktTestGroupUtil.hpp"
+#include "vktCustomInstancesDevices.hpp"
#include "tcuCommandLine.hpp"
#include "tcuImageCompare.hpp"
#include "tcuTestLog.hpp"
@@ -1347,6 +1348,8 @@
SHADER_MODULE_CREATE_INFO_RT_LIB,
NULL_RENDERING_CREATE_INFO,
COMMON_FRAG_LIBRARY,
+ VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES,
+ VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES,
};
struct MiscTestParams
@@ -2905,9 +2908,7 @@
NullRenderingCreateInfoInstance(Context &context) : vkt::TestInstance(context)
{
}
- virtual ~NullRenderingCreateInfoInstance(void)
- {
- }
+ virtual ~NullRenderingCreateInfoInstance(void) = default;
tcu::TestStatus iterate(void) override;
};
@@ -3165,6 +3166,399 @@
return tcu::TestStatus::pass("Pass");
}
+class CreateViewIndexFromDeviceIndexInstance : public vkt::TestInstance
+{
+public:
+ CreateViewIndexFromDeviceIndexInstance(Context &context, const MiscTestParams ¶ms);
+ virtual ~CreateViewIndexFromDeviceIndexInstance(void) = default;
+
+ tcu::TestStatus iterate(void) override;
+
+protected:
+ bool createDeviceGroup(void);
+
+private:
+ MiscTestParams m_testParams;
+
+ uint32_t m_deviceGroupQueueFamilyIndex;
+ CustomInstance m_deviceGroupInstance;
+ vk::Move<vk::VkDevice> m_deviceGroupLogicalDevice;
+ std::vector<vk::VkPhysicalDevice> m_deviceGroupPhysicalDevices;
+ de::MovePtr<vk::DeviceDriver> m_deviceGroupVk;
+ de::MovePtr<Allocator> m_deviceGroupAllocator;
+};
+
+CreateViewIndexFromDeviceIndexInstance::CreateViewIndexFromDeviceIndexInstance(Context &context,
+ const MiscTestParams ¶ms)
+ : vkt::TestInstance(context)
+ , m_testParams(params)
+{
+}
+
+tcu::TestStatus CreateViewIndexFromDeviceIndexInstance::iterate()
+{
+ const bool useDeviceGroup = createDeviceGroup();
+ const auto &vk = useDeviceGroup ? *m_deviceGroupVk : m_context.getDeviceInterface();
+ const auto device = useDeviceGroup ? *m_deviceGroupLogicalDevice : m_context.getDevice();
+ Allocator &allocator = useDeviceGroup ? *m_deviceGroupAllocator : m_context.getDefaultAllocator();
+ uint32_t queueFamilyIndex =
+ useDeviceGroup ? m_deviceGroupQueueFamilyIndex : m_context.getUniversalQueueFamilyIndex();
+ const auto deviceCount = useDeviceGroup ? m_deviceGroupPhysicalDevices.size() : 1u;
+ const auto viewCount = 3u;
+ const auto imageSize = 8u;
+ const auto colorFormat = VK_FORMAT_R8G8B8A8_UINT;
+ const auto extent = makeExtent3D(imageSize, imageSize, 1u);
+
+ bool useMeshShader = (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES);
+ VkPipelineCreateFlags preRasterPipelineFlags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
+ VkPipelineCreateFlags fragmentPipelineFlags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
+ preRasterPipelineFlags |= VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT;
+ fragmentPipelineFlags |= VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT;
+
+ // fill structures that are needed for pipeline creation
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = initVulkanStructure();
+ VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo = initVulkanStructure();
+ inputAssemblyStateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = initVulkanStructure();
+
+ const auto viewport = makeViewport(extent);
+ const auto scissor = makeRect2D(extent);
+ VkPipelineViewportStateCreateInfo viewportStateInfo = initVulkanStructure();
+ viewportStateInfo.viewportCount = 1u;
+ viewportStateInfo.pViewports = &viewport;
+ viewportStateInfo.scissorCount = 1u;
+ viewportStateInfo.pScissors = &scissor;
+
+ VkPipelineMultisampleStateCreateInfo multisampleStateInfo = initVulkanStructure();
+ multisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
+
+ VkPipelineColorBlendAttachmentState colorBlendAttachmentState;
+ deMemset(&colorBlendAttachmentState, 0x00, sizeof(VkPipelineColorBlendAttachmentState));
+ colorBlendAttachmentState.colorWriteMask = 0xFu;
+ VkPipelineColorBlendAttachmentState colorBlendAttachmentStates[viewCount];
+ std::fill(colorBlendAttachmentStates, colorBlendAttachmentStates + viewCount, colorBlendAttachmentState);
+
+ VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = initVulkanStructure();
+ colorBlendStateInfo.attachmentCount = 1;
+ colorBlendStateInfo.pAttachments = colorBlendAttachmentStates;
+
+ VkPipelineTessellationStateCreateInfo tessellationStateInfo = initVulkanStructure();
+ tessellationStateInfo.patchControlPoints = 3u;
+
+ // create color attachment with required number of layers
+ const auto imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, viewCount);
+ const VkImageUsageFlags imageUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ ImageWithBuffer imageWithBuffer(vk, device, allocator, extent, colorFormat, imageUsage, VK_IMAGE_TYPE_2D,
+ imageSubresourceRange, viewCount);
+ Move<VkImageView> imageView = makeImageView(vk, device, imageWithBuffer.getImage(), VK_IMAGE_VIEW_TYPE_2D_ARRAY,
+ colorFormat, imageSubresourceRange);
+
+ const auto &multiviewFeatures(m_context.getMultiviewFeatures());
+ const auto srl(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, viewCount));
+ const auto copyRegion(makeBufferImageCopy(extent, srl));
+ const auto beforeCopyBarrier(makeMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT));
+ const auto clearValue(makeClearValueColor(tcu::Vec4(0.0f)));
+
+ const auto pipelineLayout(makePipelineLayout(vk, device));
+ auto &bc(m_context.getBinaryCollection());
+ uint32_t preRasterShaderStages = 1;
+ Move<VkShaderModule> preRasterModules[4];
+ VkPipelineShaderStageCreateInfo preRasterShaderInfos[4];
+
+ if (useMeshShader)
+ {
+ preRasterModules[0] = createShaderModule(vk, device, bc.get("mesh"));
+ preRasterShaderInfos[0] = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_MESH_BIT_EXT, *preRasterModules[0]);
+ }
+ else
+ {
+ std::string moduleNames[4]{"vert", "tesc", "tese", "geom"};
+ VkShaderStageFlagBits shaderStages[4]{VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
+ VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
+ VK_SHADER_STAGE_GEOMETRY_BIT};
+
+ if (multiviewFeatures.multiviewTessellationShader)
+ {
+ inputAssemblyStateInfo.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
+ preRasterShaderStages += 2;
+ }
+
+ if (multiviewFeatures.multiviewGeometryShader)
+ {
+ moduleNames[preRasterShaderStages] = "geom";
+ shaderStages[preRasterShaderStages] = VK_SHADER_STAGE_GEOMETRY_BIT;
+ ++preRasterShaderStages;
+ }
+
+ for (uint32_t i = 0u; i < preRasterShaderStages; ++i)
+ {
+ preRasterModules[i] = createShaderModule(vk, device, bc.get(moduleNames[i]));
+ preRasterShaderInfos[i] = makePipelineShaderStageCreateInfo(shaderStages[i], *preRasterModules[i]);
+ }
+ }
+ const auto fragModule(createShaderModule(vk, device, bc.get("frag")));
+ const auto fragShaderInfo(makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, *fragModule));
+
+ // create renderpass and framebuffer
+ uint32_t viewMask = 0u;
+ uint32_t correlationMask = 0u;
+ for (uint32_t i = 0u; i < viewCount; ++i)
+ {
+ viewMask |= (1 << i);
+ correlationMask |= (1 << i);
+ }
+ VkRenderPassMultiviewCreateInfo multiviewInfo = initVulkanStructure();
+ multiviewInfo.subpassCount = 1u;
+ multiviewInfo.pViewMasks = &viewMask;
+ multiviewInfo.correlationMaskCount = 1u;
+ multiviewInfo.pCorrelationMasks = &correlationMask;
+
+ auto renderPass = makeRenderPass(
+ vk, device, colorFormat, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 0, &multiviewInfo);
+
+ const auto framebufferCreateInfo = makeFramebufferCreateInfo(*renderPass, 1u, &*imageView, imageSize, imageSize);
+ auto framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
+
+ // create pre-raster pipeline part
+ VkGraphicsPipelineLibraryCreateInfoEXT preRasterLibraryInfo = initVulkanStructure();
+ preRasterLibraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
+ VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
+ VkGraphicsPipelineCreateInfo preRasterPipelineInfo = initVulkanStructure(&preRasterLibraryInfo);
+ preRasterPipelineInfo.flags = preRasterPipelineFlags;
+ preRasterPipelineInfo.layout = *pipelineLayout;
+ preRasterPipelineInfo.renderPass = *renderPass;
+ preRasterPipelineInfo.pVertexInputState = &vertexInputStateInfo;
+ preRasterPipelineInfo.pInputAssemblyState = &inputAssemblyStateInfo;
+ preRasterPipelineInfo.pViewportState = &viewportStateInfo;
+ preRasterPipelineInfo.pRasterizationState = &rasterizationStateInfo;
+ preRasterPipelineInfo.pTessellationState = &tessellationStateInfo;
+ preRasterPipelineInfo.stageCount = preRasterShaderStages;
+ preRasterPipelineInfo.pStages = preRasterShaderInfos;
+ auto preRasterPipelinePart = createGraphicsPipeline(vk, device, DE_NULL, &preRasterPipelineInfo);
+
+ // create fragment pipeline part
+ VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo = initVulkanStructure();
+ fragShaderLibInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT |
+ VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
+ VkGraphicsPipelineCreateInfo fragmentPipelineInfo = initVulkanStructure(&fragShaderLibInfo);
+ fragmentPipelineInfo.flags = fragmentPipelineFlags;
+ fragmentPipelineInfo.layout = pipelineLayout.get();
+ fragmentPipelineInfo.renderPass = *renderPass;
+ fragmentPipelineInfo.pMultisampleState = &multisampleStateInfo;
+ fragmentPipelineInfo.pDepthStencilState = &depthStencilStateInfo;
+ fragmentPipelineInfo.pColorBlendState = &colorBlendStateInfo;
+ fragmentPipelineInfo.stageCount = 1u;
+ fragmentPipelineInfo.pStages = &fragShaderInfo;
+ auto fragmentPipelinePart = createGraphicsPipeline(vk, device, DE_NULL, &fragmentPipelineInfo);
+
+ // merge pipelines
+ const VkPipeline libraryHandles[]{
+ *preRasterPipelinePart,
+ *fragmentPipelinePart,
+ };
+ VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
+ linkedPipelineLibraryInfo.libraryCount = 2u;
+ linkedPipelineLibraryInfo.pLibraries = libraryHandles;
+ VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo);
+ linkedPipelineInfo.layout = *pipelineLayout;
+ const auto pipeline = createGraphicsPipeline(vk, device, DE_NULL, &linkedPipelineInfo);
+
+ const auto cmdPool(
+ createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
+ const auto cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+ // render triangle that covers whole color attachments
+ beginCommandBuffer(vk, *cmdBuffer);
+
+ beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, scissor, 1, &clearValue);
+ vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
+
+ if (useMeshShader)
+ vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1u, 1u, 1u);
+ else
+ vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
+
+ endRenderPass(vk, *cmdBuffer);
+
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1,
+ &beforeCopyBarrier, 0, 0, 0, 0);
+
+ vk.cmdCopyImageToBuffer(*cmdBuffer, imageWithBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ imageWithBuffer.getBuffer(), 1u, ©Region);
+
+ endCommandBuffer(vk, *cmdBuffer);
+ const VkQueue queue = getDeviceQueue(vk, device, queueFamilyIndex, 0);
+ submitCommandsAndWait(vk, device, queue, *cmdBuffer);
+
+ const auto &bufferAllocation = imageWithBuffer.getBufferAllocation();
+ invalidateAlloc(vk, device, bufferAllocation);
+
+ bool resurtIsCorrect = true;
+ const auto fragmentCount = imageSize * imageSize;
+ const auto componentCount = 4u;
+ std::vector<uint8_t> allowedValueSets(deviceCount * componentCount, 0);
+
+ for (uint8_t v = 0; v < static_cast<uint8_t>(viewCount); ++v)
+ {
+ // calculate allowed set of result values
+ for (uint8_t d = 0; d < static_cast<uint8_t>(deviceCount); ++d)
+ {
+ uint8_t *allowedValuesPtr = allowedValueSets.data() + d * componentCount;
+ allowedValuesPtr[0] = d;
+ allowedValuesPtr[1] = static_cast<uint8_t>(d + d);
+ allowedValuesPtr[2] = d;
+ allowedValuesPtr[3] = d;
+
+ // ignore tesselation and/or geometry stages when those features are not available
+ if (!multiviewFeatures.multiviewTessellationShader || useMeshShader)
+ allowedValuesPtr[1] = 0;
+ if (!multiviewFeatures.multiviewGeometryShader || useMeshShader)
+ allowedValuesPtr[2] = 0;
+ }
+
+ uint8_t *bufferPtr = static_cast<uint8_t *>(bufferAllocation.getHostPtr()) + v * fragmentCount * componentCount;
+ for (uint32_t f = 0; f < fragmentCount; ++f)
+ {
+ uint8_t *fragmentColor = bufferPtr + f * componentCount;
+ resurtIsCorrect = false;
+
+ // compare with all accepted values (if device group is used each device will produce different result)
+ for (uint8_t d = 0; d < static_cast<uint8_t>(deviceCount); ++d)
+ {
+ uint8_t *allowedValuesPtr = allowedValueSets.data() + d * componentCount;
+ resurtIsCorrect = (deMemCmp(fragmentColor, allowedValuesPtr, componentCount) == 0);
+
+ // when fragment is corret we can skip checking other allowed values
+ if (resurtIsCorrect)
+ break;
+ }
+
+ // when fragment is not corret we can skip checking other fragments
+ if (!resurtIsCorrect)
+ break;
+ }
+
+ // when fragment was not corret we can skip checking other views
+ if (!resurtIsCorrect)
+ break;
+ }
+
+ if (resurtIsCorrect)
+ return tcu::TestStatus::pass("Pass");
+
+ // log images
+ auto &log = m_context.getTestContext().getLog();
+ log << tcu::TestLog::ImageSet("Result", "");
+ for (uint32_t v = 0; v < viewCount; ++v)
+ {
+ uint8_t *bufferPtr = static_cast<uint8_t *>(bufferAllocation.getHostPtr()) + v * fragmentCount * componentCount;
+ tcu::PixelBufferAccess resultAccess(mapVkFormat(colorFormat), imageSize, imageSize, 1, bufferPtr);
+ log << tcu::TestLog::Image(std::to_string(v), "", resultAccess);
+ }
+ log << tcu::TestLog::EndImageSet;
+
+ return tcu::TestStatus::fail("Fail");
+}
+
+bool CreateViewIndexFromDeviceIndexInstance::createDeviceGroup(void)
+{
+ const auto &vki = m_context.getInstanceInterface();
+ const tcu::CommandLine &cmdLine = m_context.getTestContext().getCommandLine();
+ const uint32_t deviceGroupIndex = cmdLine.getVKDeviceGroupId() - 1;
+ const float queuePriority = 1.0f;
+
+ // create vulkan instance, list all device groups and select proper one
+ m_deviceGroupInstance = createCustomInstanceWithExtension(m_context, "VK_KHR_device_group_creation");
+ auto allDeviceGroupProperties = enumeratePhysicalDeviceGroups(vki, m_deviceGroupInstance);
+ auto &devGroupProperties = allDeviceGroupProperties[deviceGroupIndex];
+ if (devGroupProperties.physicalDeviceCount == 1)
+ return false;
+
+ const InstanceDriver &instance(m_deviceGroupInstance.getDriver());
+ VkPhysicalDeviceFeatures2 deviceFeatures2 = initVulkanStructure();
+ VkDeviceGroupDeviceCreateInfo deviceGroupInfo = initVulkanStructure(&deviceFeatures2);
+ deviceGroupInfo.physicalDeviceCount = devGroupProperties.physicalDeviceCount;
+ deviceGroupInfo.pPhysicalDevices = devGroupProperties.physicalDevices;
+
+ uint32_t physicalDeviceIndex = cmdLine.getVKDeviceId() - 1;
+ if (physicalDeviceIndex >= deviceGroupInfo.physicalDeviceCount)
+ physicalDeviceIndex = 0;
+
+ const VkPhysicalDeviceFeatures deviceFeatures =
+ getPhysicalDeviceFeatures(instance, deviceGroupInfo.pPhysicalDevices[physicalDeviceIndex]);
+ deviceFeatures2.features = deviceFeatures;
+ const std::vector<VkQueueFamilyProperties> queueProps =
+ getPhysicalDeviceQueueFamilyProperties(instance, devGroupProperties.physicalDevices[physicalDeviceIndex]);
+
+ VkPhysicalDeviceMultiviewFeatures multiviewFeatures = m_context.getMultiviewFeatures();
+ VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT gplFeatures = m_context.getGraphicsPipelineLibraryFeaturesEXT();
+ VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures = m_context.getMeshShaderFeaturesEXT();
+
+ std::vector<const char *> deviceExtensions{"VK_KHR_pipeline_library", "VK_EXT_graphics_pipeline_library",
+ "VK_KHR_multiview"};
+ if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_device_group"))
+ deviceExtensions.push_back("VK_KHR_device_group");
+
+ meshShaderFeatures.pNext = nullptr;
+ multiviewFeatures.pNext = nullptr;
+ gplFeatures.pNext = &multiviewFeatures;
+ if (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES)
+ {
+ deviceExtensions.push_back("VK_EXT_mesh_shader");
+ multiviewFeatures.pNext = &meshShaderFeatures;
+ }
+ deviceFeatures2.pNext = &gplFeatures;
+
+ m_deviceGroupPhysicalDevices.resize(devGroupProperties.physicalDeviceCount);
+ for (uint32_t pd = 0; pd < devGroupProperties.physicalDeviceCount; pd++)
+ m_deviceGroupPhysicalDevices[pd] = devGroupProperties.physicalDevices[pd];
+
+ for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
+ {
+ if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
+ m_deviceGroupQueueFamilyIndex = (uint32_t)queueNdx;
+ }
+
+ VkDeviceQueueCreateInfo queueInfo{
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags;
+ m_deviceGroupQueueFamilyIndex, // uint32_t queueFamilyIndex;
+ 1u, // uint32_t queueCount;
+ &queuePriority // const float* pQueuePriorities;
+ };
+
+ const VkDeviceCreateInfo deviceInfo{
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
+ &deviceGroupInfo, // const void* pNext;
+ (VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
+ 1u, // uint32_t queueCreateInfoCount;
+ &queueInfo, // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
+ 0u, // uint32_t enabledLayerCount;
+ DE_NULL, // const char* const* ppEnabledLayerNames;
+ uint32_t(deviceExtensions.size()), // uint32_t enabledExtensionCount;
+ deviceExtensions.data(), // const char* const* ppEnabledExtensionNames;
+ DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
+ };
+
+ m_deviceGroupLogicalDevice = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(),
+ m_context.getPlatformInterface(), m_deviceGroupInstance, instance,
+ deviceGroupInfo.pPhysicalDevices[physicalDeviceIndex], &deviceInfo);
+
+ m_deviceGroupVk = de::MovePtr<DeviceDriver>(
+ new DeviceDriver(m_context.getPlatformInterface(), m_deviceGroupInstance, *m_deviceGroupLogicalDevice,
+ m_context.getUsedApiVersion(), m_context.getTestContext().getCommandLine()));
+
+ m_deviceGroupAllocator = de::MovePtr<Allocator>(
+ new SimpleAllocator(*m_deviceGroupVk, *m_deviceGroupLogicalDevice,
+ getPhysicalDeviceMemoryProperties(instance, m_deviceGroupPhysicalDevices[0])));
+
+ return true;
+}
+
class PipelineLibraryMiscTestCase : public TestCase
{
public:
@@ -3218,6 +3612,17 @@
((numClipDistances + numCullDistances) > limits.maxCombinedClipAndCullDistances))
TCU_THROW(NotSupportedError, "Specified values of clip or cull distances are not supported");
}
+
+ if (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES)
+ context.requireDeviceFunctionality("VK_KHR_multiview");
+ else if (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES)
+ {
+ context.requireDeviceFunctionality("VK_KHR_multiview");
+ context.requireDeviceFunctionality("VK_EXT_mesh_shader");
+ const auto &meshShaderFeatures = context.getMeshShaderFeaturesEXT();
+ if (!meshShaderFeatures.multiviewMeshShader)
+ TCU_THROW(NotSupportedError, "multiviewMeshShader not supported");
+ }
}
void PipelineLibraryMiscTestCase::initPrograms(SourceCollections &programCollection) const
@@ -3535,6 +3940,117 @@
}
programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
}
+ else if (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES)
+ {
+ std::string vert("#version 460\n"
+ "#extension GL_EXT_multiview : require\n"
+ "layout(location = 0) flat out uvec4 vViewIndex;"
+ "void main() {\n"
+ " const float x = -1.0 + 4.0 * ((gl_VertexIndex & 2)>>1);\n"
+ " const float y = -1.0 + 4.0 * (gl_VertexIndex % 2);\n"
+ " gl_Position = vec4(x, y, 0.0, 1.0);\n"
+ " vViewIndex = uvec4(0);\n"
+ " vViewIndex.x = gl_ViewIndex;\n"
+ "}\n");
+ programCollection.glslSources.add("vert") << glu::VertexSource(vert);
+
+ std::string tesc("#version 450\n"
+ "#extension GL_EXT_multiview : require\n"
+ "layout (vertices = 3) out;\n"
+ "layout(location = 0) flat in uvec4 vViewIndex[];\n"
+ "layout(location = 0) flat out uvec4 vtcViewIndex[];\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_TessLevelInner[0] = 1.0;\n"
+ " gl_TessLevelInner[1] = 1.0;\n"
+ " gl_TessLevelOuter[0] = 1.0;\n"
+ " gl_TessLevelOuter[1] = 1.0;\n"
+ " gl_TessLevelOuter[2] = 1.0;\n"
+ " gl_TessLevelOuter[3] = 1.0;\n"
+ " vtcViewIndex[gl_InvocationID] = vViewIndex[gl_InvocationID];\n"
+ " vtcViewIndex[gl_InvocationID].y = gl_ViewIndex;\n"
+ " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ "}\n");
+ programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc);
+
+ std::string tese("#version 450\n"
+ "#extension GL_EXT_multiview : require\n"
+ "layout(triangles, fractional_odd_spacing, cw) in;\n"
+ "layout(location = 0) flat in uvec4 vtcViewIndex[];\n"
+ "layout(location = 0) flat out uvec4 vtViewIndex;\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
+ " (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
+ " (gl_TessCoord.z * gl_in[2].gl_Position);\n"
+ " vtViewIndex = vtcViewIndex[0];\n"
+ " vtViewIndex.y += gl_ViewIndex;\n"
+ "}\n");
+ programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese);
+
+ std::string geom("#version 450\n"
+ "#extension GL_EXT_multiview : require\n"
+ "layout (triangles) in;\n"
+ "layout (triangle_strip, max_vertices=3) out;\n"
+ "layout(location = 0) flat in uvec4 vtViewIndex[];\n"
+ "layout(location = 0) flat out uvec4 vtgViewIndex;\n"
+ "void main (void)\n"
+ "{\n"
+ " for (int i = 0; i < 3; i++)\n"
+ " {\n"
+ " gl_Position = gl_in[i].gl_Position;\n"
+ " vtgViewIndex = vtViewIndex[i];\n"
+ " vtgViewIndex.z = gl_ViewIndex;\n"
+ " EmitVertex();\n"
+ " }\n"
+ "}\n");
+ programCollection.glslSources.add("geom") << glu::GeometrySource(geom);
+
+ std::string frag("#version 460\n"
+ "#extension GL_EXT_multiview : require\n"
+ "layout(location = 0) flat in uvec4 vtgViewIndex;\n"
+ "layout (location=0) out uvec4 color;\n"
+ "void main () {\n"
+ " color = vtgViewIndex;\n"
+ " color.a = gl_ViewIndex;\n"
+ "}\n");
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
+ }
+ else if (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES)
+ {
+ const auto buildOptions =
+ vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
+
+ std::string mesh("#version 450\n"
+ "#extension GL_EXT_mesh_shader : enable\n"
+ "#extension GL_EXT_multiview : require\n"
+ "layout(local_size_x=3) in;\n"
+ "layout(triangles) out;\n"
+ "layout(max_vertices=3, max_primitives=1) out;\n"
+ "layout(location = 0) perprimitiveEXT flat out uvec4 mViewIndex[];\n"
+ "void main() {\n"
+ " SetMeshOutputsEXT(3u, 1u);\n"
+ " const uint idx = gl_LocalInvocationIndex;\n"
+ " const float x = -1.0 + 4.0 * ((idx & 2)>>1);\n"
+ " const float y = -1.0 + 4.0 * (idx % 2);\n"
+ " gl_MeshVerticesEXT[idx].gl_Position = vec4(x, y, 0.0, 1.0);\n"
+ " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
+ " mViewIndex[idx] = uvec4(0);\n"
+ " mViewIndex[idx].x = gl_ViewIndex;\n"
+ "}\n");
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh) << buildOptions;
+
+ std::string frag("#version 460\n"
+ "#extension GL_EXT_multiview : require\n"
+ "#extension GL_EXT_mesh_shader : enable\n"
+ "layout(location = 0) perprimitiveEXT flat in uvec4 mViewIndex;\n"
+ "layout (location=0) out uvec4 color;\n"
+ "void main () {\n"
+ " color = mViewIndex;\n"
+ " color.a = gl_ViewIndex;\n"
+ "}\n");
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag) << buildOptions;
+ }
else
{
DE_ASSERT(false);
@@ -3555,6 +4071,10 @@
if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
return new NullRenderingCreateInfoInstance(context);
+ if ((m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES) ||
+ (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES))
+ return new CreateViewIndexFromDeviceIndexInstance(context, m_testParams);
+
return new PipelineLibraryMiscTestInstance(context, m_testParams);
}
@@ -3767,6 +4287,14 @@
{MiscTestMode::NULL_RENDERING_CREATE_INFO, 0u, 0u}));
otherTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "common_frag_pipeline_library",
{MiscTestMode::COMMON_FRAG_LIBRARY, 0u, 0u}));
+
+ otherTests->addChild(
+ new PipelineLibraryMiscTestCase(testCtx, "view_index_from_device_index_in_all_stages",
+ {MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES, 0u, 0u}));
+ otherTests->addChild(
+ new PipelineLibraryMiscTestCase(testCtx, "view_index_from_device_index_in_mesh_stages",
+ {MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES, 0u, 0u}));
+
miscTests->addChild(otherTests.release());
}
diff --git a/external/vulkancts/mustpass/main/vk-default/pipeline/pipeline-library.txt b/external/vulkancts/mustpass/main/vk-default/pipeline/pipeline-library.txt
index c69a788..63169ee 100644
--- a/external/vulkancts/mustpass/main/vk-default/pipeline/pipeline-library.txt
+++ b/external/vulkancts/mustpass/main/vk-default/pipeline/pipeline-library.txt
@@ -35162,6 +35162,8 @@
dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.compare_link_times
dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.null_descriptor_set_in_monolithic_pipeline
dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.null_rendering_create_info
+dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.view_index_from_device_index_in_all_stages
+dEQP-VK.pipeline.pipeline_library.graphics_library.misc.other.view_index_from_device_index_in_mesh_stages
dEQP-VK.pipeline.pipeline_library.graphics_library.optimize.0_00_11_11
dEQP-VK.pipeline.pipeline_library.graphics_library.optimize.0_01_11_1
dEQP-VK.pipeline.pipeline_library.graphics_library.optimize.0_1111