1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 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 Texture color conversion tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktYCbCrConversionTests.hpp"
25
26 #include "vktShaderExecutor.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vktYCbCrUtil.hpp"
30
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkQueryUtil.hpp"
37
38 #include "tcuInterval.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuTexture.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "tcuVector.hpp"
43 #include "tcuVectorUtil.hpp"
44 #include "tcuFloatFormat.hpp"
45 #include "tcuFloat.hpp"
46 #include "tcuCommandLine.hpp"
47
48 #include "deRandom.hpp"
49 #include "deSTLUtil.hpp"
50 #include "deSharedPtr.hpp"
51
52 #include "deMath.h"
53 #include "deFloat16.h"
54
55 #include <vector>
56 #include <iomanip>
57
58 // \todo When defined color conversion extension is not used and conversion is performed in the shader
59 // #define FAKE_COLOR_CONVERSION
60
61 using tcu::Vec2;
62 using tcu::Vec4;
63
64 using tcu::UVec2;
65 using tcu::UVec4;
66
67 using tcu::IVec2;
68 using tcu::IVec3;
69 using tcu::IVec4;
70
71 using tcu::TestLog;
72 using tcu::FloatFormat;
73
74 using std::vector;
75 using std::string;
76
77 using namespace vkt::shaderexecutor;
78
79 namespace vkt
80 {
81 namespace ycbcr
82 {
83 namespace
84 {
85
86 template<typename T>
makeSharedPtr(vk::Move<T> move)87 inline de::SharedPtr<vk::Unique<T> > makeSharedPtr(vk::Move<T> move)
88 {
89 return de::SharedPtr<vk::Unique<T> >(new vk::Unique<T>(move));
90 }
91
createShaderSpec(deUint32 samplerBinding,const std::vector<vk::VkSamplerYcbcrModelConversion> & colorModels)92 ShaderSpec createShaderSpec (deUint32 samplerBinding, const std::vector<vk::VkSamplerYcbcrModelConversion>& colorModels)
93 {
94 ShaderSpec spec;
95
96 spec.inputs.push_back(Symbol("uv", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
97 // shader with single sampler
98 if (colorModels.size()==1)
99 {
100 spec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=" + de::toString(samplerBinding) + ") uniform highp sampler2D u_sampler;";
101
102 spec.outputs.push_back(Symbol("o_color", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
103
104 spec.source = "o_color = texture(u_sampler, uv);\n";
105 }
106 else // shader with array of samplers
107 {
108 spec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=" + de::toString(samplerBinding) + ") uniform highp sampler2D u_sampler[" + de::toString(colorModels.size()) + "];";
109
110 for (int i = 0; i < (int)colorModels.size(); i++)
111 {
112 spec.outputs.push_back(Symbol(string("o_color") + de::toString(i), glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
113
114 spec.source += string("o_color") + de::toString(i) + " = texture(u_sampler[" + de::toString(i) + "], uv);\n";
115 }
116 }
117 return spec;
118 }
119
genTexCoords(std::vector<Vec2> & coords,const UVec2 & srcSize,const UVec2 & dstSize)120 void genTexCoords (std::vector<Vec2>& coords,
121 const UVec2& srcSize,
122 const UVec2& dstSize)
123 {
124 for (deUint32 y = 0; y < dstSize.y(); y++)
125 for (deUint32 x = 0; x < dstSize.x(); x++)
126 {
127 const float fx = (float)x;
128 const float fy = (float)y;
129
130 const float fw = (float)srcSize.x();
131 const float fh = (float)srcSize.y();
132
133 const float s = 1.5f * ((fx * 1.5f * fw + fx) / (1.5f * fw * 1.5f * fw)) - 0.25f;
134 const float t = 1.5f * ((fy * 1.5f * fh + fy) / (1.5f * fh * 1.5f * fh)) - 0.25f;
135
136 coords.push_back(Vec2(s, t));
137 }
138 }
139
genOneToOneTexCoords(std::vector<Vec2> & coords,const UVec2 & size)140 void genOneToOneTexCoords (std::vector<Vec2>& coords,
141 const UVec2& size)
142 {
143 for (deUint32 y = 0; y < size.y(); y++)
144 for (deUint32 x = 0; x < size.x(); x++)
145 {
146 const float s = ((float)x + 0.5f) / (float)size.x();
147 const float t = ((float)y + 0.5f) / (float)size.y();
148
149 coords.push_back(Vec2(s, t));
150 }
151 }
152
153 struct TestConfig
154 {
TestConfigvkt::ycbcr::__anoned4a6e000111::TestConfig155 TestConfig (glu::ShaderType shaderType_,
156 vk::VkFormat format_,
157 vk::VkImageTiling imageTiling_,
158 vk::VkFilter textureFilter_,
159 vk::VkSamplerAddressMode addressModeU_,
160 vk::VkSamplerAddressMode addressModeV_,
161
162 vk::VkFilter chromaFilter_,
163 vk::VkChromaLocation xChromaOffset_,
164 vk::VkChromaLocation yChromaOffset_,
165 bool explicitReconstruction_,
166 bool disjoint_,
167
168 vk::VkSamplerYcbcrRange colorRange_,
169 vk::VkSamplerYcbcrModelConversion colorModel_,
170 vk::VkComponentMapping componentMapping_,
171 const UVec2 srcSize_,
172 const UVec2 dstSize_,
173 deUint32 samplerBinding_)
174 : shaderType (shaderType_)
175 , format (format_)
176 , imageTiling (imageTiling_)
177 , textureFilter (textureFilter_)
178 , addressModeU (addressModeU_)
179 , addressModeV (addressModeV_)
180
181 , chromaFilter (chromaFilter_)
182 , xChromaOffset (xChromaOffset_)
183 , yChromaOffset (yChromaOffset_)
184 , explicitReconstruction (explicitReconstruction_)
185 , disjoint (disjoint_)
186
187 , colorRange (colorRange_)
188 , colorModel (colorModel_)
189 , componentMapping (componentMapping_)
190 , srcSize (srcSize_)
191 , dstSize (dstSize_)
192 , samplerBinding (samplerBinding_)
193 {
194 }
195
196 glu::ShaderType shaderType;
197 vk::VkFormat format;
198 vk::VkImageTiling imageTiling;
199 vk::VkFilter textureFilter;
200 vk::VkSamplerAddressMode addressModeU;
201 vk::VkSamplerAddressMode addressModeV;
202
203 vk::VkFilter chromaFilter;
204 vk::VkChromaLocation xChromaOffset;
205 vk::VkChromaLocation yChromaOffset;
206 bool explicitReconstruction;
207 bool disjoint;
208
209 vk::VkSamplerYcbcrRange colorRange;
210 vk::VkSamplerYcbcrModelConversion colorModel;
211 vk::VkComponentMapping componentMapping;
212 const UVec2 srcSize;
213 const UVec2 dstSize;
214 deUint32 samplerBinding;
215 };
216
createDescriptorSetLayout(const vk::DeviceInterface & vkd,vk::VkDevice device,const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler>>> & samplers,deUint32 samplerBinding)217 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vkd,
218 vk::VkDevice device,
219 const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >& samplers,
220 deUint32 samplerBinding)
221 {
222 std::vector<vk::VkSampler> sampler;
223 for (size_t i = 0; i < samplers.size(); i++)
224 sampler.push_back(samplers[i]->get());
225 const vk::VkDescriptorSetLayoutBinding layoutBindings[] =
226 {
227 {
228 samplerBinding,
229 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
230 (deUint32)sampler.size(),
231 vk::VK_SHADER_STAGE_ALL,
232 sampler.data()
233 }
234 };
235 const vk::VkDescriptorSetLayoutCreateInfo layoutCreateInfo =
236 {
237 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
238 DE_NULL,
239
240 0u,
241 DE_LENGTH_OF_ARRAY(layoutBindings),
242 layoutBindings
243 };
244
245 return vk::createDescriptorSetLayout(vkd, device, &layoutCreateInfo);
246 }
247
createDescriptorPool(const vk::DeviceInterface & vkd,vk::VkDevice device,const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler>>> & samplers,const deUint32 combinedSamplerDescriptorCount)248 vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vkd,
249 vk::VkDevice device,
250 const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >& samplers,
251 const deUint32 combinedSamplerDescriptorCount)
252 {
253 const vk::VkDescriptorPoolSize poolSizes[] =
254 {
255 { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, (deUint32)samplers.size() * combinedSamplerDescriptorCount }
256 };
257 const vk::VkDescriptorPoolCreateInfo descriptorPoolCreateInfo =
258 {
259 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
260 DE_NULL,
261 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
262
263 1u,
264 DE_LENGTH_OF_ARRAY(poolSizes),
265 poolSizes
266 };
267
268 return createDescriptorPool(vkd, device, &descriptorPoolCreateInfo);
269 }
270
createDescriptorSet(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDescriptorPool descriptorPool,vk::VkDescriptorSetLayout layout,const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler>>> & samplers,const std::vector<de::SharedPtr<vk::Unique<vk::VkImageView>>> & imageViews,deUint32 samplerBinding)271 vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vkd,
272 vk::VkDevice device,
273 vk::VkDescriptorPool descriptorPool,
274 vk::VkDescriptorSetLayout layout,
275 const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >& samplers,
276 const std::vector<de::SharedPtr<vk::Unique<vk::VkImageView> > >& imageViews,
277 deUint32 samplerBinding)
278 {
279 const vk::VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
280 {
281 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
282 DE_NULL,
283
284 descriptorPool,
285 1u,
286 &layout
287 };
288 vk::Move<vk::VkDescriptorSet> descriptorSet (vk::allocateDescriptorSet(vkd, device, &descriptorSetAllocateInfo));
289 std::vector<vk::VkDescriptorImageInfo> imageInfo;
290 for (size_t i = 0; i < samplers.size(); i++)
291 {
292 const vk::VkDescriptorImageInfo ii =
293 {
294 samplers[i]->get(),
295 imageViews[i]->get(),
296 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
297 };
298 imageInfo.push_back(ii);
299 }
300
301 {
302 const vk::VkWriteDescriptorSet writes[] =
303 {
304 {
305 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
306 DE_NULL,
307
308 *descriptorSet,
309 samplerBinding,
310 0u,
311 (deUint32)imageInfo.size(),
312 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
313 imageInfo.data(),
314 DE_NULL,
315 DE_NULL
316 }
317 };
318
319 vkd.updateDescriptorSets(device, DE_LENGTH_OF_ARRAY(writes), writes, 0u, DE_NULL);
320 }
321
322 return descriptorSet;
323 }
324
createSampler(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFilter textureFilter,vk::VkSamplerAddressMode addressModeU,vk::VkSamplerAddressMode addressModeV,vk::VkSamplerYcbcrConversion conversion)325 vk::Move<vk::VkSampler> createSampler (const vk::DeviceInterface& vkd,
326 vk::VkDevice device,
327 vk::VkFilter textureFilter,
328 vk::VkSamplerAddressMode addressModeU,
329 vk::VkSamplerAddressMode addressModeV,
330 vk::VkSamplerYcbcrConversion conversion)
331 {
332 #if !defined(FAKE_COLOR_CONVERSION)
333 const vk::VkSamplerYcbcrConversionInfo samplerConversionInfo =
334 {
335 vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
336 DE_NULL,
337 conversion
338 };
339 #else
340 DE_UNREF(conversion);
341 #endif
342 const vk::VkSamplerCreateInfo createInfo =
343 {
344 vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
345 #if !defined(FAKE_COLOR_CONVERSION)
346 &samplerConversionInfo,
347 #else
348 DE_NULL,
349 #endif
350
351 0u,
352 textureFilter,
353 textureFilter,
354 vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,
355 addressModeU,
356 addressModeV,
357 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
358 0.0f,
359 VK_FALSE,
360 1.0f,
361 VK_FALSE,
362 vk::VK_COMPARE_OP_ALWAYS,
363 0.0f,
364 0.0f,
365 vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
366 VK_FALSE,
367 };
368
369 return createSampler(vkd, device, &createInfo);
370 }
371
createImage(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format,const UVec2 & size,bool disjoint,vk::VkImageTiling tiling)372 vk::Move<vk::VkImage> createImage (const vk::DeviceInterface& vkd,
373 vk::VkDevice device,
374 vk::VkFormat format,
375 const UVec2& size,
376 bool disjoint,
377 vk::VkImageTiling tiling)
378 {
379 const vk::VkImageCreateInfo createInfo =
380 {
381 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
382 DE_NULL,
383 disjoint ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlags)0u,
384
385 vk::VK_IMAGE_TYPE_2D,
386 format,
387 vk::makeExtent3D(size.x(), size.y(), 1u),
388 1u,
389 1u,
390 vk::VK_SAMPLE_COUNT_1_BIT,
391 tiling,
392 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT,
393 vk::VK_SHARING_MODE_EXCLUSIVE,
394 0u,
395 (const deUint32*)DE_NULL,
396 vk::VK_IMAGE_LAYOUT_PREINITIALIZED,
397 };
398
399 return vk::createImage(vkd, device, &createInfo);
400 }
401
createImageView(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,vk::VkFormat format,vk::VkSamplerYcbcrConversion conversion)402 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vkd,
403 vk::VkDevice device,
404 vk::VkImage image,
405 vk::VkFormat format,
406 vk::VkSamplerYcbcrConversion conversion)
407 {
408 // Both mappings should be equivalent: alternate between the two for different formats.
409 const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
410 const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
411 const vk::VkComponentMapping& mapping = ((static_cast<int>(format) % 2 == 0) ? mappingA : mappingB);
412
413 #if !defined(FAKE_COLOR_CONVERSION)
414 const vk::VkSamplerYcbcrConversionInfo conversionInfo =
415 {
416 vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
417 DE_NULL,
418 conversion
419 };
420 #else
421 DE_UNREF(conversion);
422 #endif
423 const vk::VkImageViewCreateInfo viewInfo =
424 {
425 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
426 #if defined(FAKE_COLOR_CONVERSION)
427 DE_NULL,
428 #else
429 &conversionInfo,
430 #endif
431 (vk::VkImageViewCreateFlags)0,
432
433 image,
434 vk::VK_IMAGE_VIEW_TYPE_2D,
435 format,
436 mapping,
437 { vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },
438 };
439
440 return vk::createImageView(vkd, device, &viewInfo);
441 }
442
createConversion(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format,vk::VkSamplerYcbcrModelConversion colorModel,vk::VkSamplerYcbcrRange colorRange,vk::VkChromaLocation xChromaOffset,vk::VkChromaLocation yChromaOffset,vk::VkFilter chromaFilter,const vk::VkComponentMapping & componentMapping,bool explicitReconstruction)443 vk::Move<vk::VkSamplerYcbcrConversion> createConversion (const vk::DeviceInterface& vkd,
444 vk::VkDevice device,
445 vk::VkFormat format,
446 vk::VkSamplerYcbcrModelConversion colorModel,
447 vk::VkSamplerYcbcrRange colorRange,
448 vk::VkChromaLocation xChromaOffset,
449 vk::VkChromaLocation yChromaOffset,
450 vk::VkFilter chromaFilter,
451 const vk::VkComponentMapping& componentMapping,
452 bool explicitReconstruction)
453 {
454 const vk::VkSamplerYcbcrConversionCreateInfo conversionInfo =
455 {
456 vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
457 DE_NULL,
458
459 format,
460 colorModel,
461 colorRange,
462 componentMapping,
463 xChromaOffset,
464 yChromaOffset,
465 chromaFilter,
466 explicitReconstruction ? VK_TRUE : VK_FALSE
467 };
468
469 return vk::createSamplerYcbcrConversion(vkd, device, &conversionInfo);
470 }
471
evalShader(Context & context,glu::ShaderType shaderType,const MultiPlaneImageData & imageData,const UVec2 & size,vk::VkFormat format,vk::VkImageTiling imageTiling,bool disjoint,vk::VkFilter textureFilter,vk::VkSamplerAddressMode addressModeU,vk::VkSamplerAddressMode addressModeV,const std::vector<vk::VkSamplerYcbcrModelConversion> & colorModels,vk::VkSamplerYcbcrRange colorRange,vk::VkChromaLocation xChromaOffset,vk::VkChromaLocation yChromaOffset,vk::VkFilter chromaFilter,const vk::VkComponentMapping & componentMapping,bool explicitReconstruction,const vector<Vec2> & sts,deUint32 samplerBinding,vector<vector<Vec4>> & results)472 void evalShader (Context& context,
473 glu::ShaderType shaderType,
474 const MultiPlaneImageData& imageData,
475 const UVec2& size,
476 vk::VkFormat format,
477 vk::VkImageTiling imageTiling,
478 bool disjoint,
479 vk::VkFilter textureFilter,
480 vk::VkSamplerAddressMode addressModeU,
481 vk::VkSamplerAddressMode addressModeV,
482 const std::vector<vk::VkSamplerYcbcrModelConversion>& colorModels,
483 vk::VkSamplerYcbcrRange colorRange,
484 vk::VkChromaLocation xChromaOffset,
485 vk::VkChromaLocation yChromaOffset,
486 vk::VkFilter chromaFilter,
487 const vk::VkComponentMapping& componentMapping,
488 bool explicitReconstruction,
489 const vector<Vec2>& sts,
490 deUint32 samplerBinding,
491 vector<vector<Vec4> >& results)
492 {
493 const vk::InstanceInterface& vk (context.getInstanceInterface());
494 const vk::DeviceInterface& vkd (context.getDeviceInterface());
495 const vk::VkDevice device (context.getDevice());
496 std::vector<de::SharedPtr<vk::Unique<vk::VkSamplerYcbcrConversion> > > conversions;
497 std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > > samplers;
498 #if !defined(FAKE_COLOR_CONVERSION)
499 for (int i = 0; i < (int)colorModels.size(); i++)
500 {
501 conversions.push_back(makeSharedPtr(createConversion(vkd, device, format, colorModels[i], colorRange, xChromaOffset, yChromaOffset, chromaFilter, componentMapping, explicitReconstruction)));
502 samplers.push_back(makeSharedPtr(createSampler(vkd, device, textureFilter, addressModeU, addressModeV, conversions[i]->get())));
503 }
504 #else
505 DE_UNREF(colorRange);
506 DE_UNREF(xChromaOffset);
507 DE_UNREF(yChromaOffset);
508 DE_UNREF(chromaFilter);
509 DE_UNREF(explicitReconstruction);
510 DE_UNREF(componentMapping);
511 samplers.push_back(makeSharedPtr(createSampler(vkd, device, textureFilter, addressModeU, addressModeV, (vk::VkSamplerYcbcrConversion)0u)));
512 #endif
513 const vk::Unique<vk::VkImage> image (createImage(vkd, device, format, size, disjoint, imageTiling));
514 const vk::MemoryRequirement memoryRequirement (imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
515 ? vk::MemoryRequirement::Any
516 : vk::MemoryRequirement::HostVisible);
517 const vk::VkImageCreateFlags createFlags (disjoint ? vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlagBits)0u);
518 const vector<AllocationSp> imageMemory (allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *image, format, createFlags, memoryRequirement));
519 std::vector<de::SharedPtr<vk::Unique<vk::VkImageView > > > imageViews;
520 #if defined(FAKE_COLOR_CONVERSION)
521 imageViews.push_back(makeSharedPtr(createImageView(vkd, device, *image, format, (vk::VkSamplerYcbcrConversion)0)));
522 #else
523 for (int i = 0; i < (int)colorModels.size(); i++)
524 {
525 imageViews.push_back(makeSharedPtr(createImageView(vkd, device, *image, format, conversions[i]->get())));
526 }
527 #endif
528
529 deUint32 combinedSamplerDescriptorCount = 1;
530 {
531 const vk::VkPhysicalDeviceImageFormatInfo2 imageFormatInfo =
532 {
533 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, //VkStructureType sType;
534 DE_NULL, //const void* pNext;
535 format, //VkFormat format;
536 vk::VK_IMAGE_TYPE_2D, //VkImageType type;
537 imageTiling, //VkImageTiling tiling;
538 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT |
539 vk::VK_IMAGE_USAGE_SAMPLED_BIT, //VkImageUsageFlags usage;
540 disjoint ?
541 (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_DISJOINT_BIT :
542 (vk::VkImageCreateFlags)0u //VkImageCreateFlags flags;
543 };
544
545 vk::VkSamplerYcbcrConversionImageFormatProperties samplerYcbcrConversionImage = {};
546 samplerYcbcrConversionImage.sType = vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
547 samplerYcbcrConversionImage.pNext = DE_NULL;
548
549 vk::VkImageFormatProperties2 imageFormatProperties = {};
550 imageFormatProperties.sType = vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
551 imageFormatProperties.pNext = &samplerYcbcrConversionImage;
552
553 VK_CHECK(vk.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &imageFormatProperties));
554 combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount;
555 }
556
557
558 const vk::Unique<vk::VkDescriptorSetLayout> layout (createDescriptorSetLayout(vkd, device, samplers, samplerBinding));
559 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool(vkd, device, samplers, combinedSamplerDescriptorCount));
560 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(vkd, device, *descriptorPool, *layout, samplers, imageViews, samplerBinding));
561
562 const ShaderSpec spec (createShaderSpec(samplerBinding, colorModels));
563 const de::UniquePtr<ShaderExecutor> executor (createExecutor(context, shaderType, spec, *layout));
564
565 if (imageTiling == vk::VK_IMAGE_TILING_OPTIMAL)
566 uploadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *image, imageData, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
567 else
568 fillImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *image, imageMemory, imageData, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
569
570 for(int i=0; i<(int)results.size(); i++)
571 results[i].resize(sts.size());
572
573 {
574 const void* const inputs[] =
575 {
576 &sts[0]
577 };
578 vector<void*> outputs;
579 for (int i = 0; i < (int)results.size(); i++)
580 outputs.push_back((void*)results[i].data());
581
582 executor->execute((int)sts.size(), inputs, outputs.data(), *descriptorSet);
583 }
584 }
585
logTestCaseInfo(TestLog & log,const TestConfig & config)586 void logTestCaseInfo (TestLog& log, const TestConfig& config)
587 {
588 log << TestLog::Message << "ShaderType: " << config.shaderType << TestLog::EndMessage;
589 log << TestLog::Message << "Format: " << config.format << TestLog::EndMessage;
590 log << TestLog::Message << "ImageTiling: " << config.imageTiling << TestLog::EndMessage;
591 log << TestLog::Message << "TextureFilter: " << config.textureFilter << TestLog::EndMessage;
592 log << TestLog::Message << "AddressModeU: " << config.addressModeU << TestLog::EndMessage;
593 log << TestLog::Message << "AddressModeV: " << config.addressModeV << TestLog::EndMessage;
594 log << TestLog::Message << "ChromaFilter: " << config.chromaFilter << TestLog::EndMessage;
595 log << TestLog::Message << "XChromaOffset: " << config.xChromaOffset << TestLog::EndMessage;
596 log << TestLog::Message << "YChromaOffset: " << config.yChromaOffset << TestLog::EndMessage;
597 log << TestLog::Message << "ExplicitReconstruction: " << (config.explicitReconstruction ? "true" : "false") << TestLog::EndMessage;
598 log << TestLog::Message << "Disjoint: " << (config.disjoint ? "true" : "false") << TestLog::EndMessage;
599 log << TestLog::Message << "ColorRange: " << config.colorRange << TestLog::EndMessage;
600 if( config.colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST )
601 log << TestLog::Message << "ColorModel: " << config.colorModel << TestLog::EndMessage;
602 else
603 log << TestLog::Message << "ColorModel: array of samplers" << TestLog::EndMessage;
604 log << TestLog::Message << "ComponentMapping: " << config.componentMapping << TestLog::EndMessage;
605 }
606
checkSupport(Context & context,const TestConfig config)607 void checkSupport (Context& context, const TestConfig config)
608 {
609 #if !defined(FAKE_COLOR_CONVERSION)
610 if (!context.isDeviceFunctionalitySupported("VK_KHR_sampler_ycbcr_conversion"))
611 TCU_THROW(NotSupportedError, "Extension VK_KHR_sampler_ycbcr_conversion not supported");
612
613 {
614 const vk::VkPhysicalDeviceSamplerYcbcrConversionFeatures features = context.getSamplerYcbcrConversionFeatures();
615 if (features.samplerYcbcrConversion == VK_FALSE)
616 TCU_THROW(NotSupportedError, "samplerYcbcrConversion feature is not supported");
617 }
618
619 try
620 {
621 const vk::VkFormatProperties properties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.format));
622 const vk::VkFormatFeatureFlags features (config.imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
623 ? properties.optimalTilingFeatures
624 : properties.linearTilingFeatures);
625
626 if ((features & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) == 0)
627 TCU_THROW(NotSupportedError, "Format doesn't support YCbCr conversions");
628
629 if ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) == 0)
630 TCU_THROW(NotSupportedError, "Format doesn't support sampling");
631
632 if (config.textureFilter == vk::VK_FILTER_LINEAR && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) == 0))
633 TCU_THROW(NotSupportedError, "Format doesn't support linear texture filtering");
634
635 if (config.chromaFilter == vk::VK_FILTER_LINEAR && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT) == 0))
636 TCU_THROW(NotSupportedError, "Format doesn't support YCbCr linear chroma reconstruction");
637
638 if (config.chromaFilter != config.textureFilter && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT) == 0))
639 TCU_THROW(NotSupportedError, "Format doesn't support different chroma and texture filters");
640
641 if (config.explicitReconstruction && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT) == 0))
642 TCU_THROW(NotSupportedError, "Format doesn't support explicit chroma reconstruction");
643
644 if (config.disjoint && ((features & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0))
645 TCU_THROW(NotSupportedError, "Format doesn't disjoint planes");
646
647 if (isXChromaSubsampled(config.format) && (config.xChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN) && ((features & vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) == 0))
648 TCU_THROW(NotSupportedError, "Format doesn't support cosited chroma samples");
649
650 if (isXChromaSubsampled(config.format) && (config.xChromaOffset == vk::VK_CHROMA_LOCATION_MIDPOINT) && ((features & vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) == 0))
651 TCU_THROW(NotSupportedError, "Format doesn't support midpoint chroma samples");
652
653 if (isYChromaSubsampled(config.format) && (config.yChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN) && ((features & vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) == 0))
654 TCU_THROW(NotSupportedError, "Format doesn't support cosited chroma samples");
655
656 if (isYChromaSubsampled(config.format) && (config.yChromaOffset == vk::VK_CHROMA_LOCATION_MIDPOINT) && ((features & vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) == 0))
657 TCU_THROW(NotSupportedError, "Format doesn't support midpoint chroma samples");
658 }
659 catch (const vk::Error& err)
660 {
661 if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
662 TCU_THROW(NotSupportedError, "Format not supported");
663
664 throw;
665 }
666 #endif
667 }
668
textureConversionTest(Context & context,const TestConfig config)669 tcu::TestStatus textureConversionTest (Context& context, const TestConfig config)
670 {
671 const std::vector<FloatFormat> filteringPrecision (getPrecision(config.format));
672 const std::vector<FloatFormat> conversionPrecision (getPrecision(config.format));
673 const deUint32 subTexelPrecisionBits (vk::getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits.subTexelPrecisionBits);
674 const tcu::UVec4 bitDepth (getYCbCrBitDepth(config.format));
675 TestLog& log (context.getTestContext().getLog());
676 bool explicitReconstruction = config.explicitReconstruction;
677 const UVec2 srcSize = config.srcSize;
678 const UVec2 dstSize = config.dstSize;
679 bool isOk = true;
680
681 logTestCaseInfo(log, config);
682
683 #if !defined(FAKE_COLOR_CONVERSION)
684 try
685 {
686 const vk::VkFormatProperties properties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.format));
687 const vk::VkFormatFeatureFlags features (config.imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
688 ? properties.optimalTilingFeatures
689 : properties.linearTilingFeatures);
690
691 if ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT) != 0)
692 explicitReconstruction = true;
693
694 log << TestLog::Message << "FormatFeatures: " << vk::getFormatFeatureFlagsStr(features) << TestLog::EndMessage;
695 }
696 catch (const vk::Error& err)
697 {
698 if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
699 TCU_THROW(NotSupportedError, "Format not supported");
700
701 throw;
702 }
703 #endif
704
705 {
706 const vk::PlanarFormatDescription planeInfo (vk::getPlanarFormatDescription(config.format));
707 MultiPlaneImageData src (config.format, srcSize);
708
709 deUint32 nullAccessData (0u);
710 ChannelAccess nullAccess (tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT, 1u, IVec3(srcSize.x(), srcSize.y(), 1), IVec3(0, 0, 0), &nullAccessData, 0u);
711 deUint32 nullAccessAlphaData (~0u);
712 ChannelAccess nullAccessAlpha (tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT, 1u, IVec3(srcSize.x(), srcSize.y(), 1), IVec3(0, 0, 0), &nullAccessAlphaData, 0u);
713 ChannelAccess rChannelAccess (planeInfo.hasChannelNdx(0) ? getChannelAccess(src, planeInfo, srcSize, 0) : nullAccess);
714 ChannelAccess gChannelAccess (planeInfo.hasChannelNdx(1) ? getChannelAccess(src, planeInfo, srcSize, 1) : nullAccess);
715 ChannelAccess bChannelAccess (planeInfo.hasChannelNdx(2) ? getChannelAccess(src, planeInfo, srcSize, 2) : nullAccess);
716 ChannelAccess aChannelAccess (planeInfo.hasChannelNdx(3) ? getChannelAccess(src, planeInfo, srcSize, 3) : nullAccessAlpha);
717 const bool implicitNearestCosited ((config.chromaFilter == vk::VK_FILTER_NEAREST && !config.explicitReconstruction) &&
718 (config.xChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN || config.yChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN));
719
720 vector<Vec2> sts;
721 vector<vector<Vec4> > results;
722 vector<vector<Vec4> > minBounds;
723 vector<vector<Vec4> > minMidpointBounds;
724 vector<vector<Vec4> > maxBounds;
725 vector<vector<Vec4> > maxMidpointBounds;
726 vector<vector<Vec4> > uvBounds;
727 vector<vector<IVec4> > ijBounds;
728
729 for (deUint32 planeNdx = 0; planeNdx < planeInfo.numPlanes; planeNdx++)
730 deMemset(src.getPlanePtr(planeNdx), 0u, src.getPlaneSize(planeNdx));
731
732 // \todo Limit values to only values that produce defined values using selected colorRange and colorModel? The verification code handles those cases already correctly.
733 if (planeInfo.hasChannelNdx(0))
734 {
735 for (int y = 0; y < rChannelAccess.getSize().y(); y++)
736 for (int x = 0; x < rChannelAccess.getSize().x(); x++)
737 rChannelAccess.setChannel(IVec3(x, y, 0), (float)x / (float)rChannelAccess.getSize().x());
738 }
739
740 if (planeInfo.hasChannelNdx(1))
741 {
742 for (int y = 0; y < gChannelAccess.getSize().y(); y++)
743 for (int x = 0; x < gChannelAccess.getSize().x(); x++)
744 gChannelAccess.setChannel(IVec3(x, y, 0), (float)y / (float)gChannelAccess.getSize().y());
745 }
746
747 if (planeInfo.hasChannelNdx(2))
748 {
749 for (int y = 0; y < bChannelAccess.getSize().y(); y++)
750 for (int x = 0; x < bChannelAccess.getSize().x(); x++)
751 bChannelAccess.setChannel(IVec3(x, y, 0), (float)(x + y) / (float)(bChannelAccess.getSize().x() + bChannelAccess.getSize().y()));
752 }
753
754 if (planeInfo.hasChannelNdx(3))
755 {
756 for (int y = 0; y < aChannelAccess.getSize().y(); y++)
757 for (int x = 0; x < aChannelAccess.getSize().x(); x++)
758 aChannelAccess.setChannel(IVec3(x, y, 0), (float)(x * y) / (float)(aChannelAccess.getSize().x() * aChannelAccess.getSize().y()));
759 }
760
761 if (dstSize.x() > srcSize.x() && dstSize.y() > srcSize.y())
762 genTexCoords(sts, srcSize, dstSize);
763 else
764 genOneToOneTexCoords(sts, dstSize);
765
766 std::vector< vk::VkSamplerYcbcrModelConversion> colorModels;
767 if (config.colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST)
768 {
769 colorModels.push_back(config.colorModel);
770 }
771 else
772 {
773 int ycbcrModelConverionCount = std::min( (int)vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST, 4 );
774 for (int i = 0; i < ycbcrModelConverionCount; i++)
775 {
776 colorModels.push_back((vk::VkSamplerYcbcrModelConversion)(vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + i));
777 }
778 }
779
780 for (int i = 0; i < (int)colorModels.size(); i++)
781 {
782 vector<Vec4> minBound;
783 vector<Vec4> minMidpointBound;
784 vector<Vec4> maxBound;
785 vector<Vec4> maxMidpointBound;
786 vector<Vec4> uvBound;
787 vector<IVec4> ijBound;
788
789 calculateBounds(rChannelAccess, gChannelAccess, bChannelAccess, aChannelAccess, bitDepth, sts, filteringPrecision, conversionPrecision, subTexelPrecisionBits, config.textureFilter, colorModels[i], config.colorRange, config.chromaFilter, config.xChromaOffset, config.yChromaOffset, config.componentMapping, explicitReconstruction, config.addressModeU, config.addressModeV, minBound, maxBound, uvBound, ijBound);
790
791 if (implicitNearestCosited)
792 {
793 calculateBounds(rChannelAccess, gChannelAccess, bChannelAccess, aChannelAccess, bitDepth, sts, filteringPrecision, conversionPrecision, subTexelPrecisionBits, config.textureFilter, colorModels[i], config.colorRange, config.chromaFilter, vk::VK_CHROMA_LOCATION_MIDPOINT, vk::VK_CHROMA_LOCATION_MIDPOINT, config.componentMapping, explicitReconstruction, config.addressModeU, config.addressModeV, minMidpointBound, maxMidpointBound, uvBound, ijBound);
794 }
795 results.push_back (vector<Vec4>());
796 minBounds.push_back (minBound);
797 minMidpointBounds.push_back (minMidpointBound);
798 maxBounds.push_back (maxBound);
799 maxMidpointBounds.push_back (maxMidpointBound);
800 uvBounds.push_back (uvBound);
801 ijBounds.push_back (ijBound);
802 }
803
804 if (vk::isYCbCrFormat(config.format))
805 {
806 tcu::TextureLevel rImage (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), rChannelAccess.getSize().x(), rChannelAccess.getSize().y());
807 tcu::TextureLevel gImage (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), gChannelAccess.getSize().x(), gChannelAccess.getSize().y());
808 tcu::TextureLevel bImage (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), bChannelAccess.getSize().x(), bChannelAccess.getSize().y());
809 tcu::TextureLevel aImage (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), aChannelAccess.getSize().x(), aChannelAccess.getSize().y());
810
811 for (int y = 0; y < (int)rChannelAccess.getSize().y(); y++)
812 for (int x = 0; x < (int)rChannelAccess.getSize().x(); x++)
813 rImage.getAccess().setPixel(Vec4(rChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
814
815 for (int y = 0; y < (int)gChannelAccess.getSize().y(); y++)
816 for (int x = 0; x < (int)gChannelAccess.getSize().x(); x++)
817 gImage.getAccess().setPixel(Vec4(gChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
818
819 for (int y = 0; y < (int)bChannelAccess.getSize().y(); y++)
820 for (int x = 0; x < (int)bChannelAccess.getSize().x(); x++)
821 bImage.getAccess().setPixel(Vec4(bChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
822
823 for (int y = 0; y < (int)aChannelAccess.getSize().y(); y++)
824 for (int x = 0; x < (int)aChannelAccess.getSize().x(); x++)
825 aImage.getAccess().setPixel(Vec4(aChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
826
827 {
828 const Vec4 scale (1.0f);
829 const Vec4 bias (0.0f);
830
831 log << TestLog::Image("SourceImageR", "SourceImageR", rImage.getAccess(), scale, bias);
832 log << TestLog::Image("SourceImageG", "SourceImageG", gImage.getAccess(), scale, bias);
833 log << TestLog::Image("SourceImageB", "SourceImageB", bImage.getAccess(), scale, bias);
834 log << TestLog::Image("SourceImageA", "SourceImageA", aImage.getAccess(), scale, bias);
835 }
836 }
837 else
838 {
839 tcu::TextureLevel srcImage (vk::mapVkFormat(config.format), srcSize.x(), srcSize.y());
840
841 for (int y = 0; y < (int)srcSize.y(); y++)
842 for (int x = 0; x < (int)srcSize.x(); x++)
843 {
844 const IVec3 pos (x, y, 0);
845 srcImage.getAccess().setPixel(Vec4(rChannelAccess.getChannel(pos), gChannelAccess.getChannel(pos), bChannelAccess.getChannel(pos), aChannelAccess.getChannel(pos)), x, y);
846 }
847
848 log << TestLog::Image("SourceImage", "SourceImage", srcImage.getAccess());
849 }
850
851 evalShader(context, config.shaderType, src, srcSize, config.format, config.imageTiling, config.disjoint, config.textureFilter, config.addressModeU, config.addressModeV, colorModels, config.colorRange, config.xChromaOffset, config.yChromaOffset, config.chromaFilter, config.componentMapping, config.explicitReconstruction, sts, config.samplerBinding, results);
852
853 {
854 std::vector<tcu::TextureLevel> minImages;
855 std::vector<tcu::TextureLevel> maxImages;
856 std::vector<tcu::TextureLevel> minMidpointImages;
857 std::vector<tcu::TextureLevel> maxMidpointImages;
858 std::vector<tcu::TextureLevel> resImages;
859 for (int i = 0; i < (int)colorModels.size(); i++)
860 {
861 minImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
862 maxImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
863 minMidpointImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
864 maxMidpointImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
865 resImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
866 }
867
868 for (int i = 0; i < (int)colorModels.size(); i++)
869 for (int y = 0; y < (int)(dstSize.y()); y++)
870 for (int x = 0; x < (int)(dstSize.x()); x++)
871 {
872 const int ndx = x + y * (int)(dstSize.x());
873 minImages[i].getAccess().setPixel(minBounds[i][ndx], x, y);
874 maxImages[i].getAccess().setPixel(maxBounds[i][ndx], x, y);
875 }
876
877 for (int i = 0; i < (int)colorModels.size(); i++)
878 for (int y = 0; y < (int)(dstSize.y()); y++)
879 for (int x = 0; x < (int)(dstSize.x()); x++)
880 {
881 const int ndx = x + y * (int)(dstSize.x());
882 resImages[i].getAccess().setPixel(results[i][ndx], x, y);
883 }
884
885 if (implicitNearestCosited)
886 {
887 for (int i = 0; i < (int)colorModels.size(); i++)
888 for (int y = 0; y < (int)(dstSize.y()); y++)
889 for (int x = 0; x < (int)(dstSize.x()); x++)
890 {
891 const int ndx = x + y * (int)(dstSize.x());
892 minMidpointImages[i].getAccess().setPixel(minMidpointBounds[i][ndx], x, y);
893 maxMidpointImages[i].getAccess().setPixel(maxMidpointBounds[i][ndx], x, y);
894 }
895 }
896
897 for (int i = 0; i < (int)colorModels.size(); i++)
898 {
899 const Vec4 scale (1.0f);
900 const Vec4 bias (0.0f);
901
902 log << TestLog::Image(string("MinBoundImage_") + de::toString(i), string("MinBoundImage_") + de::toString(i), minImages[i].getAccess(), scale, bias);
903 log << TestLog::Image(string("MaxBoundImage_") + de::toString(i), string("MaxBoundImage_") + de::toString(i), maxImages[i].getAccess(), scale, bias);
904
905 if (implicitNearestCosited)
906 {
907 log << TestLog::Image(string("MinMidpointBoundImage_") + de::toString(i), string("MinMidpointBoundImage_") + de::toString(i), minMidpointImages[i].getAccess(), scale, bias);
908 log << TestLog::Image(string("MaxMidpointBoundImage_") + de::toString(i), string("MaxMidpointBoundImage_") + de::toString(i), maxMidpointImages[i].getAccess(), scale, bias);
909 }
910
911 log << TestLog::Image(string("ResultImage_") + de::toString(i), string("ResultImage_") + de::toString(i), resImages[i].getAccess(), scale, bias);
912 }
913 }
914
915 size_t errorCount = 0;
916
917 for (int i = 0; i < (int)colorModels.size(); i++)
918 for (size_t ndx = 0; ndx < sts.size(); ndx++)
919 {
920 bool fail;
921 if (implicitNearestCosited)
922 {
923 fail = (tcu::boolAny(tcu::lessThan(results[i][ndx], minMidpointBounds[i][ndx])) || tcu::boolAny(tcu::greaterThan(results[i][ndx], maxMidpointBounds[i][ndx]))) &&
924 (tcu::boolAny(tcu::lessThan(results[i][ndx], minBounds[i][ndx])) || tcu::boolAny(tcu::greaterThan(results[i][ndx], maxBounds[i][ndx])));
925 }
926 else
927 {
928 fail = tcu::boolAny(tcu::lessThan(results[i][ndx], minBounds[i][ndx])) || tcu::boolAny(tcu::greaterThan(results[i][ndx], maxBounds[i][ndx]));
929 }
930
931 if (fail)
932 {
933 log << TestLog::Message << "Fail: " << i << " " << sts[ndx] << " " << results[i][ndx] << TestLog::EndMessage;
934 log << TestLog::Message << " Min : " << minBounds[i][ndx] << TestLog::EndMessage;
935 log << TestLog::Message << " Max : " << maxBounds[i][ndx] << TestLog::EndMessage;
936 log << TestLog::Message << " Threshold: " << (maxBounds[i][ndx] - minBounds[i][ndx]) << TestLog::EndMessage;
937 log << TestLog::Message << " UMin : " << uvBounds[i][ndx][0] << TestLog::EndMessage;
938 log << TestLog::Message << " UMax : " << uvBounds[i][ndx][1] << TestLog::EndMessage;
939 log << TestLog::Message << " VMin : " << uvBounds[i][ndx][2] << TestLog::EndMessage;
940 log << TestLog::Message << " VMax : " << uvBounds[i][ndx][3] << TestLog::EndMessage;
941 log << TestLog::Message << " IMin : " << ijBounds[i][ndx][0] << TestLog::EndMessage;
942 log << TestLog::Message << " IMax : " << ijBounds[i][ndx][1] << TestLog::EndMessage;
943 log << TestLog::Message << " JMin : " << ijBounds[i][ndx][2] << TestLog::EndMessage;
944 log << TestLog::Message << " JMax : " << ijBounds[i][ndx][3] << TestLog::EndMessage;
945
946 if (isXChromaSubsampled(config.format))
947 {
948 log << TestLog::Message << " LumaAlphaValues : " << TestLog::EndMessage;
949 log << TestLog::Message << " Offset : (" << ijBounds[i][ndx][0] << ", " << ijBounds[i][ndx][2] << ")" << TestLog::EndMessage;
950
951 for (deInt32 k = ijBounds[i][ndx][2]; k <= ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); k++)
952 {
953 const deInt32 wrappedK = wrap(config.addressModeV, k, gChannelAccess.getSize().y());
954 bool first = true;
955 std::ostringstream line;
956
957 for (deInt32 j = ijBounds[i][ndx][0]; j <= ijBounds[i][ndx][1] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); j++)
958 {
959 const deInt32 wrappedJ = wrap(config.addressModeU, j, gChannelAccess.getSize().x());
960
961 if (!first)
962 {
963 line << ", ";
964 first = false;
965 }
966
967 line << "(" << std::setfill(' ') << std::setw(5) << gChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
968 << ", " << std::setfill(' ') << std::setw(5) << aChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0)) << ")";
969 }
970 log << TestLog::Message << " " << line.str() << TestLog::EndMessage;
971 }
972
973 {
974 const IVec2 chromaJRange (divFloor(ijBounds[i][ndx][0], 2) - 1, divFloor(ijBounds[i][ndx][1] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0), 2) + 1);
975 const IVec2 chromaKRange (isYChromaSubsampled(config.format)
976 ? IVec2(divFloor(ijBounds[i][ndx][2], 2) - 1, divFloor(ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0), 2) + 1)
977 : IVec2(ijBounds[i][ndx][2], ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0)));
978
979 log << TestLog::Message << " ChromaValues : " << TestLog::EndMessage;
980 log << TestLog::Message << " Offset : (" << chromaJRange[0] << ", " << chromaKRange[0] << ")" << TestLog::EndMessage;
981
982 for (deInt32 k = chromaKRange[0]; k <= chromaKRange[1]; k++)
983 {
984 const deInt32 wrappedK = wrap(config.addressModeV, k, rChannelAccess.getSize().y());
985 bool first = true;
986 std::ostringstream line;
987
988 for (deInt32 j = chromaJRange[0]; j <= chromaJRange[1]; j++)
989 {
990 const deInt32 wrappedJ = wrap(config.addressModeU, j, rChannelAccess.getSize().x());
991
992 if (!first)
993 {
994 line << ", ";
995 first = false;
996 }
997
998 line << "(" << std::setfill(' ') << std::setw(5) << rChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
999 << ", " << std::setfill(' ') << std::setw(5) << bChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0)) << ")";
1000 }
1001 log << TestLog::Message << " " << line.str() << TestLog::EndMessage;
1002 }
1003 }
1004 }
1005 else
1006 {
1007 log << TestLog::Message << " Values : " << TestLog::EndMessage;
1008 log << TestLog::Message << " Offset : (" << ijBounds[i][ndx][0] << ", " << ijBounds[i][ndx][2] << ")" << TestLog::EndMessage;
1009
1010 for (deInt32 k = ijBounds[i][ndx][2]; k <= ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); k++)
1011 {
1012 const deInt32 wrappedK = wrap(config.addressModeV, k, rChannelAccess.getSize().y());
1013 bool first = true;
1014 std::ostringstream line;
1015
1016 for (deInt32 j = ijBounds[i][ndx][0]; j <= ijBounds[i][ndx][1] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); j++)
1017 {
1018 const deInt32 wrappedJ = wrap(config.addressModeU, j, rChannelAccess.getSize().x());
1019
1020 if (!first)
1021 {
1022 line << ", ";
1023 first = false;
1024 }
1025
1026 line << "(" << std::setfill(' ') << std::setw(5) << rChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
1027 << ", " << std::setfill(' ') << std::setw(5) << gChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
1028 << ", " << std::setfill(' ') << std::setw(5) << bChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
1029 << ", " << std::setfill(' ') << std::setw(5) << aChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0)) << ")";
1030 }
1031 log << TestLog::Message << " " << line.str() << TestLog::EndMessage;
1032 }
1033 }
1034
1035 errorCount++;
1036 isOk = false;
1037
1038 if (errorCount > 30)
1039 {
1040 log << TestLog::Message << "Encountered " << errorCount << " errors. Omitting rest of the per result logs." << TestLog::EndMessage;
1041 break;
1042 }
1043 }
1044 }
1045 }
1046
1047 if (isOk)
1048 return tcu::TestStatus::pass("Pass");
1049 else
1050 return tcu::TestStatus::fail("Result comparison failed");
1051 }
1052
1053 #if defined(FAKE_COLOR_CONVERSION)
swizzleToCompName(const char * identity,vk::VkComponentSwizzle swizzle)1054 const char* swizzleToCompName (const char* identity, vk::VkComponentSwizzle swizzle)
1055 {
1056 switch (swizzle)
1057 {
1058 case vk::VK_COMPONENT_SWIZZLE_IDENTITY: return identity;
1059 case vk::VK_COMPONENT_SWIZZLE_R: return "r";
1060 case vk::VK_COMPONENT_SWIZZLE_G: return "g";
1061 case vk::VK_COMPONENT_SWIZZLE_B: return "b";
1062 case vk::VK_COMPONENT_SWIZZLE_A: return "a";
1063 default:
1064 DE_FATAL("Unsupported swizzle");
1065 return DE_NULL;
1066 }
1067 }
1068 #endif
1069
createTestShaders(vk::SourceCollections & dst,TestConfig config)1070 void createTestShaders (vk::SourceCollections& dst, TestConfig config)
1071 {
1072 std::vector< vk::VkSamplerYcbcrModelConversion> colorModels;
1073 if (config.colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST)
1074 {
1075 colorModels.push_back(config.colorModel);
1076 }
1077 else
1078 {
1079 int ycbcrModelConverionCount = std::min((int)vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST, 4);
1080 for (int i = 0; i < ycbcrModelConverionCount; i++)
1081 {
1082 colorModels.push_back((vk::VkSamplerYcbcrModelConversion)(vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + i));
1083 }
1084 }
1085 #if !defined(FAKE_COLOR_CONVERSION)
1086 const ShaderSpec spec (createShaderSpec(config.samplerBinding, colorModels));
1087
1088 generateSources(config.shaderType, spec, dst);
1089 #else
1090 const tcu::UVec4 bits (getYCbCrBitDepth(config.format));
1091 ShaderSpec spec;
1092
1093 spec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=" + de::toString(config.samplerBinding) + ") uniform highp sampler2D u_sampler;";
1094
1095 spec.inputs.push_back(Symbol("uv", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
1096 spec.outputs.push_back(Symbol("o_color", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
1097
1098 std::ostringstream source;
1099
1100 source << "highp vec4 inputColor = texture(u_sampler, uv);\n";
1101
1102 source << "highp float r = inputColor." << swizzleToCompName("r", config.componentMapping.r) << ";\n";
1103 source << "highp float g = inputColor." << swizzleToCompName("g", config.componentMapping.g) << ";\n";
1104 source << "highp float b = inputColor." << swizzleToCompName("b", config.componentMapping.b) << ";\n";
1105 source << "highp float a = inputColor." << swizzleToCompName("a", config.componentMapping.a) << ";\n";
1106
1107 switch (config.colorRange)
1108 {
1109 case vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL:
1110 source << "highp float cr = r - (float(" << (0x1u << (bits[0] - 0x1u)) << ") / float(" << ((0x1u << bits[0]) - 1u) << "));\n";
1111 source << "highp float y = g;\n";
1112 source << "highp float cb = b - (float(" << (0x1u << (bits[2] - 0x1u)) << ") / float(" << ((0x1u << bits[2]) - 1u) << "));\n";
1113 break;
1114
1115 case vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW:
1116 source << "highp float cr = (r * float(" << ((0x1u << bits[0]) - 1u) << ") - float(" << (128u * (0x1u << (bits[0] - 8))) << ")) / float(" << (224u * (0x1u << (bits[0] - 8))) << ");\n";
1117 source << "highp float y = (g * float(" << ((0x1u << bits[1]) - 1u) << ") - float(" << (16u * (0x1u << (bits[1] - 8))) << ")) / float(" << (219u * (0x1u << (bits[1] - 8))) << ");\n";
1118 source << "highp float cb = (b * float(" << ((0x1u << bits[2]) - 1u) << ") - float(" << (128u * (0x1u << (bits[2] - 8))) << ")) / float(" << (224u * (0x1u << (bits[2] - 8))) << ");\n";
1119 break;
1120
1121 default:
1122 DE_FATAL("Unknown color range");
1123 }
1124
1125 source << "highp vec4 color;\n";
1126
1127 switch (config.colorModel)
1128 {
1129 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY:
1130 source << "color = vec4(r, g, b, a);\n";
1131 break;
1132
1133 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY:
1134 source << "color = vec4(cr, y, cb, a);\n";
1135 break;
1136
1137 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601:
1138 source << "color = vec4(y + 1.402 * cr, y - float(" << (0.202008 / 0.587) << ") * cb - float(" << (0.419198 / 0.587) << ") * cr, y + 1.772 * cb, a);\n";
1139 break;
1140
1141 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709:
1142 source << "color = vec4(y + 1.5748 * cr, y - float(" << (0.13397432 / 0.7152) << ") * cb - float(" << (0.33480248 / 0.7152) << ") * cr, y + 1.8556 * cb, a);\n";
1143 break;
1144
1145 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020:
1146 source << "color = vec4(y + 1.4746 * cr, (y - float(" << (0.11156702 / 0.6780) << ") * cb) - float(" << (0.38737742 / 0.6780) << ") * cr, y + 1.8814 * cb, a);\n";
1147 break;
1148
1149 default:
1150 DE_FATAL("Unknown color model");
1151 };
1152
1153 source << "o_color = color;\n";
1154
1155 spec.source = source.str();
1156 generateSources(config.shaderType, spec, dst);
1157 #endif
1158 }
1159
1160 struct RangeNamePair
1161 {
1162 const char* name;
1163 vk::VkSamplerYcbcrRange value;
1164 };
1165
1166
1167 struct ChromaLocationNamePair
1168 {
1169 const char* name;
1170 vk::VkChromaLocation value;
1171 };
1172
1173 // Alternate between swizzle_identity and their equivalents. Both should work.
getIdentitySwizzle(void)1174 const vk::VkComponentMapping& getIdentitySwizzle (void)
1175 {
1176 static bool alternate = false;
1177 static const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
1178 static const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
1179
1180 const vk::VkComponentMapping& mapping = (alternate ? mappingB : mappingA);
1181 alternate = (!alternate);
1182 return mapping;
1183 }
1184
1185 struct YCbCrConversionTestBuilder
1186 {
1187 const std::vector<vk::VkFormat> noChromaSubsampledFormats =
1188 {
1189 vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1190 vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1191 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
1192 vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
1193 vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
1194 vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
1195 vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1196 vk::VK_FORMAT_R8G8B8_UNORM,
1197 vk::VK_FORMAT_B8G8R8_UNORM,
1198 vk::VK_FORMAT_R8G8B8A8_UNORM,
1199 vk::VK_FORMAT_B8G8R8A8_UNORM,
1200 vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1201 vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1202 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1203 vk::VK_FORMAT_R16G16B16_UNORM,
1204 vk::VK_FORMAT_R16G16B16A16_UNORM,
1205 vk::VK_FORMAT_R10X6_UNORM_PACK16,
1206 vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
1207 vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
1208 vk::VK_FORMAT_R12X4_UNORM_PACK16,
1209 vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
1210 vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
1211 vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
1212 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
1213 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
1214 vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
1215 vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT,
1216 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT,
1217 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT,
1218 vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT,
1219 };
1220 const std::vector<vk::VkFormat> xChromaSubsampledFormats =
1221 {
1222 vk::VK_FORMAT_G8B8G8R8_422_UNORM,
1223 vk::VK_FORMAT_B8G8R8G8_422_UNORM,
1224 vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
1225 vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
1226
1227 vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
1228 vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
1229 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
1230 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
1231 vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
1232 vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
1233 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
1234 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
1235 vk::VK_FORMAT_G16B16G16R16_422_UNORM,
1236 vk::VK_FORMAT_B16G16R16G16_422_UNORM,
1237 vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
1238 vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
1239 };
1240 const std::vector<vk::VkFormat> xyChromaSubsampledFormats =
1241 {
1242 vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
1243 vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
1244 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
1245 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
1246 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
1247 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
1248 vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
1249 vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
1250 };
1251 struct ColorModelStruct
1252 {
1253 const char* const name;
1254 const vk::VkSamplerYcbcrModelConversion value;
1255 };
1256 const std::vector<ColorModelStruct> colorModels =
1257 {
1258 { "rgb_identity", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY },
1259 { "ycbcr_identity", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY },
1260 { "ycbcr_709", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 },
1261 { "ycbcr_601", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 },
1262 { "ycbcr_2020", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 }
1263 };
1264 const std::vector<RangeNamePair> colorRanges =
1265 {
1266 { "itu_full", vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL },
1267 { "itu_narrow", vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW }
1268 };
1269 const std::vector<ChromaLocationNamePair> chromaLocations =
1270 {
1271 { "cosited", vk::VK_CHROMA_LOCATION_COSITED_EVEN },
1272 { "midpoint", vk::VK_CHROMA_LOCATION_MIDPOINT }
1273 };
1274 struct TextureFilterStruct
1275 {
1276 const char* const name;
1277 vk::VkFilter value;
1278 };
1279 const std::vector<TextureFilterStruct> textureFilters =
1280 {
1281 { "linear", vk::VK_FILTER_LINEAR },
1282 { "nearest", vk::VK_FILTER_NEAREST }
1283 };
1284 // Used by the chroma reconstruction tests
1285 const vk::VkSamplerYcbcrModelConversion defaultColorModel = vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
1286 const vk::VkSamplerYcbcrRange defaultColorRange = vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
1287 const vk::VkComponentMapping swappedChromaSwizzle =
1288 {
1289 vk::VK_COMPONENT_SWIZZLE_B,
1290 vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1291 vk::VK_COMPONENT_SWIZZLE_R,
1292 vk::VK_COMPONENT_SWIZZLE_IDENTITY
1293 };
1294 const std::vector<glu::ShaderType> shaderTypes =
1295 {
1296 glu::SHADERTYPE_VERTEX,
1297 glu::SHADERTYPE_FRAGMENT,
1298 glu::SHADERTYPE_COMPUTE
1299 };
1300 struct ImageTilingStruct
1301 {
1302 const char* name;
1303 vk::VkImageTiling value;
1304 };
1305 const std::vector<ImageTilingStruct> imageTilings =
1306 {
1307 { "tiling_linear", vk::VK_IMAGE_TILING_LINEAR },
1308 { "tiling_optimal", vk::VK_IMAGE_TILING_OPTIMAL }
1309 };
1310 struct SamplerBindingStruct
1311 {
1312 const char* name;
1313 deUint32 value;
1314 };
1315 const std::vector<SamplerBindingStruct> samplerBindings =
1316 {
1317 { "binding_0", 0 },
1318 { "binding_7", 7 },
1319 { "binding_15", 15 },
1320 { "binding_31", 31 }
1321 };
1322
buildTestsvkt::ycbcr::__anoned4a6e000111::YCbCrConversionTestBuilder1323 void buildTests(tcu::TestCaseGroup* testGroup)
1324 {
1325 tcu::TestContext& testCtx(testGroup->getTestContext());
1326 de::Random rng(1978765638u);
1327
1328 // Test formats without chroma reconstruction
1329 for (size_t formatNdx = 0; formatNdx < noChromaSubsampledFormats.size(); formatNdx++)
1330 {
1331 const vk::VkFormat format(noChromaSubsampledFormats[formatNdx]);
1332 const std::string formatName(de::toLower(std::string(getFormatName(format)).substr(10)));
1333 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1334 const UVec2 srcSize(isXChromaSubsampled(format) ? 12 : 7,
1335 isYChromaSubsampled(format) ? 8 : 13);
1336 const UVec2 dstSize(srcSize.x() + srcSize.x() / 2,
1337 srcSize.y() + srcSize.y() / 2);
1338
1339 for (size_t modelNdx = 0; modelNdx < colorModels.size(); modelNdx++)
1340 {
1341 const char* const colorModelName(colorModels[modelNdx].name);
1342 const vk::VkSamplerYcbcrModelConversion colorModel(colorModels[modelNdx].value);
1343
1344 if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && getYCbCrFormatChannelCount(format) < 3)
1345 continue;
1346
1347 de::MovePtr<tcu::TestCaseGroup> colorModelGroup(new tcu::TestCaseGroup(testCtx, colorModelName, ("Tests for color model " + string(colorModelName)).c_str()));
1348
1349 if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
1350 {
1351 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1352 {
1353 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1354 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1355
1356 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1357 {
1358 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1359 const char* const tilingName(imageTilings[tilingNdx].name);
1360 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1361 const vk::VkSamplerYcbcrRange colorRange(rng.choose<RangeNamePair>(begin(colorRanges), end(colorRanges)).value);
1362 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1363
1364 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1365 {
1366 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1367 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1368 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1369 textureFilter, chromaLocation, chromaLocation, false, false,
1370 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1371
1372 addFunctionCaseWithPrograms(colorModelGroup.get(), std::string(textureFilterName) + "_" + tilingName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1373 }
1374 }
1375 }
1376 }
1377 else
1378 {
1379 for (size_t rangeNdx = 0; rangeNdx < colorRanges.size(); rangeNdx++)
1380 {
1381 const char* const colorRangeName(colorRanges[rangeNdx].name);
1382 const vk::VkSamplerYcbcrRange colorRange(colorRanges[rangeNdx].value);
1383
1384 // Narrow range doesn't really work with formats that have less than 8 bits
1385 if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1386 {
1387 const UVec4 bitDepth(getYCbCrBitDepth(format));
1388
1389 if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1390 continue;
1391 }
1392
1393 de::MovePtr<tcu::TestCaseGroup> colorRangeGroup(new tcu::TestCaseGroup(testCtx, colorRangeName, ("Tests for color range " + string(colorRangeName)).c_str()));
1394
1395 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1396 {
1397 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1398 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1399
1400 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1401 {
1402 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1403 const char* const tilingName(imageTilings[tilingNdx].name);
1404 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(shaderTypes.begin(), shaderTypes.end()));
1405 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(chromaLocations.begin(), chromaLocations.end()).value);
1406 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++) {
1407 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1408 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1409 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1410 textureFilter, chromaLocation, chromaLocation, false, false,
1411 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1412
1413 addFunctionCaseWithPrograms(colorRangeGroup.get(), std::string(textureFilterName) + "_" + tilingName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1414 }
1415 }
1416 }
1417
1418 colorModelGroup->addChild(colorRangeGroup.release());
1419 }
1420 }
1421
1422 formatGroup->addChild(colorModelGroup.release());
1423 }
1424
1425 // Color conversion tests for array of samplers ( noChromaSubsampledFormats )
1426 if (getYCbCrFormatChannelCount(format) >= 3)
1427 buildArrayOfSamplersTests(format, srcSize, dstSize, formatGroup, testCtx, rng);
1428
1429 testGroup->addChild(formatGroup.release());
1430 }
1431
1432 // Test formats with x chroma reconstruction
1433 for (size_t formatNdx = 0; formatNdx < xChromaSubsampledFormats.size(); formatNdx++)
1434 {
1435 const vk::VkFormat format(xChromaSubsampledFormats[formatNdx]);
1436 const std::string formatName(de::toLower(std::string(getFormatName(format)).substr(10)));
1437 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1438 const UVec2 srcSize(isXChromaSubsampled(format) ? 12 : 7,
1439 isYChromaSubsampled(format) ? 8 : 13);
1440 const UVec2 dstSize(srcSize.x() + srcSize.x() / 2,
1441 srcSize.y() + srcSize.y() / 2);
1442
1443 // Color conversion tests
1444 {
1445 de::MovePtr<tcu::TestCaseGroup> conversionGroup(new tcu::TestCaseGroup(testCtx, "color_conversion", ""));
1446
1447 for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1448 {
1449 const char* const xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1450 const vk::VkChromaLocation xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1451
1452 for (size_t modelNdx = 0; modelNdx < colorModels.size(); modelNdx++)
1453 {
1454 const char* const colorModelName(colorModels[modelNdx].name);
1455 const vk::VkSamplerYcbcrModelConversion colorModel(colorModels[modelNdx].value);
1456
1457 if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && getYCbCrFormatChannelCount(format) < 3)
1458 continue;
1459
1460
1461 if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
1462 {
1463 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1464 {
1465 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1466 const char* const tilingName(imageTilings[tilingNdx].name);
1467 const vk::VkSamplerYcbcrRange colorRange(rng.choose<RangeNamePair>(begin(colorRanges), end(colorRanges)).value);
1468 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1469 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1470 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1471 {
1472 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1473 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1474 const TestConfig config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1475 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, false, false,
1476 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1477
1478 addFunctionCaseWithPrograms(conversionGroup.get(), string(colorModelName) + "_" + tilingName + "_" + xChromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1479 }
1480 }
1481 }
1482 else
1483 {
1484 for (size_t rangeNdx = 0; rangeNdx < colorRanges.size(); rangeNdx++)
1485 {
1486 const char* const colorRangeName(colorRanges[rangeNdx].name);
1487 const vk::VkSamplerYcbcrRange colorRange(colorRanges[rangeNdx].value);
1488
1489 // Narrow range doesn't really work with formats that have less than 8 bits
1490 if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1491 {
1492 const UVec4 bitDepth(getYCbCrBitDepth(format));
1493
1494 if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1495 continue;
1496 }
1497
1498 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1499 {
1500 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1501 const char* const tilingName(imageTilings[tilingNdx].name);
1502 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1503 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1504 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1505 {
1506 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1507 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1508 const TestConfig config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1509 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, false, false,
1510 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1511
1512 addFunctionCaseWithPrograms(conversionGroup.get(), string(colorModelName) + "_" + colorRangeName + "_" + tilingName + "_" + xChromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1513 }
1514 }
1515 }
1516 }
1517 }
1518 }
1519
1520 formatGroup->addChild(conversionGroup.release());
1521 }
1522
1523 // Color conversion tests for array of samplers ( xChromaSubsampledFormats )
1524 if (getYCbCrFormatChannelCount(format) >= 3)
1525 buildArrayOfSamplersTests(format, srcSize, dstSize, formatGroup, testCtx, rng);
1526
1527 // Chroma reconstruction tests
1528 {
1529 de::MovePtr<tcu::TestCaseGroup> reconstrucGroup(new tcu::TestCaseGroup(testCtx, "chroma_reconstruction", ""));
1530
1531 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1532 {
1533 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1534 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1535 de::MovePtr<tcu::TestCaseGroup> textureFilterGroup(new tcu::TestCaseGroup(testCtx, textureFilterName, textureFilterName));
1536
1537 for (size_t explicitReconstructionNdx = 0; explicitReconstructionNdx < 2; explicitReconstructionNdx++)
1538 {
1539 const bool explicitReconstruction(explicitReconstructionNdx == 1);
1540
1541 for (size_t disjointNdx = 0; disjointNdx < 2; disjointNdx++)
1542 {
1543 const bool disjoint(disjointNdx == 1);
1544
1545 for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1546 {
1547 const vk::VkChromaLocation xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1548 const char* const xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1549
1550 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1551 {
1552 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1553 const char* const tilingName(imageTilings[tilingNdx].name);
1554
1555 {
1556 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1557 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1558 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1559 vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1560 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1561
1562 addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1563 }
1564
1565 {
1566 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1567 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1568 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1569 vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1570 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1571
1572 addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1573 }
1574
1575 if (!explicitReconstruction)
1576 {
1577 {
1578 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1579 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1580 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1581 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1582 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1583
1584 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1585 }
1586
1587 {
1588 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1589 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1590 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1591 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1592 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1593
1594 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1595 }
1596 }
1597 }
1598 }
1599
1600 if (explicitReconstruction)
1601 {
1602 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1603 {
1604 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1605 const char* const tilingName(imageTilings[tilingNdx].name);
1606 {
1607 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1608 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1609 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1610 vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1611 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1612
1613 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1614 }
1615
1616 {
1617 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1618 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1619 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1620 vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1621 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1622
1623 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1624 }
1625 }
1626 }
1627 }
1628 }
1629
1630 reconstrucGroup->addChild(textureFilterGroup.release());
1631 }
1632
1633 formatGroup->addChild(reconstrucGroup.release());
1634 }
1635
1636 testGroup->addChild(formatGroup.release());
1637 }
1638
1639 // Test formats with xy chroma reconstruction
1640 for (size_t formatNdx = 0; formatNdx < xyChromaSubsampledFormats.size(); formatNdx++)
1641 {
1642 const vk::VkFormat format(xyChromaSubsampledFormats[formatNdx]);
1643 const std::string formatName(de::toLower(std::string(getFormatName(format)).substr(10)));
1644 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1645 const UVec2 srcSize(isXChromaSubsampled(format) ? 12 : 7,
1646 isYChromaSubsampled(format) ? 8 : 13);
1647 const UVec2 dstSize(srcSize.x() + srcSize.x() / 2,
1648 srcSize.y() + srcSize.y() / 2);
1649
1650 // Color conversion tests
1651 {
1652 de::MovePtr<tcu::TestCaseGroup> conversionGroup(new tcu::TestCaseGroup(testCtx, "color_conversion", ""));
1653
1654 for (size_t chromaOffsetNdx = 0; chromaOffsetNdx < chromaLocations.size(); chromaOffsetNdx++)
1655 {
1656 const char* const chromaOffsetName(chromaLocations[chromaOffsetNdx].name);
1657 const vk::VkChromaLocation chromaOffset(chromaLocations[chromaOffsetNdx].value);
1658
1659 for (size_t modelNdx = 0; modelNdx < colorModels.size(); modelNdx++)
1660 {
1661 const char* const colorModelName(colorModels[modelNdx].name);
1662 const vk::VkSamplerYcbcrModelConversion colorModel(colorModels[modelNdx].value);
1663
1664 if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && getYCbCrFormatChannelCount(format) < 3)
1665 continue;
1666
1667 if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
1668 {
1669 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1670 {
1671 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1672 const char* const tilingName(imageTilings[tilingNdx].name);
1673 const vk::VkSamplerYcbcrRange colorRange(rng.choose<RangeNamePair>(begin(colorRanges), end(colorRanges)).value);
1674 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1675 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1676 {
1677 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1678 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1679 const TestConfig config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1680 vk::VK_FILTER_NEAREST, chromaOffset, chromaOffset, false, false,
1681 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1682
1683 addFunctionCaseWithPrograms(conversionGroup.get(), std::string(colorModelName) + "_" + tilingName + "_" + chromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1684 }
1685 }
1686 }
1687 else
1688 {
1689 for (size_t rangeNdx = 0; rangeNdx < colorRanges.size(); rangeNdx++)
1690 {
1691 const char* const colorRangeName(colorRanges[rangeNdx].name);
1692 const vk::VkSamplerYcbcrRange colorRange(colorRanges[rangeNdx].value);
1693
1694 // Narrow range doesn't really work with formats that have less than 8 bits
1695 if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1696 {
1697 const UVec4 bitDepth(getYCbCrBitDepth(format));
1698
1699 if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1700 continue;
1701 }
1702
1703 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1704 {
1705 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1706 const char* const tilingName(imageTilings[tilingNdx].name);
1707 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1708 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1709 {
1710 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1711 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1712 const TestConfig config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1713 vk::VK_FILTER_NEAREST, chromaOffset, chromaOffset, false, false,
1714 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1715
1716 addFunctionCaseWithPrograms(conversionGroup.get(), string(colorModelName) + "_" + colorRangeName + "_" + tilingName + "_" + chromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1717 }
1718 }
1719 }
1720 }
1721 }
1722 }
1723
1724 formatGroup->addChild(conversionGroup.release());
1725 }
1726
1727 // Color conversion tests for array of samplers ( xyChromaSubsampledFormats )
1728 if (getYCbCrFormatChannelCount(format) >= 3)
1729 buildArrayOfSamplersTests(format, srcSize, dstSize, formatGroup, testCtx, rng);
1730
1731 // Chroma reconstruction tests
1732 {
1733 de::MovePtr<tcu::TestCaseGroup> reconstrucGroup(new tcu::TestCaseGroup(testCtx, "chroma_reconstruction", ""));
1734
1735 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1736 {
1737 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1738 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1739 de::MovePtr<tcu::TestCaseGroup> textureFilterGroup(new tcu::TestCaseGroup(testCtx, textureFilterName, textureFilterName));
1740
1741 for (size_t explicitReconstructionNdx = 0; explicitReconstructionNdx < 2; explicitReconstructionNdx++)
1742 {
1743 const bool explicitReconstruction(explicitReconstructionNdx == 1);
1744
1745 for (size_t disjointNdx = 0; disjointNdx < 2; disjointNdx++)
1746 {
1747 const bool disjoint(disjointNdx == 1);
1748
1749 for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1750 for (size_t yChromaOffsetNdx = 0; yChromaOffsetNdx < chromaLocations.size(); yChromaOffsetNdx++)
1751 {
1752 const vk::VkChromaLocation xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1753 const char* const xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1754
1755 const vk::VkChromaLocation yChromaOffset(chromaLocations[yChromaOffsetNdx].value);
1756 const char* const yChromaOffsetName(chromaLocations[yChromaOffsetNdx].name);
1757
1758 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1759 {
1760 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1761 const char* const tilingName(imageTilings[tilingNdx].name);
1762 {
1763 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1764 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1765 vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1766 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1767
1768 addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1769 }
1770
1771 {
1772 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1773 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1774 vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1775 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1776
1777 addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1778 }
1779
1780 if (!explicitReconstruction)
1781 {
1782 {
1783 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1784 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1785 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1786 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1787
1788 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1789 }
1790
1791 {
1792 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1793 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1794 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1795 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1796
1797 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1798 }
1799 }
1800 }
1801 }
1802
1803 if (explicitReconstruction)
1804 {
1805 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1806 {
1807 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1808 const char* const tilingName(imageTilings[tilingNdx].name);
1809 {
1810 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1811 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1812 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1813 vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1814 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1815
1816 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1817 }
1818
1819 {
1820 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1821 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1822 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1823 vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1824 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1825
1826 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1827 }
1828 }
1829 }
1830 }
1831 }
1832
1833 reconstrucGroup->addChild(textureFilterGroup.release());
1834 }
1835
1836 formatGroup->addChild(reconstrucGroup.release());
1837 }
1838
1839 testGroup->addChild(formatGroup.release());
1840 }
1841
1842 {
1843 const UVec2 imageSizes[] =
1844 {
1845 UVec2(16, 16),
1846 UVec2(20, 12)
1847 };
1848
1849 de::MovePtr<tcu::TestCaseGroup> oneToOneGroup(new tcu::TestCaseGroup(testCtx, "one_to_one", "Ycbcr images sampled to a frame buffer of the same dimentions."));
1850
1851 const vk::VkFormat format(vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM);
1852 const vk::VkFilter filter(vk::VK_FILTER_NEAREST);
1853
1854 for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(imageSizes); sizeNdx++)
1855 {
1856 const UVec2 srcSize(imageSizes[sizeNdx]);
1857
1858 for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1859 {
1860 const vk::VkChromaLocation xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1861 const char* const xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1862
1863 for (size_t yChromaOffsetNdx = 0; yChromaOffsetNdx < chromaLocations.size(); yChromaOffsetNdx++)
1864 {
1865 const vk::VkChromaLocation yChromaOffset(chromaLocations[yChromaOffsetNdx].value);
1866 const char* const yChromaOffsetName(chromaLocations[yChromaOffsetNdx].name);
1867
1868 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1869 {
1870 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1871 const char* const tilingName(imageTilings[tilingNdx].name);
1872
1873 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1874
1875 const TestConfig config(shaderType, format, tiling, filter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1876 filter, xChromaOffset, yChromaOffset, false, false,
1877 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, srcSize, 0);
1878 std::ostringstream testName;
1879 testName << string("implicit_nearest_") << srcSize.x() << "x" << srcSize.y() << "_" << tilingName << "_" << xChromaOffsetName << "_" << yChromaOffsetName;
1880
1881 addFunctionCaseWithPrograms(oneToOneGroup.get(), testName.str(), "", checkSupport, createTestShaders, textureConversionTest, config);
1882 }
1883 }
1884 }
1885 }
1886
1887 testGroup->addChild(oneToOneGroup.release());
1888 }
1889 }
1890
buildArrayOfSamplersTestsvkt::ycbcr::__anoned4a6e000111::YCbCrConversionTestBuilder1891 void buildArrayOfSamplersTests(const vk::VkFormat& format, const UVec2& srcSize, const UVec2& dstSize, de::MovePtr<tcu::TestCaseGroup>& formatGroup, tcu::TestContext& testCtx, de::Random& rng )
1892 {
1893 de::MovePtr<tcu::TestCaseGroup> samplerArrayGroup(new tcu::TestCaseGroup(testCtx, "sampler_array", "Tests for array of samplers"));
1894
1895 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1896 {
1897 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1898 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1899
1900 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1901 {
1902 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1903 const char* const tilingName(imageTilings[tilingNdx].name);
1904 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(shaderTypes.begin(), shaderTypes.end()));
1905 const vk::VkSamplerYcbcrRange colorRange(vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL);
1906 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(chromaLocations.begin(), chromaLocations.end()).value);
1907
1908 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1909 {
1910 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1911 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1912 // colorModel==VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST means that we want to create an array of samplers instead of a single sampler
1913 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1914 textureFilter, chromaLocation, chromaLocation, false, false,
1915 colorRange, vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1916
1917 addFunctionCaseWithPrograms(samplerArrayGroup.get(), std::string(textureFilterName) + "_" + tilingName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1918 }
1919 }
1920 }
1921 formatGroup->addChild(samplerArrayGroup.release());
1922 }
1923 };
1924
initTests(tcu::TestCaseGroup * testGroup)1925 void initTests(tcu::TestCaseGroup* testGroup)
1926 {
1927 YCbCrConversionTestBuilder testBuilder;
1928 testBuilder.buildTests(testGroup);
1929 }
1930
1931 } // anonymous
1932
createConversionTests(tcu::TestContext & testCtx)1933 tcu::TestCaseGroup* createConversionTests (tcu::TestContext& testCtx)
1934 {
1935 return createTestGroup(testCtx, "conversion", "Sampler YCbCr Conversion Tests", initTests);
1936 }
1937
1938 } // ycbcr
1939 } // vkt
1940