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::UVec2;
38 using tcu::TestLog;
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::__anon5213b3120111::TestConfig54 TestConfig (const vk::VkFormat format_) : format (format_) {}
55 vk::VkFormat format;
56 };
57
checkSupport(Context & context,const TestConfig config)58 void checkSupport (Context& context, const TestConfig config)
59 {
60 const vk::VkFormatProperties properties = vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
61 context.getPhysicalDevice(), config.format);
62
63 if ((properties.linearTilingFeatures & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0)
64 TCU_THROW(NotSupportedError, "Format doesn't support disjoint planes");
65 }
66
createImage(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format,const UVec2 & size)67 vk::Move<vk::VkImage> createImage (const vk::DeviceInterface& vkd,
68 vk::VkDevice device,
69 vk::VkFormat format,
70 const UVec2& size)
71 {
72 const vk::VkImageCreateInfo createInfo =
73 {
74 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
75 DE_NULL,
76 vk::VK_IMAGE_CREATE_DISJOINT_BIT,
77 vk::VK_IMAGE_TYPE_2D,
78 format,
79 vk::makeExtent3D(size.x(), size.y(), 1u),
80 1u,
81 1u,
82 vk::VK_SAMPLE_COUNT_1_BIT,
83 vk::VK_IMAGE_TILING_LINEAR,
84 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
85 vk::VK_SHARING_MODE_EXCLUSIVE,
86 0u,
87 (const deUint32*)DE_NULL,
88 vk::VK_IMAGE_LAYOUT_PREINITIALIZED
89 };
90
91 return vk::createImage(vkd, device, &createInfo);
92 }
93
imageOffsetTest(Context & context,const TestConfig config)94 tcu::TestStatus imageOffsetTest (Context& context, const TestConfig config)
95 {
96 const vk::DeviceInterface& vkd (context.getDeviceInterface());
97 const vk::VkDevice device (context.getDevice());
98
99 const vk::Unique<vk::VkImage> srcImage (createImage(vkd, device, config.format, UVec2(8u, 8u)));
100 const vk::MemoryRequirement srcMemoryRequirement (vk::MemoryRequirement::HostVisible);
101 vector<AllocationSp> srcImageMemory;
102
103 const deUint32 numPlanes = getPlaneCount(config.format);
104 vector<vk::VkBindImageMemoryInfo> coreInfos;
105 vector<vk::VkBindImagePlaneMemoryInfo> planeInfos;
106
107 coreInfos.reserve(numPlanes);
108 planeInfos.reserve(numPlanes);
109
110 for (deUint32 planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
111 {
112 const vk::VkImageAspectFlagBits planeAspect = (vk::VkImageAspectFlagBits)(vk::VK_IMAGE_ASPECT_PLANE_0_BIT << planeNdx);
113 vk::VkMemoryRequirements reqs = getImagePlaneMemoryRequirements(vkd, device, srcImage.get(), planeAspect);
114 const VkDeviceSize offset = deAlign64(reqs.size, reqs.alignment);
115 reqs.size *= 2;
116
117 srcImageMemory.push_back(AllocationSp(context.getDefaultAllocator().allocate(reqs, srcMemoryRequirement).release()));
118
119 vk::VkBindImagePlaneMemoryInfo planeInfo =
120 {
121 vk::VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO,
122 DE_NULL,
123 planeAspect
124 };
125 planeInfos.push_back(planeInfo);
126
127 vk::VkBindImageMemoryInfo coreInfo =
128 {
129 vk::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
130 &planeInfos.back(),
131 srcImage.get(),
132 srcImageMemory.back()->getMemory(),
133 offset,
134 };
135 coreInfos.push_back(coreInfo);
136 }
137
138 VK_CHECK(vkd.bindImageMemory2(device, numPlanes, coreInfos.data()));
139
140 vk::VkImageAspectFlags aspectMasks[3] = {vk::VK_IMAGE_ASPECT_PLANE_0_BIT, vk::VK_IMAGE_ASPECT_PLANE_1_BIT,
141 vk::VK_IMAGE_ASPECT_PLANE_2_BIT};
142 for (deUint32 i = 0; i < numPlanes; i++)
143 {
144 vk::VkSubresourceLayout subresourceLayout;
145 auto subresource = vk::makeImageSubresource(aspectMasks[i], 0u, 0u);
146 vkd.getImageSubresourceLayout(device, srcImage.get(), &subresource, &subresourceLayout);
147
148 // VkSubresourceLayout::offset is the byte offset from the start of the image or the plane
149 // where the image subresource begins. For disjoint images, it should be 0 since each plane
150 // has been separately bound to memory.
151 if (subresourceLayout.offset != 0)
152 return tcu::TestStatus::fail("Failed, subresource layout offset != 0");
153 }
154
155 return tcu::TestStatus::pass("Pass");
156 }
157
initYcbcrImageOffsetTests(tcu::TestCaseGroup * testGroup)158 void initYcbcrImageOffsetTests (tcu::TestCaseGroup* testGroup)
159 {
160 const vk::VkFormat ycbcrFormats[] =
161 {
162 vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
163 vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
164 vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
165 vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
166 vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
167 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
168 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
169 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
170 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
171 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
172 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
173 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
174 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
175 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
176 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
177 vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
178 vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
179 vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
180 vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
181 vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
182 #ifndef CTS_USES_VULKANSC
183 vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM,
184 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16,
185 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16,
186 vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM,
187 #endif // CTS_USES_VULKANSC
188 };
189
190 for (int i = 0; i < DE_LENGTH_OF_ARRAY(ycbcrFormats); i++)
191 {
192 const vk::VkFormat srcFormat (ycbcrFormats[i]);
193 const string srcFormatName (de::toLower(std::string(getFormatName(srcFormat)).substr(10)));
194
195 const TestConfig config (srcFormat);
196 addFunctionCase(testGroup, srcFormatName.c_str(), "", checkSupport, imageOffsetTest, config);
197 }
198 }
199
200 } // anonymous
201
createImageOffsetTests(tcu::TestContext & testCtx)202 tcu::TestCaseGroup* createImageOffsetTests (tcu::TestContext& testCtx)
203 {
204 return createTestGroup(testCtx, "subresource_offset", "Subresourcelayout::offset tests for YCbCr images", initYcbcrImageOffsetTests);
205 }
206
207 } // ycbcr
208 } // vkt