xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/ycbcr/vktYCbCrImageOffsetTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief YCbCr image offset tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktYCbCrImageOffsetTests.hpp"
25 
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vktYCbCrUtil.hpp"
29 
30 #include "vkQueryUtil.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 
34 #include <string>
35 #include <vector>
36 
37 using tcu::TestLog;
38 using tcu::UVec2;
39 
40 using std::string;
41 using std::vector;
42 
43 using namespace vk;
44 
45 namespace vkt
46 {
47 namespace ycbcr
48 {
49 namespace
50 {
51 
52 struct TestConfig
53 {
TestConfigvkt::ycbcr::__anon5cd66ffc0111::TestConfig54     TestConfig(const vk::VkFormat format_) : format(format_)
55     {
56     }
57     vk::VkFormat format;
58 };
59 
checkSupport(Context & context,const TestConfig config)60 void checkSupport(Context &context, const TestConfig config)
61 {
62     context.requireDeviceFunctionality("VK_KHR_sampler_ycbcr_conversion"); // Required for image query
63     const vk::VkFormatProperties properties = vk::getPhysicalDeviceFormatProperties(
64         context.getInstanceInterface(), context.getPhysicalDevice(), config.format);
65 
66     if ((properties.linearTilingFeatures & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0)
67         TCU_THROW(NotSupportedError, "Format doesn't support disjoint planes");
68 }
69 
createImage(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format,const UVec2 & size)70 vk::Move<vk::VkImage> createImage(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkFormat format,
71                                   const UVec2 &size)
72 {
73     const vk::VkImageCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
74                                               DE_NULL,
75                                               vk::VK_IMAGE_CREATE_DISJOINT_BIT,
76                                               vk::VK_IMAGE_TYPE_2D,
77                                               format,
78                                               vk::makeExtent3D(size.x(), size.y(), 1u),
79                                               1u,
80                                               1u,
81                                               vk::VK_SAMPLE_COUNT_1_BIT,
82                                               vk::VK_IMAGE_TILING_LINEAR,
83                                               vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
84                                               vk::VK_SHARING_MODE_EXCLUSIVE,
85                                               0u,
86                                               (const uint32_t *)DE_NULL,
87                                               vk::VK_IMAGE_LAYOUT_PREINITIALIZED};
88 
89     return vk::createImage(vkd, device, &createInfo);
90 }
91 
imageOffsetTest(Context & context,const TestConfig config)92 tcu::TestStatus imageOffsetTest(Context &context, const TestConfig config)
93 {
94     const vk::DeviceInterface &vkd(context.getDeviceInterface());
95     const vk::VkDevice device(context.getDevice());
96 
97     const vk::Unique<vk::VkImage> srcImage(createImage(vkd, device, config.format, UVec2(8u, 8u)));
98     const vk::MemoryRequirement srcMemoryRequirement(vk::MemoryRequirement::HostVisible);
99     vector<AllocationSp> srcImageMemory;
100 
101     const uint32_t numPlanes = getPlaneCount(config.format);
102     vector<vk::VkBindImageMemoryInfo> coreInfos;
103     vector<vk::VkBindImagePlaneMemoryInfo> planeInfos;
104 
105     coreInfos.reserve(numPlanes);
106     planeInfos.reserve(numPlanes);
107 
108     for (uint32_t planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
109     {
110         const vk::VkImageAspectFlagBits planeAspect =
111             (vk::VkImageAspectFlagBits)(vk::VK_IMAGE_ASPECT_PLANE_0_BIT << planeNdx);
112         vk::VkMemoryRequirements reqs = getImagePlaneMemoryRequirements(vkd, device, srcImage.get(), planeAspect);
113         const VkDeviceSize offset     = deAlign64(reqs.size, reqs.alignment);
114         reqs.size *= 2;
115 
116         srcImageMemory.push_back(
117             AllocationSp(context.getDefaultAllocator().allocate(reqs, srcMemoryRequirement).release()));
118 
119         vk::VkBindImagePlaneMemoryInfo planeInfo = {vk::VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, DE_NULL,
120                                                     planeAspect};
121         planeInfos.push_back(planeInfo);
122 
123         vk::VkBindImageMemoryInfo coreInfo = {
124             vk::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
125             &planeInfos.back(),
126             srcImage.get(),
127             srcImageMemory.back()->getMemory(),
128             offset,
129         };
130         coreInfos.push_back(coreInfo);
131     }
132 
133     VK_CHECK(vkd.bindImageMemory2(device, numPlanes, coreInfos.data()));
134 
135     vk::VkImageAspectFlags aspectMasks[3] = {vk::VK_IMAGE_ASPECT_PLANE_0_BIT, vk::VK_IMAGE_ASPECT_PLANE_1_BIT,
136                                              vk::VK_IMAGE_ASPECT_PLANE_2_BIT};
137     for (uint32_t i = 0; i < numPlanes; i++)
138     {
139         vk::VkSubresourceLayout subresourceLayout;
140         auto subresource = vk::makeImageSubresource(aspectMasks[i], 0u, 0u);
141         vkd.getImageSubresourceLayout(device, srcImage.get(), &subresource, &subresourceLayout);
142 
143         // VkSubresourceLayout::offset is the byte offset from the start of the image or the plane
144         // where the image subresource begins. For disjoint images, it should be 0 since each plane
145         // has been separately bound to memory.
146         if (subresourceLayout.offset != 0)
147             return tcu::TestStatus::fail("Failed, subresource layout offset != 0");
148     }
149 
150     return tcu::TestStatus::pass("Pass");
151 }
152 
initYcbcrImageOffsetTests(tcu::TestCaseGroup * testGroup)153 void initYcbcrImageOffsetTests(tcu::TestCaseGroup *testGroup)
154 {
155     const vk::VkFormat ycbcrFormats[] = {
156         vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
157         vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
158         vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
159         vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
160         vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
161         vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
162         vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
163         vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
164         vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
165         vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
166         vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
167         vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
168         vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
169         vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
170         vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
171         vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
172         vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
173         vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
174         vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
175         vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
176 #ifndef CTS_USES_VULKANSC
177         vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM,
178         vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16,
179         vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16,
180         vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM,
181 #endif // CTS_USES_VULKANSC
182     };
183 
184     for (int i = 0; i < DE_LENGTH_OF_ARRAY(ycbcrFormats); i++)
185     {
186         const vk::VkFormat srcFormat(ycbcrFormats[i]);
187         const string srcFormatName(de::toLower(std::string(getFormatName(srcFormat)).substr(10)));
188 
189         const TestConfig config(srcFormat);
190         addFunctionCase(testGroup, srcFormatName.c_str(), checkSupport, imageOffsetTest, config);
191     }
192 }
193 
194 } // namespace
195 
createImageOffsetTests(tcu::TestContext & testCtx)196 tcu::TestCaseGroup *createImageOffsetTests(tcu::TestContext &testCtx)
197 {
198     return createTestGroup(testCtx, "subresource_offset", initYcbcrImageOffsetTests);
199 }
200 
201 } // namespace ycbcr
202 } // namespace vkt
203