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