| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2017-2020 The Khronos Group Inc. |
| * Copyright (c) 2020 AMD |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Tests for VK_KHR_fragment_shading_rate |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktFragmentShadingRatePixelConsistency.hpp" |
| |
| #include "vkBufferWithMemory.hpp" |
| #include "vkImageWithMemory.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkBuilderUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkObjUtil.hpp" |
| #include "vkImageUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkPlatform.hpp" |
| |
| #include "vktTestGroupUtil.hpp" |
| #include "vktTestCase.hpp" |
| #include "vktCustomInstancesDevices.hpp" |
| |
| #include "deDefs.h" |
| #include "deMath.h" |
| #include "deRandom.h" |
| #include "deSharedPtr.hpp" |
| #include "deString.h" |
| |
| #include "tcuTestCase.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuCommandLine.hpp" |
| |
| #include <limits> |
| #include <string> |
| #include <sstream> |
| |
| namespace vkt |
| { |
| namespace FragmentShadingRate |
| { |
| namespace |
| { |
| using namespace vk; |
| using namespace std; |
| |
| struct CaseDef |
| { |
| VkExtent2D shadingRate; |
| VkSampleCountFlagBits samples; |
| VkExtent2D framebufferExtent; |
| bool zwCoord; |
| }; |
| |
| struct Vertex |
| { |
| float x; |
| float y; |
| }; |
| |
| Vertex basicTriangles[6] = |
| { |
| {-1.0f, -1.0f}, |
| { 1.0f, -1.0f}, |
| { 1.0f, 1.0f}, |
| |
| {-1.0f, 1.0f}, |
| { 1.0f, -1.0f}, |
| { 1.0f, 1.0f}, |
| }; |
| |
| Move<VkDevice> createImageRobustnessDevice(Context& context) |
| { |
| const InstanceInterface& instance = context.getInstanceInterface(); |
| const vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); |
| const float queuePriority = 1.0f; |
| |
| // Create a universal queue |
| const VkDeviceQueueCreateInfo queueParams = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkDeviceQueueCreateFlags flags; |
| context.getUniversalQueueFamilyIndex(), // deUint32 queueFamilyIndex; |
| 1u, // deUint32 queueCount; |
| &queuePriority // const float* pQueuePriorities; |
| }; |
| |
| // Add image robustness extension if supported |
| std::vector<const char*> deviceExtensions; |
| |
| deviceExtensions.push_back("VK_KHR_fragment_shading_rate"); |
| |
| if (context.isDeviceFunctionalitySupported("VK_EXT_image_robustness")) |
| { |
| deviceExtensions.push_back("VK_EXT_image_robustness"); |
| } |
| |
| VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsrFeatures = |
| { |
| VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, // VkStructureType sType; |
| DE_NULL, // void* pNext; |
| DE_FALSE, // VkBool32 pipelineFragmentShadingRate; |
| DE_FALSE, // VkBool32 primitiveFragmentShadingRate; |
| DE_FALSE, // VkBool32 attachmentFragmentShadingRate; |
| }; |
| |
| VkPhysicalDeviceFeatures2 enabledFeatures; |
| enabledFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; |
| enabledFeatures.pNext = &fsrFeatures; |
| |
| instance.getPhysicalDeviceFeatures2(physicalDevice, &enabledFeatures); |
| |
| const VkDeviceCreateInfo deviceParams = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType; |
| &enabledFeatures, // const void* pNext; |
| 0u, // VkDeviceCreateFlags flags; |
| 1u, // deUint32 queueCreateInfoCount; |
| &queueParams, // const VkDeviceQueueCreateInfo* pQueueCreateInfos; |
| 0u, // deUint32 enabledLayerCount; |
| DE_NULL, // const char* const* ppEnabledLayerNames; |
| static_cast<deUint32>(deviceExtensions.size()), // deUint32 enabledExtensionCount; |
| deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0], // const char* const* ppEnabledExtensionNames; |
| DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures; |
| }; |
| |
| return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), |
| context.getInstance(), context.getInstanceInterface(), context.getPhysicalDevice(), &deviceParams); |
| } |
| |
| class FSRPixelConsistencyInstance : public TestInstance |
| { |
| public: |
| FSRPixelConsistencyInstance (Context& context, const CaseDef& data); |
| ~FSRPixelConsistencyInstance(void); |
| tcu::TestStatus iterate (void); |
| |
| private: |
| void clampShadingRate(); |
| tcu::TestStatus verifyResult(tcu::ConstPixelBufferAccess& resultBuffer, const deUint32 index); |
| |
| CaseDef m_data; |
| vector<VkExtent2D> m_shadingRateClamped; |
| |
| deUint32 m_supportedFragmentShadingRateCount; |
| vector<VkPhysicalDeviceFragmentShadingRateKHR> m_supportedFragmentShadingRates; |
| }; |
| |
| FSRPixelConsistencyInstance::FSRPixelConsistencyInstance(Context& context, const CaseDef& data) |
| : vkt::TestInstance (context) |
| , m_data(data) |
| , m_supportedFragmentShadingRateCount(0) |
| { |
| // Fetch information about supported fragment shading rates |
| context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, DE_NULL); |
| |
| m_supportedFragmentShadingRates.resize(m_supportedFragmentShadingRateCount); |
| for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i) |
| { |
| m_supportedFragmentShadingRates[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR; |
| m_supportedFragmentShadingRates[i].pNext = nullptr; |
| } |
| context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, &m_supportedFragmentShadingRates[0]); |
| |
| clampShadingRate(); |
| } |
| |
| FSRPixelConsistencyInstance::~FSRPixelConsistencyInstance(void) |
| { |
| } |
| |
| class FSRPixelConsistencyTestCase : public TestCase |
| { |
| public: |
| FSRPixelConsistencyTestCase (tcu::TestContext& context, const char* name, const char* desc, const CaseDef data); |
| ~FSRPixelConsistencyTestCase (void); |
| virtual void initPrograms (SourceCollections& programCollection) const; |
| virtual TestInstance* createInstance (Context& context) const; |
| virtual void checkSupport (Context& context) const; |
| |
| private: |
| |
| CaseDef m_data; |
| }; |
| |
| FSRPixelConsistencyTestCase::FSRPixelConsistencyTestCase(tcu::TestContext& context, const char* name, const char* desc, const CaseDef data) |
| : vkt::TestCase (context, name, desc) |
| , m_data (data) |
| { |
| } |
| |
| FSRPixelConsistencyTestCase::~FSRPixelConsistencyTestCase(void) |
| { |
| } |
| |
| void FSRPixelConsistencyTestCase::checkSupport(Context& context) const |
| { |
| const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | |
| VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate"); |
| |
| if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate) |
| TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported"); |
| |
| VkImageFormatProperties imageProperties; |
| VkResult result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), VK_FORMAT_R32G32_UINT, VK_IMAGE_TYPE_2D, |
| VK_IMAGE_TILING_OPTIMAL, cbUsage , 0, &imageProperties); |
| |
| if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) |
| TCU_THROW(NotSupportedError, "VK_FORMAT_R32G32_UINT not supported"); |
| |
| if (!(imageProperties.sampleCounts & m_data.samples)) |
| TCU_THROW(NotSupportedError, "Image sample count not supported"); |
| |
| if ((imageProperties.maxExtent.width < m_data.framebufferExtent.width) || (imageProperties.maxExtent.height < m_data.framebufferExtent.height)) |
| TCU_THROW(NotSupportedError, "Image max extents are smaller than required"); |
| } |
| |
| void FSRPixelConsistencyTestCase::initPrograms (SourceCollections& programCollection) const |
| { |
| std::stringstream vss; |
| |
| vss << |
| "#version 450 core\n" |
| "layout(location = 0) in vec2 position;\n" |
| "out gl_PerVertex\n" |
| "{\n" |
| " vec4 gl_Position;\n" |
| "};\n" |
| "void main()\n" |
| "{\n"; |
| if (!m_data.zwCoord) |
| { |
| vss << |
| " gl_Position = vec4(position, 0, 1);\n"; |
| } |
| else |
| { |
| vss << |
| " gl_Position = vec4(position, position);\n"; |
| } |
| vss << |
| "}\n"; |
| |
| programCollection.glslSources.add("vert") << glu::VertexSource(vss.str()); |
| |
| std::stringstream fssPass0; |
| |
| fssPass0 << |
| "#version 450 core\n" |
| "layout(push_constant) uniform PC {\n" |
| " uvec2 shadingRate[2];\n" |
| "} pc;\n" |
| "layout(location = 0) out uvec2 col0;\n" |
| "void main()\n" |
| "{\n"; |
| if (!m_data.zwCoord) |
| { |
| fssPass0 << |
| " col0.x = (uint(gl_FragCoord.x) % pc.shadingRate[0].x) + ((uint(gl_FragCoord.y) % pc.shadingRate[0].y) * pc.shadingRate[0].x);\n" |
| " col0.y = (uint(gl_FragCoord.x) % pc.shadingRate[1].x) + ((uint(gl_FragCoord.y) % pc.shadingRate[1].y) * pc.shadingRate[1].x);\n"; |
| } |
| else |
| { |
| fssPass0 << |
| " col0.x = (uint(gl_FragCoord.z) % pc.shadingRate[0].x) + ((uint(gl_FragCoord.w) % pc.shadingRate[0].y) * pc.shadingRate[0].x);\n" |
| " col0.y = (uint(gl_FragCoord.z) % pc.shadingRate[1].x) + ((uint(gl_FragCoord.w) % pc.shadingRate[1].y) * pc.shadingRate[1].x);\n"; |
| } |
| fssPass0 << |
| "}\n"; |
| |
| programCollection.glslSources.add("frag_pass0") << glu::FragmentSource(fssPass0.str()); |
| |
| std::stringstream fssPass1; |
| |
| fssPass1 << |
| "#version 450 core\n"; |
| |
| if (m_data.samples == VK_SAMPLE_COUNT_1_BIT) |
| { |
| fssPass1 << |
| "layout(input_attachment_index=0, set=0, binding=0) uniform usubpassInput inputAttachment;\n"; |
| } |
| else |
| { |
| fssPass1 << |
| "layout(input_attachment_index=0, set=0, binding=0) uniform usubpassInputMS inputAttachment;\n"; |
| } |
| |
| fssPass1 << |
| "layout(location = 0) out uvec2 col0;\n" |
| "void main()\n" |
| "{\n"; |
| |
| if (m_data.samples == VK_SAMPLE_COUNT_1_BIT) |
| { |
| fssPass1 << |
| " col0 = subpassLoad(inputAttachment).xy;\n"; |
| } |
| else |
| { |
| fssPass1 << |
| " col0 = subpassLoad(inputAttachment, 0).xy;\n"; |
| } |
| |
| fssPass1 << |
| "}\n"; |
| |
| programCollection.glslSources.add("frag_pass1") << glu::FragmentSource(fssPass1.str()); |
| } |
| |
| TestInstance* FSRPixelConsistencyTestCase::createInstance (Context& context) const |
| { |
| return new FSRPixelConsistencyInstance(context, m_data); |
| } |
| |
| bool compareShadingRate(VkExtent2D ext1, VkExtent2D ext2) |
| { |
| deUint32 ratio1 = std::max(ext1.width, ext1.height) / std::min(ext1.width, ext1.height); |
| deUint32 ratio2 = std::max(ext2.width, ext2.height) / std::min(ext2.width, ext2.height); |
| |
| return ratio1 < ratio2; |
| } |
| |
| void FSRPixelConsistencyInstance::clampShadingRate() |
| { |
| deUint32 desiredSize = m_data.shadingRate.width * m_data.shadingRate.height; |
| |
| while (desiredSize > 0) |
| { |
| // Find modes that maximize the area |
| for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i) |
| { |
| const VkPhysicalDeviceFragmentShadingRateKHR& supportedRate = m_supportedFragmentShadingRates[i]; |
| |
| if (supportedRate.sampleCounts & VK_SAMPLE_COUNT_1_BIT) |
| { |
| // We found exact match |
| if (supportedRate.fragmentSize.width == m_data.shadingRate.width && |
| supportedRate.fragmentSize.height == m_data.shadingRate.height) |
| { |
| m_shadingRateClamped.push_back(supportedRate.fragmentSize); |
| |
| return; |
| } |
| else |
| { |
| if (supportedRate.fragmentSize.width <= m_data.shadingRate.width && |
| supportedRate.fragmentSize.height <= m_data.shadingRate.height && |
| supportedRate.fragmentSize.width * supportedRate.fragmentSize.height == desiredSize) |
| { |
| m_shadingRateClamped.push_back(supportedRate.fragmentSize); |
| } |
| } |
| } |
| } |
| if (!m_shadingRateClamped.empty()) |
| { |
| // Sort the modes so that the ones with the smallest aspect ratio are in front |
| std::sort(m_shadingRateClamped.begin(), m_shadingRateClamped.end(), compareShadingRate); |
| |
| deUint32 desiredRatio = std::max(m_shadingRateClamped[0].width, m_shadingRateClamped[0].height) / |
| std::min(m_shadingRateClamped[0].width, m_shadingRateClamped[0].height); |
| |
| // Leave only entries with the smallest aspect ratio |
| auto it = m_shadingRateClamped.begin(); |
| while (it != m_shadingRateClamped.end()) |
| { |
| deUint32 ratio = std::max(it->width, it->height) / std::min(it->width, it->height); |
| |
| if (ratio < desiredRatio) |
| { |
| it = m_shadingRateClamped.erase(it, m_shadingRateClamped.end()); |
| } |
| else |
| { |
| ++it; |
| } |
| } |
| |
| return; |
| } |
| else |
| { |
| desiredSize /= 2; |
| } |
| } |
| DE_ASSERT(0); |
| |
| return; |
| } |
| |
| tcu::TestStatus FSRPixelConsistencyInstance::verifyResult(tcu::ConstPixelBufferAccess& resultBuffer, const deUint32 index) |
| { |
| deUint32 pixelIndex = std::numeric_limits<unsigned int>::max(); |
| deUint32 pixelOutsideIndex = std::numeric_limits<unsigned int>::max(); |
| |
| for (int y = 0; y < resultBuffer.getHeight(); y++) |
| { |
| for (int x = 0; x < resultBuffer.getWidth(); x++) |
| { |
| deUint32 pixel = resultBuffer.getPixelUint(x, y)[index]; |
| |
| // If pixel was not covered by any triangle, we skip it |
| if (pixel == std::numeric_limits<unsigned int>::max()) |
| { |
| continue; |
| } |
| |
| // We check if pixel is part of fragment area that is partially outside of framebuffer area |
| deBool outsideW = (x / m_shadingRateClamped[index].width + 1) * m_shadingRateClamped[index].width > static_cast<deUint32>(resultBuffer.getWidth()); |
| deBool outsideH = (y / m_shadingRateClamped[index].height + 1) * m_shadingRateClamped[index].height > static_cast<deUint32>(resultBuffer.getHeight()); |
| |
| if (outsideW || outsideH) |
| { |
| // If image robustness is enabled such pixel can have either a value of 0 or one of the values from the area inside framebuffer |
| if (m_context.isDeviceFunctionalitySupported("VK_EXT_image_robustness")) |
| { |
| if (pixelOutsideIndex == std::numeric_limits<unsigned int>::max() || pixelOutsideIndex == 0) |
| { |
| pixelOutsideIndex = pixel; |
| } |
| // If value is non-zero we make sure that all 'corner' pixels have the same value |
| else if ((pixel != 0) && (pixelOutsideIndex != pixel)) |
| { |
| return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL)); |
| } |
| } |
| // If image robustness is not enabled such pixel can have an undefined value, so we skip it |
| else |
| { |
| continue; |
| } |
| } |
| else |
| { |
| if (pixelIndex == std::numeric_limits<unsigned int>::max()) |
| { |
| if (pixel >= m_shadingRateClamped[index].width * m_shadingRateClamped[index].height) |
| { |
| return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL)); |
| } |
| |
| pixelIndex = pixel; |
| } |
| // If pixel is not part of 'corner' pixels we make sure that is has the same value as other non-'corner' pixels |
| else if (pixelIndex != pixel) |
| { |
| return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL)); |
| } |
| } |
| } |
| } |
| |
| return tcu::TestStatus(QP_TEST_RESULT_PASS, qpGetTestResultName(QP_TEST_RESULT_PASS)); |
| } |
| |
| tcu::TestStatus FSRPixelConsistencyInstance::iterate (void) |
| { |
| const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()); |
| |
| Move<VkDevice> vkd = createImageRobustnessDevice(m_context); |
| const VkDevice device = *vkd; |
| de::MovePtr<DeviceDriver> deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), m_context.getInstance(), device)); |
| const DeviceInterface& vk = *deviceDriver.get(); |
| const VkQueue queue = getDeviceQueue(vk, device, m_context.getUniversalQueueFamilyIndex(), 0); |
| de::MovePtr<Allocator> allocator = de::MovePtr<Allocator>(new SimpleAllocator(vk, device, memoryProperties)); |
| |
| // Create vertex buffer |
| const VkDeviceSize vertexBufferSize = sizeof(basicTriangles); |
| |
| const VkFormat imageFormat = VK_FORMAT_R32G32_UINT; |
| |
| de::MovePtr<BufferWithMemory> vertexBuffer; |
| vertexBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory( |
| vk, device, *allocator, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible)); |
| |
| float* vbuf = (float*)vertexBuffer->getAllocation().getHostPtr(); |
| |
| deMemcpy(vbuf, basicTriangles, vertexBufferSize); |
| |
| flushAlloc(vk, device, vertexBuffer->getAllocation()); |
| |
| // Create color output buffer |
| const VkDeviceSize colorOutputBufferSize = m_data.framebufferExtent.width * m_data.framebufferExtent.height * tcu::getPixelSize(mapVkFormat(imageFormat)); |
| |
| de::MovePtr<BufferWithMemory> colorOutputBuffer; |
| colorOutputBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory( |
| vk, device, *allocator, makeBufferCreateInfo(colorOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible)); |
| |
| |
| // Create color attachment for subpass 0 |
| de::MovePtr<ImageWithMemory> cbImagePass0; |
| Move<VkImageView> cbImagePass0View; |
| { |
| const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | |
| VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| const VkImageCreateInfo imageCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkImageCreateFlags)0u, // VkImageCreateFlags flags; |
| VK_IMAGE_TYPE_2D, // VkImageType imageType; |
| imageFormat, // VkFormat format; |
| { |
| m_data.framebufferExtent.width, // deUint32 width; |
| m_data.framebufferExtent.height, // deUint32 height; |
| 1u // deUint32 depth; |
| }, // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| 1u, // deUint32 arrayLayers; |
| m_data.samples, // VkSampleCountFlagBits samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| cbUsage, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 0u, // deUint32 queueFamilyIndexCount; |
| DE_NULL, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; |
| }; |
| cbImagePass0 = de::MovePtr<ImageWithMemory>(new ImageWithMemory( |
| vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any)); |
| |
| VkImageViewCreateInfo imageViewCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags; |
| **cbImagePass0, // VkImage image; |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; |
| imageFormat, // VkFormat format; |
| { |
| VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r; |
| VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g; |
| VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b; |
| VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a; |
| }, // VkComponentMapping components; |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 levelCount; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| } // VkImageSubresourceRange subresourceRange; |
| }; |
| cbImagePass0View = createImageView(vk, device, &imageViewCreateInfo, NULL); |
| } |
| |
| // Create color attachment for subpass 1 |
| de::MovePtr<ImageWithMemory> cbImagePass1; |
| Move<VkImageView> cbImagePass1View; |
| { |
| const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| const VkImageCreateInfo imageCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkImageCreateFlags)0u, // VkImageCreateFlags flags; |
| VK_IMAGE_TYPE_2D, // VkImageType imageType; |
| imageFormat, // VkFormat format; |
| { |
| m_data.framebufferExtent.width, // deUint32 width; |
| m_data.framebufferExtent.height, // deUint32 height; |
| 1u // deUint32 depth; |
| }, // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| 1u, // deUint32 arrayLayers; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| cbUsage, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 0u, // deUint32 queueFamilyIndexCount; |
| DE_NULL, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; |
| }; |
| cbImagePass1 = de::MovePtr<ImageWithMemory>(new ImageWithMemory( |
| vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any)); |
| |
| VkImageViewCreateInfo imageViewCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags; |
| **cbImagePass1, // VkImage image; |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; |
| imageFormat, // VkFormat format; |
| { |
| VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r; |
| VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g; |
| VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b; |
| VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a; |
| }, // VkComponentMapping components; |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; |
| 0u, // deUint32 baseMipLevel; |
| 1u, // deUint32 levelCount; |
| 0u, // deUint32 baseArrayLayer; |
| 1u // deUint32 layerCount; |
| } // VkImageSubresourceRange subresourceRange; |
| }; |
| cbImagePass1View = createImageView(vk, device, &imageViewCreateInfo, NULL); |
| } |
| |
| // Create render pass |
| Move<VkRenderPass> renderPass; |
| { |
| const vk::VkAttachmentReference colorAttachment0Reference = |
| { |
| 0, // attachment |
| vk::VK_IMAGE_LAYOUT_GENERAL, // layout |
| }; |
| |
| const vk::VkAttachmentReference colorAttachment1Reference = |
| { |
| 1, // attachment |
| vk::VK_IMAGE_LAYOUT_GENERAL, // layout |
| }; |
| |
| std::vector<VkAttachmentDescription> attachmentDescriptions; |
| |
| attachmentDescriptions.push_back( |
| { |
| (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; |
| imageFormat, // VkFormat format; |
| m_data.samples, // VkSampleCountFlagBits samples; |
| VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; |
| VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout; |
| VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout; |
| } |
| ); |
| |
| attachmentDescriptions.push_back( |
| { |
| (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; |
| imageFormat, // VkFormat format; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; |
| VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; |
| VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout; |
| VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout; |
| } |
| ); |
| |
| const VkSubpassDescription subpassDescs[] = |
| { |
| { |
| (vk::VkSubpassDescriptionFlags)0, // flags |
| vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint |
| 0u, // inputCount |
| DE_NULL, // pInputAttachments |
| 1u, // colorCount |
| &colorAttachment0Reference, // pColorAttachments |
| DE_NULL, // pResolveAttachments |
| DE_NULL, // depthStencilAttachment |
| 0u, // preserveCount |
| DE_NULL, // pPreserveAttachments |
| }, |
| { |
| (vk::VkSubpassDescriptionFlags)0, // flags |
| vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint |
| 1u, // inputCount |
| &colorAttachment0Reference, // pInputAttachments |
| 1u, // colorCount |
| &colorAttachment1Reference, // pColorAttachments |
| DE_NULL, // pResolveAttachments |
| DE_NULL, // depthStencilAttachment |
| 0u, // preserveCount |
| DE_NULL, // pPreserveAttachments |
| }, |
| }; |
| |
| const VkSubpassDependency subpassDependency = |
| { |
| 0u, // srcSubpass; |
| 1u, // dstSubpass; |
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // srcStageMask; |
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // dstStageMask; |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask; |
| VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // dstAccessMask; |
| 0 // dependencyFlags; |
| }; |
| |
| const VkRenderPassCreateInfo renderPassParams = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (vk::VkRenderPassCreateFlags)0, |
| (deUint32)attachmentDescriptions.size(), // attachmentCount |
| &attachmentDescriptions[0], // pAttachments |
| sizeof(subpassDescs) / sizeof(subpassDescs[0]), // subpassCount |
| subpassDescs, // pSubpasses |
| 1u, // dependencyCount |
| &subpassDependency, // pDependencies |
| }; |
| |
| renderPass = createRenderPass(vk, device, &renderPassParams); |
| } |
| |
| // Create framebuffer |
| Move<VkFramebuffer> framebuffer; |
| { |
| std::vector<VkImageView> attachments; |
| attachments.push_back(*cbImagePass0View); |
| attachments.push_back(*cbImagePass1View); |
| |
| const vk::VkFramebufferCreateInfo framebufferParams = |
| { |
| vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (vk::VkFramebufferCreateFlags)(0), // createFlags |
| *renderPass, // renderPass |
| (deUint32)attachments.size(), // attachmentCount |
| &attachments[0], // pAttachments |
| m_data.framebufferExtent.width, // width |
| m_data.framebufferExtent.height, // height |
| 1u, // layers |
| }; |
| |
| framebuffer = createFramebuffer(vk, device, &framebufferParams); |
| } |
| |
| |
| // Create vertex attribute |
| const VkVertexInputBindingDescription vertexBinding = |
| { |
| 0u, // deUint32 binding; |
| sizeof(Vertex), // deUint32 stride; |
| VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; |
| }; |
| |
| const VkVertexInputAttributeDescription vertexInputAttributeDescription = |
| { |
| 0u, // deUint32 location; |
| 0u, // deUint32 binding; |
| VK_FORMAT_R32G32_SFLOAT, // VkFormat format; |
| 0u // deUint32 offset; |
| }; |
| |
| const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; |
| 1u, // deUint32 vertexBindingDescriptionCount; |
| &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; |
| 1u, // deUint32 vertexAttributeDescriptionCount; |
| &vertexInputAttributeDescription // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; |
| }; |
| |
| const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology; |
| VK_FALSE // VkBool32 primitiveRestartEnable; |
| }; |
| |
| // Create rasterization state |
| const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; |
| VK_FALSE, // VkBool32 depthClampEnable; |
| VK_FALSE, // VkBool32 rasterizerDiscardEnable; |
| VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; |
| VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; |
| VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace; |
| VK_FALSE, // VkBool32 depthBiasEnable; |
| 0.0f, // float depthBiasConstantFactor; |
| 0.0f, // float depthBiasClamp; |
| 0.0f, // float depthBiasSlopeFactor; |
| 1.0f // float lineWidth; |
| }; |
| |
| // Create scissor and viewport |
| VkViewport viewport = makeViewport(m_data.framebufferExtent.width, m_data.framebufferExtent.height); |
| VkRect2D scissor = makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height); |
| |
| const VkPipelineViewportStateCreateInfo viewportStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags |
| 1u, // deUint32 viewportCount |
| &viewport, // const VkViewport* pViewports |
| 1u, // deUint32 scissorCount |
| &scissor // const VkRect2D* pScissors |
| }; |
| |
| const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkPipelineDynamicStateCreateFlags)0, // VkPipelineDynamicStateCreateFlags flags; |
| 0u, // uint32_t dynamicStateCount; |
| DE_NULL, // const VkDynamicState* pDynamicStates; |
| }; |
| |
| const VkPipelineColorBlendAttachmentState colorBlendAttachmentState[] = |
| { |
| { |
| VK_FALSE, // VkBool32 blendEnable; |
| VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor; |
| VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; |
| VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; |
| VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor; |
| VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; |
| VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; |
| 0xf // VkColorComponentFlags colorWriteMask; |
| } |
| }; |
| |
| const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineColorBlendStateCreateFlags flags; |
| VK_FALSE, // VkBool32 logicOpEnable; |
| VK_LOGIC_OP_COPY, // VkLogicOp logicOp; |
| sizeof(colorBlendAttachmentState) / sizeof(colorBlendAttachmentState[0]), // deUint32 attachmentCount; |
| colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; |
| { 1.0f, 1.0f, 1.0f, 1.0f } // float blendConstants[4]; |
| }; |
| |
| VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineDepthStencilStateCreateFlags flags; |
| VK_FALSE, // VkBool32 depthTestEnable; |
| VK_FALSE, // VkBool32 depthWriteEnable; |
| VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp; |
| VK_FALSE, // VkBool32 depthBoundsTestEnable; |
| VK_FALSE, // VkBool32 stencilTestEnable; |
| // VkStencilOpState front; |
| { |
| VK_STENCIL_OP_REPLACE, // VkStencilOp failOp; |
| VK_STENCIL_OP_REPLACE, // VkStencilOp passOp; |
| VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp; |
| VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp; |
| 0u, // deUint32 compareMask; |
| 0xFFu, // deUint32 writeMask; |
| 0xFFu, // deUint32 reference; |
| }, |
| // VkStencilOpState back; |
| { |
| VK_STENCIL_OP_REPLACE, // VkStencilOp failOp; |
| VK_STENCIL_OP_REPLACE, // VkStencilOp passOp; |
| VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp; |
| VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp; |
| 0u, // deUint32 compareMask; |
| 0xFFu, // deUint32 writeMask; |
| 0xFFu, // deUint32 reference; |
| }, |
| 0.0f, // float minDepthBounds; |
| 0.0f, // float maxDepthBounds; |
| }; |
| |
| // Create pipeline for pass 0 |
| Move<VkPipeline> pipelinePass0; |
| Move<VkPipelineLayout> pipelineLayoutPass0; |
| { |
| const VkPushConstantRange pushConstantRange = |
| { |
| VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags; |
| 0u, // deUint32 offset; |
| 2 * sizeof(VkExtent2D) // deUint32 size; |
| }; |
| |
| const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkPipelineLayoutCreateFlags)0, |
| 0u, // setLayoutCount |
| DE_NULL, // pSetLayouts |
| 1u, // pushConstantRangeCount |
| &pushConstantRange, // pPushConstantRanges |
| }; |
| |
| pipelineLayoutPass0 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL); |
| |
| const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkPipelineMultisampleStateCreateFlags flags |
| (VkSampleCountFlagBits)m_data.samples, // VkSampleCountFlagBits rasterizationSamples |
| VK_FALSE, // VkBool32 sampleShadingEnable |
| 1.0f, // float minSampleShading |
| DE_NULL, // const VkSampleMask* pSampleMask |
| VK_FALSE, // VkBool32 alphaToCoverageEnable |
| VK_FALSE // VkBool32 alphaToOneEnable |
| }; |
| |
| Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0); |
| Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass0"), 0); |
| |
| const VkPipelineShaderStageCreateInfo shaderCreateInfo[] = |
| { |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| DE_NULL, |
| (VkPipelineShaderStageCreateFlags)0, |
| VK_SHADER_STAGE_VERTEX_BIT, // stage |
| *vertShader, // shader |
| "main", |
| DE_NULL, // pSpecializationInfo |
| }, |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| DE_NULL, |
| (VkPipelineShaderStageCreateFlags)0, |
| VK_SHADER_STAGE_FRAGMENT_BIT, // stage |
| *fragShader, // shader |
| "main", |
| DE_NULL, // pSpecializationInfo |
| } |
| }; |
| |
| const VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; |
| sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]), // deUint32 stageCount; |
| &shaderCreateInfo[0], // const VkPipelineShaderStageCreateInfo* pStages; |
| &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; |
| &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; |
| DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; |
| &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; |
| &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; |
| &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; |
| &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; |
| &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; |
| &dynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState; |
| pipelineLayoutPass0.get(), // VkPipelineLayout layout; |
| renderPass.get(), // VkRenderPass renderPass; |
| 0u, // deUint32 subpass; |
| DE_NULL, // VkPipeline basePipelineHandle; |
| 0 // int basePipelineIndex; |
| }; |
| |
| pipelinePass0 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo); |
| } |
| |
| |
| // Create pipeline for pass 1 |
| Move<VkPipeline> pipelinePass1; |
| Move<VkPipelineLayout> pipelineLayoutPass1; |
| Move<vk::VkDescriptorPool> descriptorPool; |
| Move<vk::VkDescriptorSetLayout> descriptorSetLayout; |
| Move<vk::VkDescriptorSet> descriptorSet; |
| { |
| const VkDescriptorSetLayoutBinding bindings[] = |
| { |
| { |
| 0u, // binding |
| VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // descriptorType |
| 1u, // descriptorCount |
| VK_SHADER_STAGE_FRAGMENT_BIT, // stageFlags |
| DE_NULL, // pImmutableSamplers |
| } |
| }; |
| |
| // Create a layout and allocate a descriptor set for it. |
| const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkDescriptorSetLayoutCreateFlags)(0), // flags |
| sizeof(bindings) / sizeof(bindings[0]), // bindingCount |
| &bindings[0] // pBindings |
| }; |
| |
| descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo); |
| |
| vk::DescriptorPoolBuilder poolBuilder; |
| |
| for (deInt32 i = 0; i < (deInt32)(sizeof(bindings) / sizeof(bindings[0])); ++i) |
| { |
| poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount); |
| } |
| |
| descriptorPool = poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); |
| descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout); |
| |
| VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(DE_NULL, *cbImagePass0View, VK_IMAGE_LAYOUT_GENERAL); |
| |
| VkWriteDescriptorSet writeDescriptorSet = |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType |
| DE_NULL, // pNext |
| *descriptorSet, // dstSet |
| 0u, // dstBinding |
| 0u, // dstArrayElement |
| 1u, // descriptorCount |
| bindings[0].descriptorType, // descriptorType |
| &imageInfo, // pImageInfo |
| DE_NULL, // pBufferInfo |
| DE_NULL, // pTexelBufferView |
| }; |
| |
| vk.updateDescriptorSets(device, 1, &writeDescriptorSet, 0, NULL); |
| |
| const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkPipelineLayoutCreateFlags)0, |
| 1u, // setLayoutCount |
| &descriptorSetLayout.get(), // pSetLayouts |
| 0u, // pushConstantRangeCount |
| DE_NULL, // pPushConstantRanges |
| }; |
| |
| pipelineLayoutPass1 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL); |
| |
| const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkPipelineMultisampleStateCreateFlags flags |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples |
| VK_FALSE, // VkBool32 sampleShadingEnable |
| 1.0f, // float minSampleShading |
| DE_NULL, // const VkSampleMask* pSampleMask |
| VK_FALSE, // VkBool32 alphaToCoverageEnable |
| VK_FALSE // VkBool32 alphaToOneEnable |
| }; |
| |
| VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| m_data.shadingRate, // VkExtent2D fragmentSize; |
| { VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR }, // VkFragmentShadingRateCombinerOpKHR combinerOps[2]; |
| }; |
| |
| Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0); |
| Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass1"), 0); |
| |
| const VkPipelineShaderStageCreateInfo shaderCreateInfo[] = |
| { |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| DE_NULL, |
| (VkPipelineShaderStageCreateFlags)0, |
| VK_SHADER_STAGE_VERTEX_BIT, // stage |
| *vertShader, // shader |
| "main", |
| DE_NULL, // pSpecializationInfo |
| }, |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| DE_NULL, |
| (VkPipelineShaderStageCreateFlags)0, |
| VK_SHADER_STAGE_FRAGMENT_BIT, // stage |
| *fragShader, // shader |
| "main", |
| DE_NULL, // pSpecializationInfo |
| } |
| }; |
| |
| const VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; |
| &shadingRateStateCreateInfo, // const void* pNext; |
| (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; |
| sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]), // deUint32 stageCount; |
| &shaderCreateInfo[0], // const VkPipelineShaderStageCreateInfo* pStages; |
| &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; |
| &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; |
| DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; |
| &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; |
| &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; |
| &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; |
| &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; |
| &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; |
| &dynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState; |
| pipelineLayoutPass1.get(), // VkPipelineLayout layout; |
| renderPass.get(), // VkRenderPass renderPass; |
| 1u, // deUint32 subpass; |
| DE_NULL, // VkPipeline basePipelineHandle; |
| 0 // int basePipelineIndex; |
| }; |
| |
| pipelinePass1 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo); |
| } |
| |
| // Create command buffer |
| Move<VkCommandPool> cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex()); |
| Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| |
| VkImageMemoryBarrier preImageBarriers[] = |
| { |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkAccessFlags srcAccessMask |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout |
| VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex |
| **cbImagePass0, // VkImage image |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask |
| 0u, // uint32_t baseMipLevel |
| VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels, |
| 0u, // uint32_t baseArray |
| VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize |
| } |
| }, |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkAccessFlags srcAccessMask |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout |
| VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex |
| **cbImagePass1, // VkImage image |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask |
| 0u, // uint32_t baseMipLevel |
| VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels, |
| 0u, // uint32_t baseArray |
| VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize |
| } |
| } |
| }; |
| |
| // Record commands |
| beginCommandBuffer(vk, *cmdBuffer, 0u); |
| |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, |
| (VkDependencyFlags)0, |
| 0, (const VkMemoryBarrier*)DE_NULL, |
| 0, (const VkBufferMemoryBarrier*)DE_NULL, |
| sizeof(preImageBarriers) / sizeof(preImageBarriers[0]), preImageBarriers); |
| |
| // Clear both images to UINT_MAX |
| VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); |
| VkClearValue clearColor = makeClearValueColorU32(std::numeric_limits<unsigned int>::max(),0,0,0); |
| |
| vk.cmdClearColorImage(*cmdBuffer, **cbImagePass0, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range); |
| vk.cmdClearColorImage(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range); |
| |
| // Barrier between the clear and the rendering |
| VkImageMemoryBarrier clearColorBarriers[] = |
| { |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask |
| VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout |
| VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex |
| **cbImagePass0, // VkImage image |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask |
| 0u, // uint32_t baseMipLevel |
| VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels, |
| 0u, // uint32_t baseArray |
| VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize |
| } |
| }, |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask |
| VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout |
| VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex |
| **cbImagePass1, // VkImage image |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask |
| 0u, // uint32_t baseMipLevel |
| VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels, |
| 0u, // uint32_t baseArray |
| VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize |
| } |
| } |
| }; |
| |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, |
| (VkDependencyFlags)0, |
| 0, (const VkMemoryBarrier*)DE_NULL, |
| 0, (const VkBufferMemoryBarrier*)DE_NULL, |
| sizeof(clearColorBarriers) / sizeof(clearColorBarriers[0]), clearColorBarriers); |
| |
| beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, |
| makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height), |
| 0, DE_NULL, VK_SUBPASS_CONTENTS_INLINE, DE_NULL); |
| |
| // Put primitive shading rate in a push constant |
| if (m_shadingRateClamped.size() == 1) |
| { |
| vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]); |
| vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(m_shadingRateClamped[0]), sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]); |
| } |
| else |
| { |
| vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, 0, static_cast<deUint32>(m_shadingRateClamped.size() * sizeof(m_shadingRateClamped[0])), &m_shadingRateClamped[0]); |
| } |
| |
| // Bind vertex buffer |
| const VkDeviceSize vertexBufferOffset = 0; |
| VkBuffer vb = **vertexBuffer; |
| vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset); |
| |
| // Bind pipeline |
| vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass0); |
| |
| // Draw triangles |
| vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u); |
| |
| // Start next subpass |
| vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); |
| |
| // Bind descriptors |
| vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPass1, 0, 1, &descriptorSet.get(), 0, DE_NULL); |
| |
| // Bind vertex buffer |
| vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset); |
| |
| // Bind pipeline |
| vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass1); |
| |
| // Draw triangles |
| vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u); |
| |
| endRenderPass(vk, *cmdBuffer); |
| |
| VkImageMemoryBarrier postImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask |
| VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask |
| VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex |
| VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex |
| **cbImagePass1, // VkImage image |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask |
| 0u, // uint32_t baseMipLevel |
| VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels, |
| 0u, // uint32_t baseArray |
| VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize |
| } |
| }; |
| |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier); |
| |
| const VkBufferImageCopy copyRegion = |
| { |
| 0u, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| { |
| VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect; |
| 0u, // deUint32 mipLevel; |
| 0u, // deUint32 baseArrayLayer; |
| 1u, // deUint32 layerCount; |
| }, // VkImageSubresourceLayers imageSubresource; |
| { 0, 0, 0 }, // VkOffset3D imageOffset; |
| {m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1} // VkExtent3D imageExtent; |
| }; |
| |
| vk.cmdCopyImageToBuffer(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **colorOutputBuffer, 1u, ©Region); |
| |
| const VkBufferMemoryBarrier bufferBarrier = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| **colorOutputBuffer, // VkBuffer buffer; |
| 0ull, // VkDeviceSize offset; |
| VK_WHOLE_SIZE // VkDeviceSize size; |
| }; |
| |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); |
| |
| endCommandBuffer(vk, *cmdBuffer); |
| |
| submitCommandsAndWait(vk, device, queue, cmdBuffer.get()); |
| |
| // Read buffer data |
| invalidateAlloc(vk, device, colorOutputBuffer->getAllocation()); |
| |
| tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess( |
| tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNSIGNED_INT32), |
| m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1, (const void *)colorOutputBuffer->getAllocation().getHostPtr()); |
| |
| for (deUint32 i = 0; i < m_shadingRateClamped.size(); i++) |
| { |
| tcu::TestStatus result = verifyResult(resultBuffer, i); |
| if (result.getCode() == QP_TEST_RESULT_PASS) |
| { |
| return result; |
| } |
| } |
| |
| return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL)); |
| } |
| |
| } // anonymous |
| |
| void createPixelConsistencyTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup) |
| { |
| typedef struct |
| { |
| deUint32 count; |
| const char* name; |
| const char* description; |
| } TestGroupCase; |
| |
| typedef struct |
| { |
| VkExtent2D count; |
| const char* name; |
| const char* description; |
| } TestGroupCase2D; |
| |
| TestGroupCase2D shadingRateCases[] = |
| { |
| { {1, 1}, "rate_1x1", "1x1 shading rate" }, |
| { {1, 2}, "rate_1x2", "1x2 shading rate" }, |
| { {1, 4}, "rate_1x4", "1x4 shading rate" }, |
| { {2, 1}, "rate_2x1", "2x1 shading rate" }, |
| { {2, 2}, "rate_2x2", "2x2 shading rate" }, |
| { {2, 4}, "rate_2x4", "2x4 shading rate" }, |
| { {4, 1}, "rate_4x1", "4x1 shading rate" }, |
| { {4, 2}, "rate_4x2", "4x2 shading rate" }, |
| { {4, 4}, "rate_4x4", "4x4 shading rate" }, |
| }; |
| |
| TestGroupCase sampCases[] = |
| { |
| { VK_SAMPLE_COUNT_1_BIT, "samples_1", "1 raster sample" }, |
| { VK_SAMPLE_COUNT_2_BIT, "samples_2", "2 raster samples" }, |
| { VK_SAMPLE_COUNT_4_BIT, "samples_4", "4 raster samples" }, |
| { VK_SAMPLE_COUNT_8_BIT, "samples_8", "8 raster samples" }, |
| { VK_SAMPLE_COUNT_16_BIT, "samples_16", "16 raster samples" }, |
| }; |
| |
| TestGroupCase2D extentCases[] = |
| { |
| { {1, 1}, "extent_1x1", "framebuffer size 1x1" }, |
| { {4, 4}, "extent_4x4", "framebuffer size 4x4" }, |
| { {33, 35}, "extent_33x35", "framebuffer size 33x35" }, |
| { {151, 431}, "extent_151x431", "framebuffer size 151x431" }, |
| { {256, 256}, "extent_256x256", "framebuffer size 256x256" }, |
| }; |
| |
| de::MovePtr<tcu::TestCaseGroup> pixelGroup(new tcu::TestCaseGroup(testCtx, "pixel_consistency", "Pixel selection consistency")); |
| |
| for (int rateNdx = 0; rateNdx < DE_LENGTH_OF_ARRAY(shadingRateCases); rateNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> rateGroup(new tcu::TestCaseGroup(testCtx, shadingRateCases[rateNdx].name, shadingRateCases[rateNdx].description)); |
| |
| for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name, sampCases[sampNdx].description)); |
| for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++) |
| { |
| VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(sampCases[sampNdx].count); |
| VkExtent2D framebufferExtent = extentCases[extNdx].count; |
| |
| CaseDef caseParams{ |
| shadingRateCases[rateNdx].count, |
| samples, |
| framebufferExtent, |
| false}; |
| sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, extentCases[extNdx].name, extentCases[extNdx].description, caseParams)); |
| |
| // test FragCoord.zw but to avoid duplication limit tests to extent_151x431/256x256 and 1 or 4 samples |
| if ((framebufferExtent.width > 150) && (samples & (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))) |
| { |
| std::string caseName = std::string(extentCases[extNdx].name) + "_zw_coord"; |
| caseParams.zwCoord = true; |
| sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, caseName.c_str(), extentCases[extNdx].description, caseParams)); |
| } |
| } |
| rateGroup->addChild(sampleGroup.release()); |
| } |
| |
| pixelGroup->addChild(rateGroup.release()); |
| } |
| |
| parentGroup->addChild(pixelGroup.release()); |
| } |
| |
| } // FragmentShadingRage |
| } // vkt |