| /*------------------------------------------------------------------------- |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2017 Google Inc. |
| * |
| * 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 YCbCr Image View Tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktYCbCrViewTests.hpp" |
| #include "vktYCbCrUtil.hpp" |
| #include "vktTestCaseUtil.hpp" |
| #include "vktTestGroupUtil.hpp" |
| #include "vktShaderExecutor.hpp" |
| |
| #include "vkStrUtil.hpp" |
| #include "vkRef.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkImageUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| |
| #include "tcuTestLog.hpp" |
| #include "tcuVectorUtil.hpp" |
| |
| #include "deStringUtil.hpp" |
| #include "deSharedPtr.hpp" |
| #include "deUniquePtr.hpp" |
| #include "deRandom.hpp" |
| #include "deSTLUtil.hpp" |
| |
| namespace vkt |
| { |
| namespace ycbcr |
| { |
| namespace |
| { |
| |
| using namespace vk; |
| using namespace shaderexecutor; |
| |
| using tcu::UVec2; |
| using tcu::Vec2; |
| using tcu::Vec4; |
| using tcu::TestLog; |
| using de::MovePtr; |
| using de::UniquePtr; |
| using std::vector; |
| using std::string; |
| |
| Move<VkImage> createTestImage (const DeviceInterface& vkd, |
| VkDevice device, |
| VkFormat format, |
| const UVec2& size, |
| VkImageCreateFlags createFlags) |
| { |
| const VkImageCreateInfo createInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| DE_NULL, |
| createFlags, |
| VK_IMAGE_TYPE_2D, |
| format, |
| makeExtent3D(size.x(), size.y(), 1u), |
| 1u, // mipLevels |
| 1u, // arrayLayers |
| VK_SAMPLE_COUNT_1_BIT, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT, |
| VK_SHARING_MODE_EXCLUSIVE, |
| 0u, |
| (const deUint32*)DE_NULL, |
| VK_IMAGE_LAYOUT_UNDEFINED, |
| }; |
| |
| return createImage(vkd, device, &createInfo); |
| } |
| |
| Move<VkImageView> createImageView (const DeviceInterface& vkd, |
| VkDevice device, |
| VkImage image, |
| VkFormat format, |
| VkImageAspectFlagBits imageAspect, |
| const VkSamplerYcbcrConversionInfo* samplerConversionInfo) |
| { |
| const VkImageViewCreateInfo viewInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| samplerConversionInfo, |
| (VkImageViewCreateFlags)0, |
| image, |
| VK_IMAGE_VIEW_TYPE_2D, |
| format, |
| { |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| }, |
| { (VkImageAspectFlags)imageAspect, 0u, 1u, 0u, 1u }, |
| }; |
| |
| return createImageView(vkd, device, &viewInfo); |
| } |
| |
| // Descriptor layout for set 1: |
| // 0: Plane view bound as COMBINED_IMAGE_SAMPLER |
| // 1: "Whole" image bound as COMBINED_IMAGE_SAMPLER |
| // + immutable sampler (required for color conversion) |
| |
| Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device, VkSampler conversionSampler) |
| { |
| const VkDescriptorSetLayoutBinding bindings[] = |
| { |
| { |
| 0u, // binding |
| VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |
| 1u, // descriptorCount |
| VK_SHADER_STAGE_ALL, |
| (const VkSampler*)DE_NULL |
| }, |
| { |
| 1u, // binding |
| VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |
| 1u, // descriptorCount |
| VK_SHADER_STAGE_ALL, |
| &conversionSampler |
| } |
| }; |
| const VkDescriptorSetLayoutCreateInfo layoutInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, |
| DE_NULL, |
| (VkDescriptorSetLayoutCreateFlags)0u, |
| DE_LENGTH_OF_ARRAY(bindings), |
| bindings, |
| }; |
| |
| return createDescriptorSetLayout(vkd, device, &layoutInfo); |
| } |
| |
| Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkd, VkDevice device, const deUint32 combinedSamplerDescriptorCount) |
| { |
| const VkDescriptorPoolSize poolSizes[] = |
| { |
| { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u * combinedSamplerDescriptorCount }, |
| }; |
| const VkDescriptorPoolCreateInfo poolInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, |
| DE_NULL, |
| (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, |
| 1u, // maxSets |
| DE_LENGTH_OF_ARRAY(poolSizes), |
| poolSizes, |
| }; |
| |
| return createDescriptorPool(vkd, device, & poolInfo); |
| } |
| |
| Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkd, |
| VkDevice device, |
| VkDescriptorPool descPool, |
| VkDescriptorSetLayout descLayout, |
| VkImageView planeView, |
| VkSampler planeViewSampler, |
| VkImageView wholeView, |
| VkSampler wholeViewSampler) |
| { |
| Move<VkDescriptorSet> descSet; |
| |
| { |
| const VkDescriptorSetAllocateInfo allocInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, |
| DE_NULL, |
| descPool, |
| 1u, |
| &descLayout, |
| }; |
| |
| descSet = allocateDescriptorSet(vkd, device, &allocInfo); |
| } |
| |
| { |
| const VkDescriptorImageInfo imageInfo0 = |
| { |
| planeViewSampler, |
| planeView, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
| }; |
| const VkDescriptorImageInfo imageInfo1 = |
| { |
| wholeViewSampler, |
| wholeView, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
| }; |
| const VkWriteDescriptorSet descriptorWrites[] = |
| { |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, |
| DE_NULL, |
| *descSet, |
| 0u, // dstBinding |
| 0u, // dstArrayElement |
| 1u, // descriptorCount |
| VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |
| &imageInfo0, |
| (const VkDescriptorBufferInfo*)DE_NULL, |
| (const VkBufferView*)DE_NULL, |
| }, |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, |
| DE_NULL, |
| *descSet, |
| 1u, // dstBinding |
| 0u, // dstArrayElement |
| 1u, // descriptorCount |
| VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |
| &imageInfo1, |
| (const VkDescriptorBufferInfo*)DE_NULL, |
| (const VkBufferView*)DE_NULL, |
| } |
| }; |
| |
| vkd.updateDescriptorSets(device, DE_LENGTH_OF_ARRAY(descriptorWrites), descriptorWrites, 0u, DE_NULL); |
| } |
| |
| return descSet; |
| } |
| |
| void executeImageBarrier (const DeviceInterface& vkd, |
| VkDevice device, |
| deUint32 queueFamilyNdx, |
| VkPipelineStageFlags srcStage, |
| VkPipelineStageFlags dstStage, |
| const VkImageMemoryBarrier& barrier) |
| { |
| const VkQueue queue = getDeviceQueue(vkd, device, queueFamilyNdx, 0u); |
| const Unique<VkCommandPool> cmdPool (createCommandPool(vkd, device, (VkCommandPoolCreateFlags)0, queueFamilyNdx)); |
| const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| |
| beginCommandBuffer(vkd, *cmdBuffer); |
| |
| vkd.cmdPipelineBarrier(*cmdBuffer, |
| srcStage, |
| dstStage, |
| (VkDependencyFlags)0u, |
| 0u, |
| (const VkMemoryBarrier*)DE_NULL, |
| 0u, |
| (const VkBufferMemoryBarrier*)DE_NULL, |
| 1u, |
| &barrier); |
| |
| endCommandBuffer(vkd, *cmdBuffer); |
| |
| submitCommandsAndWait(vkd, device, queue, *cmdBuffer); |
| } |
| |
| struct TestParameters |
| { |
| enum ViewType |
| { |
| VIEWTYPE_IMAGE_VIEW = 0, |
| VIEWTYPE_MEMORY_ALIAS, |
| |
| VIEWTYPE_LAST |
| }; |
| |
| ViewType viewType; |
| VkFormat format; |
| UVec2 size; |
| VkImageCreateFlags createFlags; |
| deUint32 planeNdx; |
| glu::ShaderType shaderType; |
| |
| TestParameters (ViewType viewType_, VkFormat format_, const UVec2& size_, VkImageCreateFlags createFlags_, deUint32 planeNdx_, glu::ShaderType shaderType_) |
| : viewType (viewType_) |
| , format (format_) |
| , size (size_) |
| , createFlags (createFlags_) |
| , planeNdx (planeNdx_) |
| , shaderType (shaderType_) |
| { |
| } |
| |
| TestParameters (void) |
| : viewType (VIEWTYPE_LAST) |
| , format (VK_FORMAT_UNDEFINED) |
| , createFlags (0u) |
| , planeNdx (0u) |
| , shaderType (glu::SHADERTYPE_LAST) |
| { |
| } |
| }; |
| |
| ShaderSpec getShaderSpec (const TestParameters&) |
| { |
| ShaderSpec spec; |
| |
| spec.inputs.push_back(Symbol("texCoord", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP))); |
| spec.outputs.push_back(Symbol("result0", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP))); |
| spec.outputs.push_back(Symbol("result1", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP))); |
| |
| spec.globalDeclarations = |
| "layout(binding = 1, set = 1) uniform highp sampler2D u_image;\n" |
| "layout(binding = 0, set = 1) uniform highp sampler2D u_planeView;\n"; |
| |
| spec.source = |
| "result0 = texture(u_image, texCoord);\n" |
| "result1 = texture(u_planeView, texCoord);\n"; |
| |
| return spec; |
| } |
| |
| |
| void generateLookupCoordinates (const UVec2& imageSize, size_t numCoords, de::Random* rnd, vector<Vec2>* dst) |
| { |
| dst->resize(numCoords); |
| |
| for (size_t coordNdx = 0; coordNdx < numCoords; ++coordNdx) |
| { |
| const deUint32 texelX = rnd->getUint32() % imageSize.x(); |
| const deUint32 texelY = rnd->getUint32() % imageSize.y(); |
| const float x = ((float)texelX + 0.5f) / (float)imageSize.x(); |
| const float y = ((float)texelY + 0.5f) / (float)imageSize.y(); |
| |
| (*dst)[coordNdx] = Vec2(x, y); |
| } |
| } |
| |
| void checkImageUsageSupport (Context& context, |
| VkFormat format, |
| VkImageUsageFlags usage) |
| { |
| { |
| const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(context.getInstanceInterface(), |
| context.getPhysicalDevice(), |
| format); |
| const VkFormatFeatureFlags featureFlags = formatProperties.optimalTilingFeatures; |
| |
| if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) != 0 |
| && (featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) == 0) |
| { |
| TCU_THROW(NotSupportedError, "Format doesn't support sampling"); |
| } |
| |
| // Other image usages are not handled currently |
| DE_ASSERT((usage & ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT)) == 0); |
| } |
| } |
| |
| void checkSupport(Context& context, TestParameters params) |
| { |
| const VkFormat planeViewFormat = getPlaneCompatibleFormat(params.format, params.planeNdx); |
| const VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| |
| checkImageSupport(context, params.format, params.createFlags); |
| checkImageUsageSupport(context, params.format, usage); |
| checkImageUsageSupport(context, planeViewFormat, usage); |
| } |
| |
| tcu::TestStatus testPlaneView (Context& context, TestParameters params) |
| { |
| de::Random randomGen (deInt32Hash((deUint32)params.format) ^ |
| deInt32Hash((deUint32)params.planeNdx) ^ |
| deInt32Hash((deUint32)params.shaderType)); |
| |
| const InstanceInterface& vk = context.getInstanceInterface(); |
| const DeviceInterface& vkd = context.getDeviceInterface(); |
| const VkDevice device = context.getDevice(); |
| |
| const VkFormat format = params.format; |
| const VkImageCreateFlags createFlags = params.createFlags; |
| const VkFormat planeViewFormat = getPlaneCompatibleFormat(format, params.planeNdx); |
| const PlanarFormatDescription formatInfo = getPlanarFormatDescription(format); |
| const UVec2 size = params.size; |
| const UVec2 planeExtent = getPlaneExtent(formatInfo, size, params.planeNdx, 0); |
| const Unique<VkImage> image (createTestImage(vkd, device, format, size, createFlags)); |
| const Unique<VkImage> imageAlias ((params.viewType == TestParameters::VIEWTYPE_MEMORY_ALIAS) |
| ? createTestImage(vkd, device, planeViewFormat, planeExtent, createFlags) |
| : Move<VkImage>()); |
| const vector<AllocationSp> allocations (allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *image, format, createFlags)); |
| |
| if (imageAlias) |
| { |
| if ((createFlags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0) |
| { |
| VkBindImagePlaneMemoryInfo planeInfo = |
| { |
| VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR, |
| DE_NULL, |
| VK_IMAGE_ASPECT_PLANE_0_BIT_KHR |
| }; |
| |
| VkBindImageMemoryInfo coreInfo = |
| { |
| VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR, |
| &planeInfo, |
| *imageAlias, |
| allocations[params.planeNdx]->getMemory(), |
| allocations[params.planeNdx]->getOffset(), |
| }; |
| |
| VK_CHECK(vkd.bindImageMemory2(device, 1, &coreInfo)); |
| } |
| else |
| { |
| VK_CHECK(vkd.bindImageMemory(device, *imageAlias, allocations[params.planeNdx]->getMemory(), allocations[params.planeNdx]->getOffset())); |
| } |
| } |
| |
| const VkSamplerYcbcrConversionCreateInfo conversionInfo = |
| { |
| VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, |
| DE_NULL, |
| format, |
| VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, |
| VK_SAMPLER_YCBCR_RANGE_ITU_FULL, |
| { |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| }, |
| VK_CHROMA_LOCATION_MIDPOINT, |
| VK_CHROMA_LOCATION_MIDPOINT, |
| VK_FILTER_NEAREST, |
| VK_FALSE, // forceExplicitReconstruction |
| }; |
| const Unique<VkSamplerYcbcrConversion> conversion (createSamplerYcbcrConversion(vkd, device, &conversionInfo)); |
| const VkSamplerYcbcrConversionInfo samplerConversionInfo = |
| { |
| VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, |
| DE_NULL, |
| *conversion, |
| }; |
| const Unique<VkImageView> wholeView (createImageView(vkd, device, *image, format, VK_IMAGE_ASPECT_COLOR_BIT, &samplerConversionInfo)); |
| const Unique<VkImageView> planeView (createImageView(vkd, |
| device, |
| !imageAlias ? *image : *imageAlias, |
| planeViewFormat, |
| !imageAlias ? getPlaneAspect(params.planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT, |
| DE_NULL)); |
| |
| const VkSamplerCreateInfo wholeSamplerInfo = |
| { |
| VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, |
| &samplerConversionInfo, |
| 0u, |
| VK_FILTER_NEAREST, // magFilter |
| VK_FILTER_NEAREST, // minFilter |
| VK_SAMPLER_MIPMAP_MODE_NEAREST, // mipmapMode |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW |
| 0.0f, // mipLodBias |
| VK_FALSE, // anisotropyEnable |
| 1.0f, // maxAnisotropy |
| VK_FALSE, // compareEnable |
| VK_COMPARE_OP_ALWAYS, // compareOp |
| 0.0f, // minLod |
| 0.0f, // maxLod |
| VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor |
| VK_FALSE, // unnormalizedCoords |
| }; |
| const VkSamplerCreateInfo planeSamplerInfo = |
| { |
| VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, |
| DE_NULL, |
| 0u, |
| VK_FILTER_NEAREST, // magFilter |
| VK_FILTER_NEAREST, // minFilter |
| VK_SAMPLER_MIPMAP_MODE_NEAREST, // mipmapMode |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW |
| 0.0f, // mipLodBias |
| VK_FALSE, // anisotropyEnable |
| 1.0f, // maxAnisotropy |
| VK_FALSE, // compareEnable |
| VK_COMPARE_OP_ALWAYS, // compareOp |
| 0.0f, // minLod |
| 0.0f, // maxLod |
| VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor |
| VK_FALSE, // unnormalizedCoords |
| }; |
| |
| deUint32 combinedSamplerDescriptorCount = 1; |
| { |
| const VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = |
| { |
| VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // sType; |
| DE_NULL, // pNext; |
| format, // format; |
| VK_IMAGE_TYPE_2D, // type; |
| VK_IMAGE_TILING_OPTIMAL, // tiling; |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT | |
| VK_IMAGE_USAGE_SAMPLED_BIT, // usage; |
| createFlags // flags; |
| }; |
| |
| VkSamplerYcbcrConversionImageFormatProperties samplerYcbcrConversionImage = {}; |
| samplerYcbcrConversionImage.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES; |
| samplerYcbcrConversionImage.pNext = DE_NULL; |
| |
| VkImageFormatProperties2 imageFormatProperties = {}; |
| imageFormatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; |
| imageFormatProperties.pNext = &samplerYcbcrConversionImage; |
| |
| VK_CHECK(vk.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &imageFormatProperties)); |
| combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount; |
| } |
| |
| const Unique<VkSampler> wholeSampler(createSampler(vkd, device, &wholeSamplerInfo)); |
| const Unique<VkSampler> planeSampler(createSampler(vkd, device, &planeSamplerInfo)); |
| |
| const Unique<VkDescriptorSetLayout> descLayout (createDescriptorSetLayout(vkd, device, *wholeSampler)); |
| const Unique<VkDescriptorPool> descPool (createDescriptorPool(vkd, device, combinedSamplerDescriptorCount)); |
| const Unique<VkDescriptorSet> descSet (createDescriptorSet(vkd, device, *descPool, *descLayout, *planeView, *planeSampler, *wholeView, *wholeSampler)); |
| |
| MultiPlaneImageData imageData (format, size); |
| |
| // Prepare texture data |
| fillRandom(&randomGen, &imageData); |
| |
| if (imageAlias) |
| { |
| // Transition alias to right layout first |
| const VkImageMemoryBarrier initAliasBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, |
| DE_NULL, |
| (VkAccessFlags)0, |
| VK_ACCESS_SHADER_READ_BIT, |
| VK_IMAGE_LAYOUT_UNDEFINED, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, |
| VK_QUEUE_FAMILY_IGNORED, |
| VK_QUEUE_FAMILY_IGNORED, |
| *imageAlias, |
| { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } |
| }; |
| |
| executeImageBarrier(vkd, |
| device, |
| context.getUniversalQueueFamilyIndex(), |
| (VkPipelineStageFlags)VK_PIPELINE_STAGE_HOST_BIT, |
| (VkPipelineStageFlags)VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, |
| initAliasBarrier); |
| } |
| |
| // Upload and prepare image |
| uploadImage(vkd, |
| device, |
| context.getUniversalQueueFamilyIndex(), |
| context.getDefaultAllocator(), |
| *image, |
| imageData, |
| (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); |
| |
| { |
| const size_t numValues = 500; |
| vector<Vec2> texCoord (numValues); |
| vector<Vec4> resultWhole (numValues); |
| vector<Vec4> resultPlane (numValues); |
| vector<Vec4> referenceWhole (numValues); |
| vector<Vec4> referencePlane (numValues); |
| bool allOk = true; |
| Vec4 threshold (0.02f); |
| |
| generateLookupCoordinates(size, numValues, &randomGen, &texCoord); |
| |
| { |
| UniquePtr<ShaderExecutor> executor (createExecutor(context, params.shaderType, getShaderSpec(params), *descLayout)); |
| const void* inputs[] = { texCoord[0].getPtr() }; |
| void* outputs[] = { resultWhole[0].getPtr(), resultPlane[0].getPtr() }; |
| |
| executor->execute((int)numValues, inputs, outputs, *descSet); |
| } |
| |
| // Whole image sampling reference |
| for (deUint32 channelNdx = 0; channelNdx < 4; channelNdx++) |
| { |
| if (formatInfo.hasChannelNdx(channelNdx)) |
| { |
| const tcu::ConstPixelBufferAccess channelAccess = imageData.getChannelAccess(channelNdx); |
| const tcu::Sampler refSampler = mapVkSampler(wholeSamplerInfo); |
| const tcu::Texture2DView refTexView (1u, &channelAccess); |
| |
| for (size_t ndx = 0; ndx < numValues; ++ndx) |
| { |
| const Vec2& coord = texCoord[ndx]; |
| referenceWhole[ndx][channelNdx] = refTexView.sample(refSampler, coord.x(), coord.y(), 0.0f)[0]; |
| } |
| } |
| else |
| { |
| for (size_t ndx = 0; ndx < numValues; ++ndx) |
| referenceWhole[ndx][channelNdx] = channelNdx == 3 ? 1.0f : 0.0f; |
| } |
| } |
| |
| // Plane view sampling reference |
| { |
| const tcu::ConstPixelBufferAccess planeAccess (mapVkFormat(planeViewFormat), |
| tcu::IVec3((int)planeExtent.x(), (int)planeExtent.y(), 1), |
| imageData.getPlanePtr(params.planeNdx)); |
| const tcu::Sampler refSampler = mapVkSampler(planeSamplerInfo); |
| const tcu::Texture2DView refTexView (1u, &planeAccess); |
| |
| for (size_t ndx = 0; ndx < numValues; ++ndx) |
| { |
| const Vec2& coord = texCoord[ndx]; |
| referencePlane[ndx] = refTexView.sample(refSampler, coord.x(), coord.y(), 0.0f); |
| } |
| } |
| |
| for (int viewNdx = 0; viewNdx < 2; ++viewNdx) |
| { |
| const char* const viewName = (viewNdx == 0) ? "complete image" : "plane view"; |
| const vector<Vec4>& reference = (viewNdx == 0) ? referenceWhole : referencePlane; |
| const vector<Vec4>& result = (viewNdx == 0) ? resultWhole : resultPlane; |
| |
| for (size_t ndx = 0; ndx < numValues; ++ndx) |
| { |
| if (boolAny(greaterThanEqual(abs(result[ndx] - reference[ndx]), threshold))) |
| { |
| context.getTestContext().getLog() |
| << TestLog::Message << "ERROR: When sampling " << viewName << " at " << texCoord[ndx] |
| << ": got " << result[ndx] |
| << ", expected " << reference[ndx] |
| << TestLog::EndMessage; |
| allOk = false; |
| } |
| } |
| } |
| |
| if (allOk) |
| return tcu::TestStatus::pass("All samples passed"); |
| else |
| return tcu::TestStatus::fail("Got invalid results"); |
| } |
| } |
| |
| void initPrograms (SourceCollections& dst, TestParameters params) |
| { |
| const ShaderSpec spec = getShaderSpec(params); |
| |
| generateSources(params.shaderType, spec, dst); |
| } |
| |
| void addPlaneViewCase (tcu::TestCaseGroup* group, const TestParameters& params) |
| { |
| std::ostringstream name; |
| |
| name << de::toLower(de::toString(params.format).substr(10)); |
| |
| if ((params.viewType != TestParameters::VIEWTYPE_MEMORY_ALIAS) && |
| ((params.createFlags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0)) |
| name << "_disjoint"; |
| |
| name << "_plane_" << params.planeNdx; |
| |
| addFunctionCaseWithPrograms(group, name.str(), "", checkSupport, initPrograms, testPlaneView, params); |
| } |
| |
| void populateViewTypeGroup (tcu::TestCaseGroup* group, TestParameters::ViewType viewType) |
| { |
| const glu::ShaderType shaderType = glu::SHADERTYPE_FRAGMENT; |
| const UVec2 size (32, 58); |
| const VkImageCreateFlags baseFlags = (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
| | (viewType == TestParameters::VIEWTYPE_MEMORY_ALIAS ? (VkImageCreateFlags)VK_IMAGE_CREATE_ALIAS_BIT : 0u); |
| |
| for (int formatNdx = VK_YCBCR_FORMAT_FIRST; formatNdx < VK_YCBCR_FORMAT_LAST; formatNdx++) |
| { |
| const VkFormat format = (VkFormat)formatNdx; |
| const deUint32 numPlanes = getPlaneCount(format); |
| |
| if (numPlanes == 1) |
| continue; // Plane views not possible |
| |
| for (int isDisjoint = 0; isDisjoint < 2; ++isDisjoint) |
| { |
| const VkImageCreateFlags flags = baseFlags | (isDisjoint == 1 ? (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT : 0u); |
| |
| if ((viewType == TestParameters::VIEWTYPE_MEMORY_ALIAS) && |
| ((flags & VK_IMAGE_CREATE_DISJOINT_BIT) == 0)) |
| continue; // Memory alias cases require disjoint planes |
| |
| for (deUint32 planeNdx = 0; planeNdx < numPlanes; ++planeNdx) |
| addPlaneViewCase(group, TestParameters(viewType, format, size, flags, planeNdx, shaderType)); |
| } |
| } |
| } |
| |
| void populateViewGroup (tcu::TestCaseGroup* group) |
| { |
| addTestGroup(group, "image_view", "Plane View via VkImageView", populateViewTypeGroup, TestParameters::VIEWTYPE_IMAGE_VIEW); |
| addTestGroup(group, "memory_alias", "Plane View via Memory Aliasing", populateViewTypeGroup, TestParameters::VIEWTYPE_MEMORY_ALIAS); |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createViewTests (tcu::TestContext& testCtx) |
| { |
| return createTestGroup(testCtx, "plane_view", "YCbCr Plane View Tests", populateViewGroup); |
| } |
| |
| } // ycbcr |
| } // vkt |
| |