1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 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 Binding shader access tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktBindingShaderAccessTests.hpp"
25
26 #include "vktTestCase.hpp"
27
28 #include "vkDefs.hpp"
29 #include "vkRef.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkCmdUtil.hpp"
39 #include "vkObjUtil.hpp"
40
41 #include "tcuVector.hpp"
42 #include "tcuVectorUtil.hpp"
43 #include "tcuTexture.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuResultCollector.hpp"
46 #include "tcuTestLog.hpp"
47 #include "tcuRGBA.hpp"
48 #include "tcuSurface.hpp"
49 #include "tcuImageCompare.hpp"
50
51 #include "deUniquePtr.hpp"
52 #include "deSharedPtr.hpp"
53 #include "deStringUtil.hpp"
54 #include "deArrayUtil.hpp"
55
56 #include "qpInfo.h"
57 #include <iostream>
58
59 namespace vkt
60 {
61 namespace BindingModel
62 {
63 namespace
64 {
65
66 enum ResourceFlag
67 {
68 RESOURCE_FLAG_IMMUTABLE_SAMPLER = (1u << 0u),
69
70 RESOURCE_FLAG_LAST = (1u << 1u)
71 };
72
73 enum DescriptorUpdateMethod
74 {
75 DESCRIPTOR_UPDATE_METHOD_NORMAL = 0, //!< use vkUpdateDescriptorSets
76 DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE, //!< use descriptor update templates
77 DESCRIPTOR_UPDATE_METHOD_WITH_PUSH, //!< use push descriptor updates
78 DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE, //!< use push descriptor update templates
79
80 DESCRIPTOR_UPDATE_METHOD_LAST
81 };
82
stringifyDescriptorUpdateMethod(DescriptorUpdateMethod method)83 std::string stringifyDescriptorUpdateMethod(DescriptorUpdateMethod method)
84 {
85 switch (method)
86 {
87 case DESCRIPTOR_UPDATE_METHOD_NORMAL:
88 return "";
89
90 case DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE:
91 return "with_template";
92
93 case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH:
94 return "with_push";
95
96 case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE:
97 return "with_push_template";
98
99 default:
100 return "N/A";
101 }
102 }
103
104 static const char *const s_quadrantGenVertexPosSource =
105 " highp int quadPhase = gl_VertexIndex % 6;\n"
106 " highp int quadXcoord = int(quadPhase == 1 || quadPhase == 4 || quadPhase == 5);\n"
107 " highp int quadYcoord = int(quadPhase == 2 || quadPhase == 3 || quadPhase == 5);\n"
108 " highp int quadOriginX = (gl_VertexIndex / 6) % 2;\n"
109 " highp int quadOriginY = (gl_VertexIndex / 6) / 2;\n"
110 " quadrant_id = gl_VertexIndex / 6;\n"
111 " result_position = vec4(float(quadOriginX + quadXcoord - 1), float(quadOriginY + quadYcoord - 1), 0.0, 1.0);\n";
112
genPerVertexBlock(const vk::VkShaderStageFlagBits stage,const glu::GLSLVersion version)113 std::string genPerVertexBlock(const vk::VkShaderStageFlagBits stage, const glu::GLSLVersion version)
114 {
115 static const char *const block =
116 "gl_PerVertex {\n"
117 " vec4 gl_Position;\n"
118 " float gl_PointSize;\n" // not used, but for compatibility with how implicit block is declared in ES
119 "}";
120 std::ostringstream str;
121
122 if (!glu::glslVersionIsES(version))
123 switch (stage)
124 {
125 case vk::VK_SHADER_STAGE_VERTEX_BIT:
126 str << "out " << block << ";\n";
127 break;
128
129 case vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
130 str << "in " << block << " gl_in[gl_MaxPatchVertices];\n"
131 << "out " << block << " gl_out[];\n";
132 break;
133
134 case vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
135 str << "in " << block << " gl_in[gl_MaxPatchVertices];\n"
136 << "out " << block << ";\n";
137 break;
138
139 case vk::VK_SHADER_STAGE_GEOMETRY_BIT:
140 str << "in " << block << " gl_in[];\n"
141 << "out " << block << ";\n";
142 break;
143
144 default:
145 break;
146 }
147
148 return str.str();
149 }
150
isUniformDescriptorType(vk::VkDescriptorType type)151 bool isUniformDescriptorType(vk::VkDescriptorType type)
152 {
153 return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
154 type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
155 }
156
isDynamicDescriptorType(vk::VkDescriptorType type)157 bool isDynamicDescriptorType(vk::VkDescriptorType type)
158 {
159 return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
160 type == vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
161 }
162
verifyDriverSupport(const uint32_t apiVersion,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const std::vector<std::string> & deviceExtensions,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descType,vk::VkShaderStageFlags activeStages,vk::VkImageViewType viewType=vk::VK_IMAGE_VIEW_TYPE_2D)163 void verifyDriverSupport(const uint32_t apiVersion, const vk::VkPhysicalDeviceFeatures &deviceFeatures,
164 const std::vector<std::string> &deviceExtensions, DescriptorUpdateMethod updateMethod,
165 vk::VkDescriptorType descType, vk::VkShaderStageFlags activeStages,
166 vk::VkImageViewType viewType = vk::VK_IMAGE_VIEW_TYPE_2D)
167 {
168 std::vector<std::string> extensionNames;
169 size_t numExtensionsNeeded = 0;
170
171 switch (updateMethod)
172 {
173 case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH:
174 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_push_descriptor"))
175 extensionNames.push_back("VK_KHR_push_descriptor");
176 break;
177
178 case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE:
179 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_push_descriptor"))
180 extensionNames.push_back("VK_KHR_push_descriptor");
181 // Fallthrough
182 case DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE:
183 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_descriptor_update_template"))
184 extensionNames.push_back("VK_KHR_descriptor_update_template");
185 break;
186
187 case DESCRIPTOR_UPDATE_METHOD_NORMAL:
188 // no extensions needed
189 break;
190
191 default:
192 DE_FATAL("Impossible");
193 }
194
195 numExtensionsNeeded = extensionNames.size();
196
197 if (numExtensionsNeeded > 0)
198 {
199 for (size_t deviceExtNdx = 0; deviceExtNdx < deviceExtensions.size(); deviceExtNdx++)
200 {
201 for (size_t requiredExtNdx = 0; requiredExtNdx < extensionNames.size(); requiredExtNdx++)
202 {
203 if (deviceExtensions[deviceExtNdx] == extensionNames[requiredExtNdx])
204 {
205 --numExtensionsNeeded;
206 break;
207 }
208 }
209
210 if (numExtensionsNeeded == 0)
211 break;
212 }
213
214 if (numExtensionsNeeded > 0)
215 {
216 TCU_THROW(NotSupportedError,
217 (stringifyDescriptorUpdateMethod(updateMethod) + " tests are not supported").c_str());
218 }
219 }
220
221 switch (descType)
222 {
223 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
224 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
225 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
226 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
227 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
228 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
229 // These are supported in all stages
230 break;
231
232 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
233 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
234 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
235 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
236 if (activeStages & (vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
237 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT))
238 {
239 if (!deviceFeatures.vertexPipelineStoresAndAtomics)
240 TCU_THROW(NotSupportedError,
241 (de::toString(descType) + " is not supported in the vertex pipeline").c_str());
242 }
243
244 if (activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT)
245 {
246 if (!deviceFeatures.fragmentStoresAndAtomics)
247 TCU_THROW(NotSupportedError,
248 (de::toString(descType) + " is not supported in fragment shaders").c_str());
249 }
250 break;
251
252 default:
253 DE_FATAL("Impossible");
254 }
255
256 if (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !deviceFeatures.imageCubeArray)
257 TCU_THROW(NotSupportedError, "imageCubeArray feature not supported");
258 }
259
viewTypeToImageType(vk::VkImageViewType type)260 vk::VkImageType viewTypeToImageType(vk::VkImageViewType type)
261 {
262 switch (type)
263 {
264 case vk::VK_IMAGE_VIEW_TYPE_1D:
265 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
266 return vk::VK_IMAGE_TYPE_1D;
267 case vk::VK_IMAGE_VIEW_TYPE_2D:
268 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
269 return vk::VK_IMAGE_TYPE_2D;
270 case vk::VK_IMAGE_VIEW_TYPE_3D:
271 return vk::VK_IMAGE_TYPE_3D;
272 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
273 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
274 return vk::VK_IMAGE_TYPE_2D;
275
276 default:
277 DE_FATAL("Impossible");
278 return (vk::VkImageType)0;
279 }
280 }
281
getImageLayoutForDescriptorType(vk::VkDescriptorType descType)282 vk::VkImageLayout getImageLayoutForDescriptorType(vk::VkDescriptorType descType)
283 {
284 if (descType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
285 return vk::VK_IMAGE_LAYOUT_GENERAL;
286 else
287 return vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
288 }
289
getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid & srcImage)290 uint32_t getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid &srcImage)
291 {
292 uint32_t dataSize = 0;
293 for (int level = 0; level < srcImage.getNumLevels(); ++level)
294 {
295 const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
296
297 // tightly packed
298 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
299
300 dataSize +=
301 srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
302 }
303 return dataSize;
304 }
305
writeTextureLevelPyramidData(void * dst,uint32_t dstLen,const tcu::TextureLevelPyramid & srcImage,vk::VkImageViewType viewType,std::vector<vk::VkBufferImageCopy> * copySlices)306 void writeTextureLevelPyramidData(void *dst, uint32_t dstLen, const tcu::TextureLevelPyramid &srcImage,
307 vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy> *copySlices)
308 {
309 // \note cube is copied face-by-face
310 const uint32_t arraySize =
311 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
312 (srcImage.getLevel(0).getHeight()) :
313 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ?
314 (srcImage.getLevel(0).getDepth()) :
315 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
316 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
317 (srcImage.getLevel(0).getDepth()) :
318 ((uint32_t)0);
319 uint32_t levelOffset = 0;
320
321 DE_ASSERT(arraySize != 0);
322
323 for (int level = 0; level < srcImage.getNumLevels(); ++level)
324 {
325 const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
326 const tcu::PixelBufferAccess dstAccess(srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(),
327 (uint8_t *)dst + levelOffset);
328 const uint32_t dataSize =
329 srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
330 const uint32_t sliceDataSize = dataSize / arraySize;
331 const int32_t sliceHeight =
332 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
333 (1) :
334 (srcAccess.getHeight());
335 const int32_t sliceDepth = (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1);
336 const tcu::IVec3 sliceSize(srcAccess.getWidth(), sliceHeight, sliceDepth);
337
338 // tightly packed
339 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
340
341 for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx)
342 {
343 const vk::VkBufferImageCopy copySlice = {
344 (vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize, // bufferOffset
345 (uint32_t)sliceSize.x(), // bufferRowLength
346 (uint32_t)sliceSize.y(), // bufferImageHeight
347 {
348 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
349 (uint32_t)level, // mipLevel
350 (uint32_t)sliceNdx, // arrayLayer
351 1u, // arraySize
352 }, // imageSubresource
353 {
354 0,
355 0,
356 0,
357 }, // imageOffset
358 {
359 (uint32_t)sliceSize.x(),
360 (uint32_t)sliceSize.y(),
361 (uint32_t)sliceSize.z(),
362 } // imageExtent
363 };
364 copySlices->push_back(copySlice);
365 }
366
367 DE_ASSERT(arraySize * sliceDataSize == dataSize);
368
369 tcu::copy(dstAccess, srcAccess);
370 levelOffset += dataSize;
371 }
372
373 DE_ASSERT(dstLen == levelOffset);
374 DE_UNREF(dstLen);
375 }
376
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkBuffer buffer,vk::MemoryRequirement requirement)377 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory(const vk::DeviceInterface &vki, vk::VkDevice device,
378 vk::Allocator &allocator, vk::VkBuffer buffer,
379 vk::MemoryRequirement requirement)
380 {
381 const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vki, device, buffer);
382 de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement);
383
384 VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
385 return allocation;
386 }
387
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkImage image,vk::MemoryRequirement requirement)388 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory(const vk::DeviceInterface &vki, vk::VkDevice device,
389 vk::Allocator &allocator, vk::VkImage image,
390 vk::MemoryRequirement requirement)
391 {
392 const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vki, device, image);
393 de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement);
394
395 VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
396 return allocation;
397 }
398
makeDescriptorImageInfo(vk::VkSampler sampler)399 vk::VkDescriptorImageInfo makeDescriptorImageInfo(vk::VkSampler sampler)
400 {
401 return vk::makeDescriptorImageInfo(sampler, VK_NULL_HANDLE, (vk::VkImageLayout)0);
402 }
403
makeDescriptorImageInfo(vk::VkImageView imageView,vk::VkImageLayout layout)404 vk::VkDescriptorImageInfo makeDescriptorImageInfo(vk::VkImageView imageView, vk::VkImageLayout layout)
405 {
406 return vk::makeDescriptorImageInfo(VK_NULL_HANDLE, imageView, layout);
407 }
408
drawQuadrantReferenceResult(const tcu::PixelBufferAccess & dst,const tcu::Vec4 & c1,const tcu::Vec4 & c2,const tcu::Vec4 & c3,const tcu::Vec4 & c4)409 void drawQuadrantReferenceResult(const tcu::PixelBufferAccess &dst, const tcu::Vec4 &c1, const tcu::Vec4 &c2,
410 const tcu::Vec4 &c3, const tcu::Vec4 &c4)
411 {
412 tcu::clear(tcu::getSubregion(dst, 0, 0, dst.getWidth() / 2, dst.getHeight() / 2), c1);
413 tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, 0, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() / 2),
414 c2);
415 tcu::clear(
416 tcu::getSubregion(dst, 0, dst.getHeight() / 2, dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c3);
417 tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, dst.getHeight() / 2, dst.getWidth() - dst.getWidth() / 2,
418 dst.getHeight() - dst.getHeight() / 2),
419 c4);
420 }
421
422 #ifndef CTS_USES_VULKANSC
createTemplateBinding(uint32_t binding,uint32_t arrayElement,uint32_t descriptorCount,vk::VkDescriptorType descriptorType,size_t offset,size_t stride)423 static const vk::VkDescriptorUpdateTemplateEntry createTemplateBinding(uint32_t binding, uint32_t arrayElement,
424 uint32_t descriptorCount,
425 vk::VkDescriptorType descriptorType,
426 size_t offset, size_t stride)
427 {
428 const vk::VkDescriptorUpdateTemplateEntry updateBinding = {binding, arrayElement, descriptorCount,
429 descriptorType, offset, stride};
430
431 return updateBinding;
432 }
433
434 class RawUpdateRegistry
435 {
436 public:
437 RawUpdateRegistry(void);
438
439 template <typename Type>
440 void addWriteObject(const Type &updateObject);
441 size_t getWriteObjectOffset(const uint32_t objectId);
442 const uint8_t *getRawPointer() const;
443
444 private:
445 std::vector<uint8_t> m_updateEntries;
446 std::vector<size_t> m_updateEntryOffsets;
447 size_t m_nextOffset;
448 };
449
RawUpdateRegistry(void)450 RawUpdateRegistry::RawUpdateRegistry(void) : m_updateEntries(), m_updateEntryOffsets(), m_nextOffset(0)
451 {
452 }
453
454 template <typename Type>
addWriteObject(const Type & updateObject)455 void RawUpdateRegistry::addWriteObject(const Type &updateObject)
456 {
457 m_updateEntryOffsets.push_back(m_nextOffset);
458
459 // in this case, elements <=> bytes
460 m_updateEntries.resize(m_nextOffset + sizeof(updateObject));
461 Type *t = reinterpret_cast<Type *>(m_updateEntries.data() + m_nextOffset);
462 *t = updateObject;
463 m_nextOffset += sizeof(updateObject);
464 }
465
getWriteObjectOffset(const uint32_t objectId)466 size_t RawUpdateRegistry::getWriteObjectOffset(const uint32_t objectId)
467 {
468 return m_updateEntryOffsets[objectId];
469 }
470
getRawPointer() const471 const uint8_t *RawUpdateRegistry::getRawPointer() const
472 {
473 return m_updateEntries.data();
474 }
475 #endif
476
bindDescriptorSets(const vk::DeviceInterface & m_vki,vk::VkCommandBuffer cmdBuffer,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,vk::VkPipelineBindPoint bindPoint,vk::VkPipelineLayout layout,uint32_t first,uint32_t count,const vk::VkDescriptorSet * descriptorSets,uint32_t dynamicOffsetCount,const uint32_t * dynamicOffsets,bool bind2)477 void bindDescriptorSets(const vk::DeviceInterface &m_vki, vk::VkCommandBuffer cmdBuffer,
478 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
479 vk::VkPipelineBindPoint bindPoint, vk::VkPipelineLayout layout, uint32_t first, uint32_t count,
480 const vk::VkDescriptorSet *descriptorSets, uint32_t dynamicOffsetCount,
481 const uint32_t *dynamicOffsets, bool bind2)
482 {
483 DE_UNREF(stageFlags);
484 DE_UNREF(existingStages);
485 if (bind2)
486 {
487 #ifndef CTS_USES_VULKANSC
488 vk::VkBindDescriptorSetsInfoKHR bindDescriptorSetsInfo = {
489 vk::VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO_KHR, // VkStructureType sType;
490 nullptr, // const void* pNext;
491 existingStages, // VkShaderStageFlags stageFlags;
492 layout, // VkPipelineLayout layout;
493 first, // uint32_t firstSet;
494 count, // uint32_t descriptorSetCount;
495 descriptorSets, // const VkDescriptorSet* pDescriptorSets;
496 dynamicOffsetCount, // uint32_t dynamicOffsetCount;
497 dynamicOffsets // const uint32_t* pDynamicOffsets;
498 };
499 m_vki.cmdBindDescriptorSets2(cmdBuffer, &bindDescriptorSetsInfo);
500 #endif
501 }
502 else
503 {
504 m_vki.cmdBindDescriptorSets(cmdBuffer, bindPoint, layout, first, count, descriptorSets, dynamicOffsetCount,
505 dynamicOffsets);
506 }
507 }
508
509 class SingleTargetRenderInstance : public vkt::TestInstance
510 {
511 public:
512 SingleTargetRenderInstance(Context &context, const tcu::UVec2 &size, const bool bind2);
513
514 private:
515 static vk::Move<vk::VkImage> createColorAttachment(const vk::DeviceInterface &vki, vk::VkDevice device,
516 vk::Allocator &allocator, const tcu::TextureFormat &format,
517 const tcu::UVec2 &size,
518 de::MovePtr<vk::Allocation> *outAllocation);
519
520 static vk::Move<vk::VkImageView> createColorAttachmentView(const vk::DeviceInterface &vki, vk::VkDevice device,
521 const tcu::TextureFormat &format, vk::VkImage image);
522
523 static vk::Move<vk::VkFramebuffer> createFramebuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
524 vk::VkRenderPass renderpass,
525 vk::VkImageView colorAttachmentView, const tcu::UVec2 &size);
526
527 static vk::Move<vk::VkCommandPool> createCommandPool(const vk::DeviceInterface &vki, vk::VkDevice device,
528 uint32_t queueFamilyIndex);
529
530 virtual void logTestPlan(void) const = 0;
531 virtual void renderToTarget(void) = 0;
532 virtual tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const = 0;
533
534 void readRenderTarget(tcu::TextureLevel &dst);
535 tcu::TestStatus iterate(void);
536
537 protected:
538 const tcu::TextureFormat m_targetFormat;
539 const tcu::UVec2 m_targetSize;
540 const bool m_bind2;
541
542 const vk::DeviceInterface &m_vki;
543 const vk::VkDevice m_device;
544 const vk::VkQueue m_queue;
545 const uint32_t m_queueFamilyIndex;
546 vk::Allocator &m_allocator;
547 de::MovePtr<vk::Allocation> m_colorAttachmentMemory;
548 const vk::Unique<vk::VkImage> m_colorAttachmentImage;
549 const vk::Unique<vk::VkImageView> m_colorAttachmentView;
550 const vk::Unique<vk::VkRenderPass> m_renderPass;
551 const vk::Unique<vk::VkFramebuffer> m_framebuffer;
552 const vk::Unique<vk::VkCommandPool> m_cmdPool;
553
554 bool m_firstIteration;
555 };
556
SingleTargetRenderInstance(Context & context,const tcu::UVec2 & size,const bool bind2)557 SingleTargetRenderInstance::SingleTargetRenderInstance(Context &context, const tcu::UVec2 &size, const bool bind2)
558 : vkt::TestInstance(context)
559 , m_targetFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
560 , m_targetSize(size)
561 , m_bind2(bind2)
562 , m_vki(context.getDeviceInterface())
563 , m_device(context.getDevice())
564 , m_queue(context.getUniversalQueue())
565 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
566 , m_allocator(context.getDefaultAllocator())
567 , m_colorAttachmentMemory(nullptr)
568 , m_colorAttachmentImage(
569 createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory))
570 , m_colorAttachmentView(createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage))
571 , m_renderPass(makeRenderPass(m_vki, m_device, vk::mapTextureFormat(m_targetFormat)))
572 , m_framebuffer(createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize))
573 , m_cmdPool(createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex()))
574 , m_firstIteration(true)
575 {
576 }
577
createColorAttachment(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,const tcu::TextureFormat & format,const tcu::UVec2 & size,de::MovePtr<vk::Allocation> * outAllocation)578 vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment(const vk::DeviceInterface &vki,
579 vk::VkDevice device, vk::Allocator &allocator,
580 const tcu::TextureFormat &format,
581 const tcu::UVec2 &size,
582 de::MovePtr<vk::Allocation> *outAllocation)
583 {
584 const vk::VkImageCreateInfo imageInfo = {
585 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
586 nullptr,
587 (vk::VkImageCreateFlags)0,
588 vk::VK_IMAGE_TYPE_2D, // imageType
589 vk::mapTextureFormat(format), // format
590 {size.x(), size.y(), 1u}, // extent
591 1, // mipLevels
592 1, // arraySize
593 vk::VK_SAMPLE_COUNT_1_BIT, // samples
594 vk::VK_IMAGE_TILING_OPTIMAL, // tiling
595 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
596 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
597 0u, // queueFamilyCount
598 nullptr, // pQueueFamilyIndices
599 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
600 };
601
602 vk::Move<vk::VkImage> image(vk::createImage(vki, device, &imageInfo));
603 de::MovePtr<vk::Allocation> allocation(
604 allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any));
605
606 *outAllocation = allocation;
607 return image;
608 }
609
createColorAttachmentView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & format,vk::VkImage image)610 vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView(const vk::DeviceInterface &vki,
611 vk::VkDevice device,
612 const tcu::TextureFormat &format,
613 vk::VkImage image)
614 {
615 const vk::VkImageViewCreateInfo createInfo = {
616 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
617 nullptr,
618 (vk::VkImageViewCreateFlags)0,
619 image, // image
620 vk::VK_IMAGE_VIEW_TYPE_2D, // viewType
621 vk::mapTextureFormat(format), // format
622 vk::makeComponentMappingRGBA(),
623 {
624 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
625 0u, // baseMipLevel
626 1u, // mipLevels
627 0u, // baseArrayLayer
628 1u, // arraySize
629 },
630 };
631
632 return vk::createImageView(vki, device, &createInfo);
633 }
634
createFramebuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkRenderPass renderpass,vk::VkImageView colorAttachmentView,const tcu::UVec2 & size)635 vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer(const vk::DeviceInterface &vki,
636 vk::VkDevice device,
637 vk::VkRenderPass renderpass,
638 vk::VkImageView colorAttachmentView,
639 const tcu::UVec2 &size)
640 {
641 const vk::VkFramebufferCreateInfo framebufferCreateInfo = {
642 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
643 nullptr,
644 (vk::VkFramebufferCreateFlags)0,
645 renderpass, // renderPass
646 1u, // attachmentCount
647 &colorAttachmentView, // pAttachments
648 size.x(), // width
649 size.y(), // height
650 1, // layers
651 };
652
653 return vk::createFramebuffer(vki, device, &framebufferCreateInfo);
654 }
655
createCommandPool(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex)656 vk::Move<vk::VkCommandPool> SingleTargetRenderInstance::createCommandPool(const vk::DeviceInterface &vki,
657 vk::VkDevice device,
658 uint32_t queueFamilyIndex)
659 {
660 return vk::createCommandPool(vki, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
661 }
662
readRenderTarget(tcu::TextureLevel & dst)663 void SingleTargetRenderInstance::readRenderTarget(tcu::TextureLevel &dst)
664 {
665 const uint64_t pixelDataSize = (uint64_t)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize());
666 const vk::VkBufferCreateInfo bufferCreateInfo = {
667 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
668 nullptr,
669 0u, // flags
670 pixelDataSize, // size
671 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
672 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
673 0u, // queueFamilyCount
674 nullptr, // pQueueFamilyIndices
675 };
676 const vk::Unique<vk::VkBuffer> buffer(vk::createBuffer(m_vki, m_device, &bufferCreateInfo));
677
678 const de::MovePtr<vk::Allocation> bufferMemory =
679 allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible);
680
681 const vk::Unique<vk::VkCommandBuffer> cmd(
682 vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
683
684 // copy content to buffer
685 beginCommandBuffer(m_vki, *cmd);
686 copyImageToBuffer(m_vki, *cmd, *m_colorAttachmentImage, *buffer, tcu::IVec2(m_targetSize.x(), m_targetSize.y()));
687 endCommandBuffer(m_vki, *cmd);
688
689 submitCommandsAndWait(m_vki, m_device, m_queue, cmd.get());
690
691 dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y());
692
693 // copy data
694 invalidateAlloc(m_vki, m_device, *bufferMemory);
695 tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr()));
696 }
697
iterate(void)698 tcu::TestStatus SingleTargetRenderInstance::iterate(void)
699 {
700 tcu::TextureLevel resultImage;
701
702 // log
703 if (m_firstIteration)
704 {
705 logTestPlan();
706 m_firstIteration = false;
707 }
708
709 // render
710 {
711 // transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
712 const vk::VkImageSubresourceRange fullSubrange = {
713 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
714 0u, // baseMipLevel
715 1u, // mipLevels
716 0u, // baseArraySlice
717 1u, // arraySize
718 };
719 const vk::VkImageMemoryBarrier imageBarrier = {
720 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
721 nullptr,
722 0u, // srcAccessMask
723 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
724 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
725 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
726 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
727 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
728 *m_colorAttachmentImage, // image
729 fullSubrange, // subresourceRange
730 };
731
732 const vk::Unique<vk::VkCommandBuffer> cmd(
733 vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
734
735 beginCommandBuffer(m_vki, *cmd);
736 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
737 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0, 0,
738 nullptr, 0, nullptr, 1, &imageBarrier);
739 endCommandBuffer(m_vki, *cmd);
740
741 submitCommandsAndWait(m_vki, m_device, m_queue, cmd.get());
742
743 renderToTarget();
744 }
745
746 // read and verify
747 readRenderTarget(resultImage);
748 #ifdef CTS_USES_VULKANSC
749 // skip costly verification in main process
750 if (!m_context.getTestContext().getCommandLine().isSubProcess())
751 return tcu::TestStatus::pass("Success");
752 #endif // CTS_USES_VULKANSC
753 return verifyResultImage(resultImage.getAccess());
754 }
755
756 class RenderInstanceShaders
757 {
758 public:
759 RenderInstanceShaders(const vk::DeviceInterface &vki, vk::VkDevice device,
760 const vk::VkPhysicalDeviceFeatures &deviceFeatures,
761 const vk::BinaryCollection &programCollection);
762
hasTessellationStage(void) const763 inline bool hasTessellationStage(void) const
764 {
765 return *m_tessCtrlShaderModule != VK_NULL_HANDLE || *m_tessEvalShaderModule != VK_NULL_HANDLE;
766 }
getNumStages(void) const767 inline uint32_t getNumStages(void) const
768 {
769 return (uint32_t)m_stageInfos.size();
770 }
getStages(void) const771 inline const vk::VkPipelineShaderStageCreateInfo *getStages(void) const
772 {
773 return &m_stageInfos[0];
774 }
775
776 private:
777 void addStage(const vk::DeviceInterface &vki, vk::VkDevice device,
778 const vk::VkPhysicalDeviceFeatures &deviceFeatures, const vk::BinaryCollection &programCollection,
779 const char *name, vk::VkShaderStageFlagBits stage, vk::Move<vk::VkShaderModule> *outModule);
780
781 vk::VkPipelineShaderStageCreateInfo getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,
782 vk::VkShaderModule shader) const;
783
784 vk::Move<vk::VkShaderModule> m_vertexShaderModule;
785 vk::Move<vk::VkShaderModule> m_tessCtrlShaderModule;
786 vk::Move<vk::VkShaderModule> m_tessEvalShaderModule;
787 vk::Move<vk::VkShaderModule> m_geometryShaderModule;
788 vk::Move<vk::VkShaderModule> m_fragmentShaderModule;
789 std::vector<vk::VkPipelineShaderStageCreateInfo> m_stageInfos;
790 };
791
RenderInstanceShaders(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const vk::BinaryCollection & programCollection)792 RenderInstanceShaders::RenderInstanceShaders(const vk::DeviceInterface &vki, vk::VkDevice device,
793 const vk::VkPhysicalDeviceFeatures &deviceFeatures,
794 const vk::BinaryCollection &programCollection)
795 {
796 addStage(vki, device, deviceFeatures, programCollection, "vertex", vk::VK_SHADER_STAGE_VERTEX_BIT,
797 &m_vertexShaderModule);
798 addStage(vki, device, deviceFeatures, programCollection, "tess_ctrl", vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
799 &m_tessCtrlShaderModule);
800 addStage(vki, device, deviceFeatures, programCollection, "tess_eval",
801 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvalShaderModule);
802 addStage(vki, device, deviceFeatures, programCollection, "geometry", vk::VK_SHADER_STAGE_GEOMETRY_BIT,
803 &m_geometryShaderModule);
804 addStage(vki, device, deviceFeatures, programCollection, "fragment", vk::VK_SHADER_STAGE_FRAGMENT_BIT,
805 &m_fragmentShaderModule);
806
807 DE_ASSERT(!m_stageInfos.empty());
808 }
809
addStage(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const vk::BinaryCollection & programCollection,const char * name,vk::VkShaderStageFlagBits stage,vk::Move<vk::VkShaderModule> * outModule)810 void RenderInstanceShaders::addStage(const vk::DeviceInterface &vki, vk::VkDevice device,
811 const vk::VkPhysicalDeviceFeatures &deviceFeatures,
812 const vk::BinaryCollection &programCollection, const char *name,
813 vk::VkShaderStageFlagBits stage, vk::Move<vk::VkShaderModule> *outModule)
814 {
815 if (programCollection.contains(name))
816 {
817 if (vk::isShaderStageSupported(deviceFeatures, stage))
818 {
819 vk::Move<vk::VkShaderModule> module =
820 createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0);
821
822 m_stageInfos.push_back(getShaderStageCreateInfo(stage, *module));
823 *outModule = module;
824 }
825 else
826 {
827 // Wait for the GPU to idle so that throwing the exception
828 // below doesn't free in-use GPU resource.
829 vki.deviceWaitIdle(device);
830 TCU_THROW(NotSupportedError, (de::toString(stage) + " is not supported").c_str());
831 }
832 }
833 }
834
getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,vk::VkShaderModule shader) const835 vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,
836 vk::VkShaderModule shader) const
837 {
838 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo = {
839 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
840 nullptr,
841 (vk::VkPipelineShaderStageCreateFlags)0,
842 stage, // stage
843 shader, // shader
844 "main",
845 nullptr, // pSpecializationInfo
846 };
847 return stageCreateInfo;
848 }
849
850 class SingleCmdRenderInstance : public SingleTargetRenderInstance
851 {
852 public:
853 SingleCmdRenderInstance(Context &context, bool isPrimaryCmdBuf, const tcu::UVec2 &renderSize, const bool bind2);
854
855 private:
856 vk::Move<vk::VkPipeline> createPipeline(vk::VkPipelineLayout pipelineLayout);
857
858 virtual vk::VkPipelineLayout getPipelineLayout(void) const = 0;
859 virtual void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const = 0;
860
861 void renderToTarget(void);
862
863 const bool m_isPrimaryCmdBuf;
864 };
865
SingleCmdRenderInstance(Context & context,bool isPrimaryCmdBuf,const tcu::UVec2 & renderSize,const bool bind2)866 SingleCmdRenderInstance::SingleCmdRenderInstance(Context &context, bool isPrimaryCmdBuf, const tcu::UVec2 &renderSize,
867 const bool bind2)
868 : SingleTargetRenderInstance(context, renderSize, bind2)
869 , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
870 {
871 }
872
createPipeline(vk::VkPipelineLayout pipelineLayout)873 vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline(vk::VkPipelineLayout pipelineLayout)
874 {
875 const RenderInstanceShaders shaderStages(m_vki, m_device, m_context.getDeviceFeatures(),
876 m_context.getBinaryCollection());
877 const vk::VkPrimitiveTopology topology = shaderStages.hasTessellationStage() ?
878 vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
879 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
880 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = {
881 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
882 nullptr,
883 (vk::VkPipelineVertexInputStateCreateFlags)0,
884 0u, // bindingCount
885 nullptr, // pVertexBindingDescriptions
886 0u, // attributeCount
887 nullptr, // pVertexAttributeDescriptions
888 };
889 const vk::VkPipelineInputAssemblyStateCreateInfo iaState = {
890 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
891 nullptr,
892 (vk::VkPipelineInputAssemblyStateCreateFlags)0,
893 topology, // topology
894 VK_FALSE, // primitiveRestartEnable
895 };
896 const vk::VkPipelineTessellationStateCreateInfo tessState = {
897 vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, nullptr,
898 (vk::VkPipelineTessellationStateCreateFlags)0,
899 3u, // patchControlPoints
900 };
901 const vk::VkViewport viewport = vk::makeViewport(m_targetSize);
902 const vk::VkRect2D renderArea = vk::makeRect2D(m_targetSize);
903 const vk::VkPipelineViewportStateCreateInfo vpState = {
904 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
905 nullptr,
906 (vk::VkPipelineViewportStateCreateFlags)0,
907 1u, // viewportCount
908 &viewport,
909 1u,
910 &renderArea,
911 };
912 const vk::VkPipelineRasterizationStateCreateInfo rsState = {
913 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
914 nullptr,
915 (vk::VkPipelineRasterizationStateCreateFlags)0,
916 VK_FALSE, // depthClipEnable
917 VK_FALSE, // rasterizerDiscardEnable
918 vk::VK_POLYGON_MODE_FILL, // fillMode
919 vk::VK_CULL_MODE_NONE, // cullMode
920 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
921 VK_FALSE, // depthBiasEnable
922 0.0f, // depthBias
923 0.0f, // depthBiasClamp
924 0.0f, // slopeScaledDepthBias
925 1.0f, // lineWidth
926 };
927 const vk::VkSampleMask sampleMask = 0x01u;
928 const vk::VkPipelineMultisampleStateCreateInfo msState = {
929 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
930 nullptr,
931 (vk::VkPipelineMultisampleStateCreateFlags)0,
932 vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples
933 VK_FALSE, // sampleShadingEnable
934 0.0f, // minSampleShading
935 &sampleMask, // sampleMask
936 VK_FALSE, // alphaToCoverageEnable
937 VK_FALSE, // alphaToOneEnable
938 };
939 const vk::VkPipelineDepthStencilStateCreateInfo dsState = {
940 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
941 nullptr,
942 (vk::VkPipelineDepthStencilStateCreateFlags)0,
943 VK_FALSE, // depthTestEnable
944 VK_FALSE, // depthWriteEnable
945 vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp
946 VK_FALSE, // depthBoundsTestEnable
947 VK_FALSE, // stencilTestEnable
948 {vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u,
949 0u}, // front
950 {vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u,
951 0u}, // back
952 -1.0f, // minDepthBounds
953 +1.0f, // maxDepthBounds
954 };
955 const vk::VkPipelineColorBlendAttachmentState cbAttachment = {
956 VK_FALSE, // blendEnable
957 vk::VK_BLEND_FACTOR_ZERO, // srcBlendColor
958 vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
959 vk::VK_BLEND_OP_ADD, // blendOpColor
960 vk::VK_BLEND_FACTOR_ZERO, // srcBlendAlpha
961 vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
962 vk::VK_BLEND_OP_ADD, // blendOpAlpha
963 (vk::VK_COLOR_COMPONENT_R_BIT | vk::VK_COLOR_COMPONENT_G_BIT | vk::VK_COLOR_COMPONENT_B_BIT |
964 vk::VK_COLOR_COMPONENT_A_BIT), // channelWriteMask
965 };
966 const vk::VkPipelineColorBlendStateCreateInfo cbState = {
967 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
968 nullptr,
969 (vk::VkPipelineColorBlendStateCreateFlags)0,
970 VK_FALSE, // logicOpEnable
971 vk::VK_LOGIC_OP_CLEAR, // logicOp
972 1u, // attachmentCount
973 &cbAttachment, // pAttachments
974 {0.0f, 0.0f, 0.0f, 0.0f}, // blendConst
975 };
976 const vk::VkGraphicsPipelineCreateInfo createInfo = {
977 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
978 nullptr,
979 (vk::VkPipelineCreateFlags)0,
980 shaderStages.getNumStages(), // stageCount
981 shaderStages.getStages(), // pStages
982 &vertexInputState, // pVertexInputState
983 &iaState, // pInputAssemblyState
984 (shaderStages.hasTessellationStage() ? &tessState : nullptr), // pTessellationState
985 &vpState, // pViewportState
986 &rsState, // pRasterState
987 &msState, // pMultisampleState
988 &dsState, // pDepthStencilState
989 &cbState, // pColorBlendState
990 nullptr, // pDynamicState
991 pipelineLayout, // layout
992 *m_renderPass, // renderPass
993 0u, // subpass
994 VK_NULL_HANDLE, // basePipelineHandle
995 0u, // basePipelineIndex
996 };
997 return createGraphicsPipeline(m_vki, m_device, VK_NULL_HANDLE, &createInfo);
998 }
999
renderToTarget(void)1000 void SingleCmdRenderInstance::renderToTarget(void)
1001 {
1002 const vk::VkRect2D renderArea = {
1003 {0, 0}, // offset
1004 {m_targetSize.x(), m_targetSize.y()}, // extent
1005 };
1006 const vk::VkCommandBufferInheritanceInfo passCmdBufInheritInfo = {
1007 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1008 nullptr,
1009 (vk::VkRenderPass)*m_renderPass, // renderPass
1010 0u, // subpass
1011 (vk::VkFramebuffer)*m_framebuffer, // framebuffer
1012 VK_FALSE, // occlusionQueryEnable
1013 (vk::VkQueryControlFlags)0,
1014 (vk::VkQueryPipelineStatisticFlags)0,
1015 };
1016 const vk::VkCommandBufferBeginInfo passCmdBufBeginInfo = {
1017 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1018 nullptr,
1019 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // flags
1020 &passCmdBufInheritInfo,
1021 };
1022
1023 const vk::VkPipelineLayout pipelineLayout(getPipelineLayout());
1024 const vk::Unique<vk::VkPipeline> pipeline(createPipeline(pipelineLayout));
1025 const vk::Unique<vk::VkCommandBuffer> mainCmd(
1026 vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1027 const vk::Unique<vk::VkCommandBuffer> passCmd(
1028 (m_isPrimaryCmdBuf) ?
1029 (vk::Move<vk::VkCommandBuffer>()) :
1030 (vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY)));
1031 const vk::Unique<vk::VkFence> fence(vk::createFence(m_vki, m_device));
1032 const vk::VkSubpassContents passContents =
1033 (m_isPrimaryCmdBuf) ? (vk::VK_SUBPASS_CONTENTS_INLINE) : (vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1034
1035 if (!m_isPrimaryCmdBuf)
1036 {
1037 VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo));
1038 m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1039 writeDrawCmdBuffer(*passCmd);
1040 endCommandBuffer(m_vki, *passCmd);
1041 }
1042
1043 beginCommandBuffer(m_vki, *mainCmd);
1044 beginRenderPass(m_vki, *mainCmd, *m_renderPass, *m_framebuffer, renderArea, tcu::Vec4(0.0f), passContents);
1045
1046 if (m_isPrimaryCmdBuf)
1047 {
1048 m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1049 writeDrawCmdBuffer(*mainCmd);
1050 }
1051 else
1052 {
1053 m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get());
1054 }
1055
1056 endRenderPass(m_vki, *mainCmd);
1057 endCommandBuffer(m_vki, *mainCmd);
1058
1059 // submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no).
1060 submitCommandsAndWait(m_vki, m_device, m_queue, mainCmd.get());
1061 }
1062
1063 enum DescriptorSetCount
1064 {
1065 DESCRIPTOR_SET_COUNT_SINGLE = 0, //!< single descriptor set
1066 DESCRIPTOR_SET_COUNT_MULTIPLE, //!< multiple descriptor sets
1067 DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS, //!< multiple discontiguous descriptor sets
1068
1069 DESCRIPTOR_SET_COUNT_LAST
1070 };
1071
getDescriptorSetCount(DescriptorSetCount count)1072 uint32_t getDescriptorSetCount(DescriptorSetCount count)
1073 {
1074 switch (count)
1075 {
1076 case DESCRIPTOR_SET_COUNT_SINGLE:
1077 return 1u;
1078 case DESCRIPTOR_SET_COUNT_MULTIPLE:
1079 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1080 return 2u;
1081 default:
1082 DE_FATAL("Impossible");
1083 return 0u;
1084 }
1085 }
1086
getDescriptorSetNdx(DescriptorSetCount count,uint32_t setNdx)1087 uint32_t getDescriptorSetNdx(DescriptorSetCount count, uint32_t setNdx)
1088 {
1089 DE_ASSERT(setNdx < getDescriptorSetCount(count));
1090
1091 const uint32_t contiguousNdx[] = {0, 1};
1092 const uint32_t discontiguousNdx[] = {0, 2};
1093
1094 switch (count)
1095 {
1096 case DESCRIPTOR_SET_COUNT_SINGLE:
1097 return 0u;
1098 case DESCRIPTOR_SET_COUNT_MULTIPLE:
1099 return contiguousNdx[setNdx];
1100 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1101 return discontiguousNdx[setNdx];
1102 default:
1103 DE_FATAL("Impossible");
1104 return 0u;
1105 }
1106 }
1107
1108 enum ShaderInputInterface
1109 {
1110 SHADER_INPUT_SINGLE_DESCRIPTOR = 0, //!< one descriptor
1111 SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with contiguous binding id's
1112 SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with discontiguous binding id's
1113 SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS, //!< multiple descriptors with large gaps between binding id's
1114 SHADER_INPUT_DESCRIPTOR_ARRAY, //!< descriptor array
1115
1116 SHADER_INPUT_LAST
1117 };
1118
getInterfaceNumResources(ShaderInputInterface shaderInterface)1119 uint32_t getInterfaceNumResources(ShaderInputInterface shaderInterface)
1120 {
1121 switch (shaderInterface)
1122 {
1123 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1124 return 1u;
1125 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1126 return 2u;
1127 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1128 return 2u;
1129 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1130 return 2u;
1131 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1132 return 2u;
1133
1134 default:
1135 DE_FATAL("Impossible");
1136 return 0u;
1137 }
1138 }
1139
getArbitraryBindingIndex(uint32_t ndx)1140 uint32_t getArbitraryBindingIndex(uint32_t ndx)
1141 {
1142 DE_ASSERT(ndx < 2);
1143
1144 // Binding decoration value can be any 32-bit unsigned integer value.
1145 // 0xFFFE is the largest binding value accepted by glslang
1146
1147 const uint32_t bufferIndices[] = {
1148 #ifndef CTS_USES_VULKANSC
1149 0x7FFEu, 0xFFFEu
1150 #else
1151 // Use smaller values for VulkanSC since these can produce huge static memory allocations
1152 0x1FFu, 0x3FFu
1153 #endif
1154 };
1155
1156 return bufferIndices[ndx];
1157 }
1158
1159 typedef de::MovePtr<vk::Allocation> AllocationMp;
1160 typedef de::SharedPtr<vk::Allocation> AllocationSp;
1161 typedef vk::Unique<vk::VkBuffer> BufferHandleUp;
1162 typedef de::SharedPtr<BufferHandleUp> BufferHandleSp;
1163 typedef vk::Unique<vk::VkBufferView> BufferViewHandleUp;
1164 typedef de::SharedPtr<BufferViewHandleUp> BufferViewHandleSp;
1165 typedef vk::Unique<vk::VkSampler> SamplerHandleUp;
1166 typedef de::SharedPtr<SamplerHandleUp> SamplerHandleSp;
1167 typedef vk::Unique<vk::VkImage> ImageHandleUp;
1168 typedef de::SharedPtr<ImageHandleUp> ImageHandleSp;
1169 typedef vk::Unique<vk::VkImageView> ImageViewHandleUp;
1170 typedef de::SharedPtr<ImageViewHandleUp> ImageViewHandleSp;
1171 typedef vk::Unique<vk::VkDescriptorSet> DescriptorSetHandleUp;
1172 typedef de::SharedPtr<DescriptorSetHandleUp> DescriptorSetHandleSp;
1173 typedef vk::Unique<vk::VkDescriptorSetLayout> DescriptorSetLayoutHandleUp;
1174 typedef de::SharedPtr<DescriptorSetLayoutHandleUp> DescriptorSetLayoutHandleSp;
1175 #ifndef CTS_USES_VULKANSC
1176 typedef vk::Unique<vk::VkDescriptorUpdateTemplate> UpdateTemplateHandleUp;
1177 typedef de::SharedPtr<UpdateTemplateHandleUp> UpdateTemplateHandleSp;
1178 #endif
1179
1180 class BufferRenderInstance : public SingleCmdRenderInstance
1181 {
1182 public:
1183 BufferRenderInstance(Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
1184 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1185 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
1186 ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
1187 bool dynamicOffsetNonZero, bool bind2);
1188
1189 static std::vector<uint32_t> getViewOffsets(DescriptorSetCount descriptorSetCount,
1190 ShaderInputInterface shaderInterface, bool setViewOffset);
1191
1192 static std::vector<uint32_t> getDynamicOffsets(DescriptorSetCount descriptorSetCount,
1193 ShaderInputInterface shaderInterface, bool dynamicOffsetNonZero);
1194
1195 static std::vector<BufferHandleSp> createSourceBuffers(
1196 const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator,
1197 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1198 ShaderInputInterface shaderInterface, const std::vector<uint32_t> &viewOffset,
1199 const std::vector<uint32_t> &dynamicOffset, std::vector<AllocationSp> &bufferMemory);
1200
1201 static vk::Move<vk::VkBuffer> createSourceBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1202 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
1203 uint32_t setNdx, uint32_t offset, uint32_t bufferSize,
1204 de::MovePtr<vk::Allocation> *outMemory);
1205
1206 static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
1207 vk::VkDescriptorType descriptorType,
1208 DescriptorSetCount descriptorSetCount,
1209 ShaderInputInterface shaderInterface);
1210
1211 static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
1212 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
1213 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
1214 DescriptorUpdateMethod updateMethod);
1215
1216 static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
1217 const vk::DeviceInterface &vki, vk::VkDevice device,
1218 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
1219
1220 static std::vector<DescriptorSetHandleSp> createDescriptorSets(
1221 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
1222 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool descriptorPool,
1223 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1224 ShaderInputInterface shaderInterface, const std::vector<BufferHandleSp> &buffers,
1225 const std::vector<uint32_t> &offsets, vk::DescriptorSetUpdateBuilder &updateBuilder,
1226 std::vector<uint32_t> &descriptorsPerSet,
1227 #ifndef CTS_USES_VULKANSC
1228 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
1229 #endif
1230 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
1231
1232 static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
1233 vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1234 vk::VkBuffer sourceBufferA, const uint32_t viewOffsetA, vk::VkBuffer sourceBufferB,
1235 const uint32_t viewOffsetB, vk::VkDescriptorSet descriptorSet,
1236 vk::DescriptorSetUpdateBuilder &updateBuilder,
1237 std::vector<uint32_t> &descriptorsPerSet,
1238 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
1239
1240 #ifndef CTS_USES_VULKANSC
1241 static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
1242 vk::VkDescriptorSetLayout descriptorSetLayout, uint32_t setNdx,
1243 vk::VkDescriptorPool descriptorPool, vk::VkDescriptorType descriptorType,
1244 ShaderInputInterface shaderInterface, vk::VkBuffer sourceBufferA,
1245 const uint32_t viewOffsetA, vk::VkBuffer sourceBufferB,
1246 const uint32_t viewOffsetB, vk::VkDescriptorSet descriptorSet,
1247 std::vector<UpdateTemplateHandleSp> &updateTemplates,
1248 std::vector<RawUpdateRegistry> ®istry, bool withPush = false,
1249 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
1250 #endif
1251
1252 void logTestPlan(void) const;
1253 vk::VkPipelineLayout getPipelineLayout(void) const;
1254 void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
1255 tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
1256
1257 enum
1258 {
1259 RENDER_SIZE = 128,
1260 BUFFER_DATA_SIZE = 8 * sizeof(float),
1261 BUFFER_SIZE_A = 2048, //!< a lot more than required
1262 BUFFER_SIZE_B = 2560, //!< a lot more than required
1263 BUFFER_SIZE_C = 2128, //!< a lot more than required
1264 BUFFER_SIZE_D = 2136, //!< a lot more than required
1265
1266 STATIC_OFFSET_VALUE_A = 256,
1267 DYNAMIC_OFFSET_VALUE_A = 512,
1268 STATIC_OFFSET_VALUE_B = 1024,
1269 DYNAMIC_OFFSET_VALUE_B = 768,
1270 STATIC_OFFSET_VALUE_C = 512,
1271 DYNAMIC_OFFSET_VALUE_C = 512,
1272 STATIC_OFFSET_VALUE_D = 768,
1273 DYNAMIC_OFFSET_VALUE_D = 1024,
1274 };
1275
1276 const DescriptorUpdateMethod m_updateMethod;
1277 const vk::VkDescriptorType m_descriptorType;
1278 const DescriptorSetCount m_descriptorSetCount;
1279 const ShaderInputInterface m_shaderInterface;
1280 const bool m_setViewOffset;
1281 const bool m_setDynamicOffset;
1282 const bool m_dynamicOffsetNonZero;
1283 const vk::VkShaderStageFlags m_stageFlags;
1284 const vk::VkShaderStageFlags m_existingStages;
1285
1286 const std::vector<uint32_t> m_viewOffset;
1287 const std::vector<uint32_t> m_dynamicOffset;
1288
1289 std::vector<AllocationSp> m_bufferMemory;
1290 const std::vector<BufferHandleSp> m_sourceBuffer;
1291 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
1292 #ifndef CTS_USES_VULKANSC
1293 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
1294 std::vector<RawUpdateRegistry> m_updateRegistry;
1295 #endif
1296 vk::DescriptorSetUpdateBuilder m_updateBuilder;
1297 const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
1298 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
1299 std::vector<uint32_t> m_descriptorsPerSet;
1300 const std::vector<DescriptorSetHandleSp> m_descriptorSets;
1301 };
1302
BufferRenderInstance(Context & context,DescriptorUpdateMethod updateMethod,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero,bool bind2)1303 BufferRenderInstance::BufferRenderInstance(Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
1304 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1305 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
1306 ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
1307 bool dynamicOffsetNonZero, bool bind2)
1308 : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
1309 , m_updateMethod(updateMethod)
1310 , m_descriptorType(descriptorType)
1311 , m_descriptorSetCount(descriptorSetCount)
1312 , m_shaderInterface(shaderInterface)
1313 , m_setViewOffset(viewOffset)
1314 , m_setDynamicOffset(dynamicOffset)
1315 , m_dynamicOffsetNonZero(dynamicOffsetNonZero)
1316 , m_stageFlags(stageFlags)
1317 , m_existingStages(existingStages)
1318 , m_viewOffset(getViewOffsets(m_descriptorSetCount, m_shaderInterface, m_setViewOffset))
1319 , m_dynamicOffset(getDynamicOffsets(m_descriptorSetCount, m_shaderInterface, m_dynamicOffsetNonZero))
1320 , m_bufferMemory()
1321 , m_sourceBuffer(createSourceBuffers(m_vki, m_device, m_allocator, m_descriptorType, m_descriptorSetCount,
1322 m_shaderInterface, m_viewOffset, m_dynamicOffset, m_bufferMemory))
1323 , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
1324 #ifndef CTS_USES_VULKANSC
1325 , m_updateTemplates()
1326 , m_updateRegistry()
1327 #endif
1328 , m_updateBuilder()
1329 , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
1330 m_shaderInterface, m_stageFlags, m_updateMethod))
1331 , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
1332 , m_descriptorsPerSet()
1333 , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorSetLayouts, *m_descriptorPool,
1334 m_descriptorType, m_descriptorSetCount, m_shaderInterface, m_sourceBuffer,
1335 m_viewOffset, m_updateBuilder, m_descriptorsPerSet,
1336 #ifndef CTS_USES_VULKANSC
1337 m_updateTemplates, m_updateRegistry,
1338 #endif
1339 *m_pipelineLayout))
1340 {
1341 if (m_setDynamicOffset)
1342 DE_ASSERT(isDynamicDescriptorType(m_descriptorType));
1343 if (m_dynamicOffsetNonZero)
1344 DE_ASSERT(m_setDynamicOffset);
1345 }
1346
getViewOffsets(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool setViewOffset)1347 std::vector<uint32_t> BufferRenderInstance::getViewOffsets(DescriptorSetCount descriptorSetCount,
1348 ShaderInputInterface shaderInterface, bool setViewOffset)
1349 {
1350 const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1351 std::vector<uint32_t> viewOffset;
1352
1353 for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1354 {
1355 const uint32_t staticOffsetValues[] = {STATIC_OFFSET_VALUE_A, STATIC_OFFSET_VALUE_B, STATIC_OFFSET_VALUE_C,
1356 STATIC_OFFSET_VALUE_D};
1357
1358 viewOffset.push_back(
1359 setViewOffset ? (staticOffsetValues[bufferNdx % getInterfaceNumResources(shaderInterface)]) : (0u));
1360 }
1361
1362 return viewOffset;
1363 }
1364
getDynamicOffsets(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool dynamicOffsetNonZero)1365 std::vector<uint32_t> BufferRenderInstance::getDynamicOffsets(DescriptorSetCount descriptorSetCount,
1366 ShaderInputInterface shaderInterface,
1367 bool dynamicOffsetNonZero)
1368 {
1369 const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1370 std::vector<uint32_t> dynamicOffset;
1371
1372 for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1373 {
1374 const uint32_t dynamicOffsetValues[] = {DYNAMIC_OFFSET_VALUE_A, DYNAMIC_OFFSET_VALUE_B, DYNAMIC_OFFSET_VALUE_C,
1375 DYNAMIC_OFFSET_VALUE_D};
1376
1377 dynamicOffset.push_back(
1378 dynamicOffsetNonZero ? (dynamicOffsetValues[bufferNdx % getInterfaceNumResources(shaderInterface)]) : (0u));
1379 }
1380
1381 return dynamicOffset;
1382 }
1383
createSourceBuffers(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<uint32_t> & viewOffset,const std::vector<uint32_t> & dynamicOffset,std::vector<AllocationSp> & bufferMemory)1384 std::vector<BufferHandleSp> BufferRenderInstance::createSourceBuffers(
1385 const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
1386 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
1387 const std::vector<uint32_t> &viewOffset, const std::vector<uint32_t> &dynamicOffset,
1388 std::vector<AllocationSp> &bufferMemory)
1389 {
1390 const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1391 std::vector<uint32_t> effectiveOffset;
1392 std::vector<uint32_t> bufferSize;
1393 std::vector<BufferHandleSp> sourceBuffers;
1394
1395 for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1396 {
1397 const uint32_t bufferSizeValues[] = {BUFFER_SIZE_A, BUFFER_SIZE_B, BUFFER_SIZE_C, BUFFER_SIZE_D};
1398
1399 effectiveOffset.push_back(isDynamicDescriptorType(descriptorType) ?
1400 (viewOffset[bufferNdx] + dynamicOffset[bufferNdx]) :
1401 (viewOffset[bufferNdx]));
1402 bufferSize.push_back(bufferSizeValues[bufferNdx % getInterfaceNumResources(shaderInterface)]);
1403 }
1404
1405 // Create source buffers
1406 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1407 {
1408 for (uint32_t bufferNdx = 0; bufferNdx < getInterfaceNumResources(shaderInterface); bufferNdx++)
1409 {
1410 de::MovePtr<vk::Allocation> memory;
1411 vk::Move<vk::VkBuffer> buffer =
1412 createSourceBuffer(vki, device, allocator, descriptorType, setNdx, effectiveOffset[bufferNdx],
1413 bufferSize[bufferNdx], &memory);
1414
1415 bufferMemory.push_back(AllocationSp(memory.release()));
1416 sourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
1417 }
1418 }
1419
1420 return sourceBuffers;
1421 }
1422
createSourceBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,uint32_t setNdx,uint32_t offset,uint32_t bufferSize,de::MovePtr<vk::Allocation> * outMemory)1423 vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1424 vk::Allocator &allocator,
1425 vk::VkDescriptorType descriptorType, uint32_t setNdx,
1426 uint32_t offset, uint32_t bufferSize,
1427 de::MovePtr<vk::Allocation> *outMemory)
1428 {
1429 static const float s_colors[] = {
1430 0.0f, 1.0f, 0.0f, 1.0f, // green
1431 1.0f, 1.0f, 0.0f, 1.0f, // yellow
1432 0.0f, 0.0f, 1.0f, 1.0f, // blue
1433 1.0f, 0.0f, 0.0f, 1.0f // red
1434 };
1435 DE_STATIC_ASSERT(sizeof(s_colors) / 2 == BUFFER_DATA_SIZE);
1436 DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize);
1437 DE_ASSERT(offset % sizeof(float) == 0);
1438 DE_ASSERT(bufferSize % sizeof(float) == 0);
1439
1440 const bool isUniformBuffer = isUniformDescriptorType(descriptorType);
1441 const vk::VkBufferUsageFlags usageFlags =
1442 (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1443 const float preGuardValue = 0.5f;
1444 const float postGuardValue = 0.75f;
1445 const vk::VkBufferCreateInfo bufferCreateInfo = {
1446 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1447 nullptr,
1448 0u, // flags
1449 bufferSize, // size
1450 usageFlags, // usage
1451 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1452 0u, // queueFamilyCount
1453 nullptr, // pQueueFamilyIndices
1454 };
1455 vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &bufferCreateInfo));
1456 de::MovePtr<vk::Allocation> bufferMemory =
1457 allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible);
1458 void *const mapPtr = bufferMemory->getHostPtr();
1459
1460 // guard with interesting values
1461 for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float))
1462 deMemcpy((uint8_t *)mapPtr + preGuardOffset, &preGuardValue, sizeof(float));
1463
1464 deMemcpy((uint8_t *)mapPtr + offset, &s_colors[8 * (setNdx % 2)], sizeof(s_colors) / 2);
1465 for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors) / 2;
1466 postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float))
1467 deMemcpy((uint8_t *)mapPtr + postGuardOffset, &postGuardValue, sizeof(float));
1468 deMemset((uint8_t *)mapPtr + offset + sizeof(s_colors) / 2, 0x5A,
1469 (size_t)bufferSize - (size_t)offset -
1470 sizeof(s_colors) / 2); // fill with interesting pattern that produces valid floats
1471
1472 flushAlloc(vki, device, *bufferMemory);
1473
1474 // Flushed host-visible memory is automatically made available to the GPU, no barrier is needed.
1475
1476 *outMemory = bufferMemory;
1477 return buffer;
1478 }
1479
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)1480 vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
1481 vk::VkDevice device,
1482 vk::VkDescriptorType descriptorType,
1483 DescriptorSetCount descriptorSetCount,
1484 ShaderInputInterface shaderInterface)
1485 {
1486 return vk::DescriptorPoolBuilder()
1487 .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
1488 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1489 getDescriptorSetCount(descriptorSetCount));
1490 }
1491
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)1492 std::vector<DescriptorSetLayoutHandleSp> BufferRenderInstance::createDescriptorSetLayouts(
1493 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
1494 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
1495 DescriptorUpdateMethod updateMethod)
1496 {
1497 #ifdef CTS_USES_VULKANSC
1498 DE_UNREF(updateMethod);
1499 #endif
1500 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
1501
1502 #ifndef CTS_USES_VULKANSC
1503 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
1504 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1505 {
1506 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
1507 }
1508 #endif
1509
1510 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
1511
1512 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1513 {
1514 vk::DescriptorSetLayoutBuilder builder;
1515 switch (shaderInterface)
1516 {
1517 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1518 builder.addSingleBinding(descriptorType, stageFlags);
1519 break;
1520
1521 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1522 builder.addSingleBinding(descriptorType, stageFlags);
1523 builder.addSingleBinding(descriptorType, stageFlags);
1524 break;
1525
1526 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1527 builder.addSingleIndexedBinding(descriptorType, stageFlags, 0u);
1528 builder.addSingleIndexedBinding(descriptorType, stageFlags, 2u);
1529 break;
1530
1531 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1532 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
1533 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
1534 break;
1535
1536 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1537 builder.addArrayBinding(descriptorType, 2u, stageFlags);
1538 break;
1539
1540 default:
1541 DE_FATAL("Impossible");
1542 }
1543
1544 vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
1545 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
1546
1547 // Add an empty descriptor set layout between sets 0 and 2
1548 if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
1549 {
1550 vk::DescriptorSetLayoutBuilder emptyBuilder;
1551 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
1552 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
1553 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
1554 }
1555 }
1556 return descriptorSetLayouts;
1557 }
1558
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)1559 vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout(
1560 const vk::DeviceInterface &vki, vk::VkDevice device,
1561 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
1562 {
1563 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
1564 for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
1565 layoutHandles.push_back(**descriptorSetLayout[setNdx]);
1566
1567 const vk::VkPipelineLayoutCreateInfo createInfo = {
1568 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1569 nullptr,
1570 (vk::VkPipelineLayoutCreateFlags)0,
1571 (uint32_t)layoutHandles.size(), // descriptorSetCount
1572 &layoutHandles.front(), // pSetLayouts
1573 0u, // pushConstantRangeCount
1574 nullptr, // pPushConstantRanges
1575 };
1576 return vk::createPipelineLayout(vki, device, &createInfo);
1577 }
1578
createDescriptorSets(const vk::DeviceInterface & vki,DescriptorUpdateMethod updateMethod,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayouts,vk::VkDescriptorPool descriptorPool,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<BufferHandleSp> & buffers,const std::vector<uint32_t> & offsets,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & updateRegistry,vk::VkPipelineLayout pipelineLayout)1579 std::vector<DescriptorSetHandleSp> BufferRenderInstance::createDescriptorSets(
1580 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
1581 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool descriptorPool,
1582 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
1583 const std::vector<BufferHandleSp> &buffers, const std::vector<uint32_t> &offsets,
1584 vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
1585 #ifndef CTS_USES_VULKANSC
1586 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
1587 #endif
1588 vk::VkPipelineLayout pipelineLayout)
1589 {
1590 #ifdef CTS_USES_VULKANSC
1591 DE_UNREF(pipelineLayout);
1592 #endif
1593 std::vector<DescriptorSetHandleSp> descriptorSets;
1594
1595 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1596 {
1597 vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
1598 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
1599 descriptorPool, 1u, &layout};
1600
1601 vk::VkBuffer bufferA = **buffers[(setNdx * getInterfaceNumResources(shaderInterface)) % buffers.size()];
1602 vk::VkBuffer bufferB = **buffers[(setNdx * getInterfaceNumResources(shaderInterface) + 1) % buffers.size()];
1603 uint32_t offsetA = offsets[(setNdx * getInterfaceNumResources(shaderInterface)) % offsets.size()];
1604 uint32_t offsetB = offsets[(setNdx * getInterfaceNumResources(shaderInterface) + 1) % offsets.size()];
1605
1606 vk::Move<vk::VkDescriptorSet> descriptorSet;
1607
1608 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
1609 updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1610 {
1611 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
1612 }
1613 else
1614 {
1615 descriptorSet = vk::Move<vk::VkDescriptorSet>();
1616 }
1617
1618 #ifndef CTS_USES_VULKANSC
1619 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
1620 {
1621 writeDescriptorSetWithTemplate(vki, device, layout, setNdx, descriptorPool, descriptorType, shaderInterface,
1622 bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplates,
1623 updateRegistry);
1624 }
1625 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1626 {
1627 writeDescriptorSetWithTemplate(vki, device, layout, setNdx, descriptorPool, descriptorType, shaderInterface,
1628 bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplates,
1629 updateRegistry, true, pipelineLayout);
1630 }
1631 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1632 {
1633 writeDescriptorSet(vki, device, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB,
1634 *descriptorSet, updateBuilder, descriptorsPerSet, updateMethod);
1635 }
1636 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
1637 #endif
1638 {
1639 writeDescriptorSet(vki, device, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB,
1640 *descriptorSet, updateBuilder, descriptorsPerSet);
1641 }
1642
1643 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
1644 }
1645 return descriptorSets;
1646 }
1647
writeDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkBuffer bufferA,const uint32_t offsetA,vk::VkBuffer bufferB,const uint32_t offsetB,vk::VkDescriptorSet descriptorSet,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)1648 void BufferRenderInstance::writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
1649 vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1650 vk::VkBuffer bufferA, const uint32_t offsetA, vk::VkBuffer bufferB,
1651 const uint32_t offsetB, vk::VkDescriptorSet descriptorSet,
1652 vk::DescriptorSetUpdateBuilder &updateBuilder,
1653 std::vector<uint32_t> &descriptorsPerSet,
1654 DescriptorUpdateMethod updateMethod)
1655 {
1656 const vk::VkDescriptorBufferInfo bufferInfos[2] = {
1657 vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1658 vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1659 };
1660 uint32_t numDescriptors = 0u;
1661
1662 switch (shaderInterface)
1663 {
1664 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1665 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1666 &bufferInfos[0]);
1667 numDescriptors++;
1668 break;
1669
1670 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1671 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1672 &bufferInfos[0]);
1673 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
1674 &bufferInfos[1]);
1675 numDescriptors += 2;
1676 break;
1677
1678 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1679 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1680 &bufferInfos[0]);
1681 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
1682 &bufferInfos[1]);
1683 numDescriptors += 2;
1684 break;
1685
1686 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1687 updateBuilder.writeSingle(descriptorSet,
1688 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
1689 descriptorType, &bufferInfos[0]);
1690 updateBuilder.writeSingle(descriptorSet,
1691 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
1692 descriptorType, &bufferInfos[1]);
1693 numDescriptors += 2;
1694 break;
1695
1696 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1697 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1698 2u, bufferInfos);
1699 numDescriptors++;
1700 break;
1701
1702 default:
1703 DE_FATAL("Impossible");
1704 }
1705
1706 descriptorsPerSet.push_back(numDescriptors);
1707
1708 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
1709 {
1710 updateBuilder.update(vki, device);
1711 updateBuilder.clear();
1712 }
1713 }
1714
1715 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkDescriptorPool descriptorPool,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkBuffer bufferA,const uint32_t offsetA,vk::VkBuffer bufferB,const uint32_t offsetB,vk::VkDescriptorSet descriptorSet,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)1716 void BufferRenderInstance::writeDescriptorSetWithTemplate(
1717 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorSetLayout layout, uint32_t setNdx,
1718 vk::VkDescriptorPool descriptorPool, vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1719 vk::VkBuffer bufferA, const uint32_t offsetA, vk::VkBuffer bufferB, const uint32_t offsetB,
1720 vk::VkDescriptorSet descriptorSet, std::vector<UpdateTemplateHandleSp> &updateTemplates,
1721 std::vector<RawUpdateRegistry> ®istry, bool withPush, vk::VkPipelineLayout pipelineLayout)
1722 {
1723 DE_UNREF(descriptorPool);
1724 const vk::VkDescriptorBufferInfo bufferInfos[2] = {
1725 vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1726 vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1727 };
1728 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
1729 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
1730 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
1731 nullptr,
1732 0,
1733 0, // descriptorUpdateEntryCount
1734 nullptr, // pDescriptorUpdateEntries
1735 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
1736 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
1737 layout,
1738 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1739 pipelineLayout,
1740 setNdx};
1741
1742 RawUpdateRegistry updateRegistry;
1743
1744 updateRegistry.addWriteObject(bufferInfos[0]);
1745 updateRegistry.addWriteObject(bufferInfos[1]);
1746
1747 switch (shaderInterface)
1748 {
1749 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1750 updateEntries.push_back(
1751 createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1752 break;
1753
1754 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1755 updateEntries.push_back(
1756 createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1757 updateEntries.push_back(
1758 createTemplateBinding(1u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
1759 break;
1760
1761 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1762 updateEntries.push_back(
1763 createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1764 updateEntries.push_back(
1765 createTemplateBinding(2u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
1766 break;
1767
1768 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1769 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
1770 updateRegistry.getWriteObjectOffset(0), 0));
1771 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
1772 updateRegistry.getWriteObjectOffset(1), 0));
1773 break;
1774
1775 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1776 updateEntries.push_back(createTemplateBinding(0u, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
1777 sizeof(bufferInfos[0])));
1778 break;
1779
1780 default:
1781 DE_FATAL("Impossible");
1782 }
1783
1784 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
1785 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
1786
1787 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
1788 vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
1789 updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
1790 registry.push_back(updateRegistry);
1791
1792 if (!withPush)
1793 {
1794 vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
1795 registry.back().getRawPointer());
1796 }
1797 }
1798 #endif
1799
logTestPlan(void) const1800 void BufferRenderInstance::logTestPlan(void) const
1801 {
1802 std::ostringstream msg;
1803
1804 msg << "Rendering 2x2 yellow-green grid.\n"
1805 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
1806 "Multiple descriptor sets. ")
1807 << "Each descriptor set contains "
1808 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
1809 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
1810 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
1811 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
1812 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
1813 nullptr)
1814 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
1815 << "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
1816
1817 if (isDynamicDescriptorType(m_descriptorType))
1818 {
1819 if (m_setDynamicOffset)
1820 {
1821 msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
1822 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
1823 }
1824 else
1825 {
1826 msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
1827 }
1828 }
1829
1830 if (m_stageFlags == 0u)
1831 {
1832 msg << "Descriptors are not accessed in any shader stage.\n";
1833 }
1834 else
1835 {
1836 msg << "Descriptors are accessed in {"
1837 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
1838 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
1839 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
1840 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
1841 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.\n";
1842 }
1843
1844 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
1845 }
1846
getPipelineLayout(void) const1847 vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout(void) const
1848 {
1849 return *m_pipelineLayout;
1850 }
1851
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const1852 void BufferRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
1853 {
1854 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
1855 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1856 {
1857 std::vector<vk::VkDescriptorSet> sets;
1858 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1859 sets.push_back(**m_descriptorSets[setNdx]);
1860
1861 switch (m_descriptorSetCount)
1862 {
1863 case DESCRIPTOR_SET_COUNT_SINGLE:
1864 case DESCRIPTOR_SET_COUNT_MULTIPLE:
1865 {
1866 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1867 const uint32_t numOffsets = (!m_setDynamicOffset) ? (0u) : ((uint32_t)m_dynamicOffset.size());
1868 const uint32_t *const dynamicOffsetPtr = (!m_setDynamicOffset) ? (nullptr) : (&m_dynamicOffset.front());
1869
1870 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1871 getPipelineLayout(), 0, (int)sets.size(), &sets.front(), numOffsets, dynamicOffsetPtr,
1872 m_bind2);
1873 break;
1874 }
1875 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1876 {
1877 uint32_t dynamicOffsetNdx = 0u;
1878
1879 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1880 {
1881 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1882 const uint32_t numOffsets =
1883 (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
1884 const uint32_t *const dynamicOffsetPtr =
1885 (!m_setDynamicOffset) ? (nullptr) : (&m_dynamicOffset[dynamicOffsetNdx]);
1886 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
1887
1888 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1889 getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], numOffsets,
1890 dynamicOffsetPtr, m_bind2);
1891
1892 dynamicOffsetNdx += getInterfaceNumResources(m_shaderInterface);
1893 }
1894 break;
1895 }
1896 default:
1897 DE_FATAL("Impossible");
1898 }
1899 }
1900 #ifndef CTS_USES_VULKANSC
1901 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1902 {
1903 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1904 m_vki.cmdPushDescriptorSetWithTemplate(cmd, **m_updateTemplates[setNdx], getPipelineLayout(), setNdx,
1905 (const void *)m_updateRegistry[setNdx].getRawPointer());
1906 }
1907 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1908 {
1909 uint32_t descriptorNdx = 0u;
1910 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1911 {
1912 const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
1913 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, setNdx,
1914 descriptorNdx, numDescriptors);
1915 descriptorNdx += numDescriptors;
1916 }
1917 }
1918 #endif
1919
1920 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
1921 }
1922
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const1923 tcu::TestStatus BufferRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
1924 {
1925 const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
1926 const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
1927 const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
1928 tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
1929
1930 tcu::Vec4 sample0 = tcu::Vec4(0.0f);
1931 tcu::Vec4 sample1 = tcu::Vec4(0.0f);
1932
1933 if (m_stageFlags)
1934 {
1935 const tcu::Vec4 colors[] = {
1936 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), // green
1937 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), // yellow
1938 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), // blue
1939 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), // red
1940 };
1941
1942 for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
1943 {
1944 sample0 += colors[2 * (setNdx % 2)];
1945 sample1 += colors[2 * (setNdx % 2) + 1];
1946 }
1947
1948 if (numDescriptorSets > 1)
1949 {
1950 sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
1951 sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
1952 }
1953 }
1954 else
1955 {
1956 sample0 = green;
1957 sample1 = yellow;
1958 }
1959
1960 drawQuadrantReferenceResult(reference.getAccess(), sample1, sample0, sample0, sample1);
1961
1962 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
1963 result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
1964 return tcu::TestStatus::fail("Image verification failed");
1965 else
1966 return tcu::TestStatus::pass("Pass");
1967 }
1968
1969 class ComputeInstanceResultBuffer
1970 {
1971 public:
1972 enum
1973 {
1974 DATA_SIZE = sizeof(tcu::Vec4[4])
1975 };
1976
1977 ComputeInstanceResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator);
1978
1979 void readResultContentsTo(tcu::Vec4 (*results)[4]) const;
1980
getBuffer(void) const1981 inline vk::VkBuffer getBuffer(void) const
1982 {
1983 return *m_buffer;
1984 }
getResultReadBarrier(void) const1985 inline const vk::VkBufferMemoryBarrier *getResultReadBarrier(void) const
1986 {
1987 return &m_bufferBarrier;
1988 }
1989
1990 private:
1991 static vk::Move<vk::VkBuffer> createResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1992 vk::Allocator &allocator,
1993 de::MovePtr<vk::Allocation> *outAllocation);
1994
1995 static vk::VkBufferMemoryBarrier createResultBufferBarrier(vk::VkBuffer buffer);
1996
1997 const vk::DeviceInterface &m_vki;
1998 const vk::VkDevice m_device;
1999
2000 de::MovePtr<vk::Allocation> m_bufferMem;
2001 const vk::Unique<vk::VkBuffer> m_buffer;
2002 const vk::VkBufferMemoryBarrier m_bufferBarrier;
2003 };
2004
ComputeInstanceResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator)2005 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
2006 vk::Allocator &allocator)
2007 : m_vki(vki)
2008 , m_device(device)
2009 , m_bufferMem(nullptr)
2010 , m_buffer(createResultBuffer(m_vki, m_device, allocator, &m_bufferMem))
2011 , m_bufferBarrier(createResultBufferBarrier(*m_buffer))
2012 {
2013 }
2014
readResultContentsTo(tcu::Vec4 (* results)[4]) const2015 void ComputeInstanceResultBuffer::readResultContentsTo(tcu::Vec4 (*results)[4]) const
2016 {
2017 invalidateAlloc(m_vki, m_device, *m_bufferMem);
2018 deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
2019 }
2020
createResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,de::MovePtr<vk::Allocation> * outAllocation)2021 vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer(const vk::DeviceInterface &vki,
2022 vk::VkDevice device, vk::Allocator &allocator,
2023 de::MovePtr<vk::Allocation> *outAllocation)
2024 {
2025 const vk::VkBufferCreateInfo createInfo = {
2026 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
2027 nullptr,
2028 0u, // flags
2029 (vk::VkDeviceSize)DATA_SIZE, // size
2030 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage
2031 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
2032 0u, // queueFamilyCount
2033 nullptr, // pQueueFamilyIndices
2034 };
2035 vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &createInfo));
2036 de::MovePtr<vk::Allocation> allocation(
2037 allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
2038 const float clearValue = -1.0f;
2039 void *mapPtr = allocation->getHostPtr();
2040
2041 for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
2042 deMemcpy(((uint8_t *)mapPtr) + offset, &clearValue, sizeof(float));
2043
2044 flushAlloc(vki, device, *allocation);
2045
2046 *outAllocation = allocation;
2047 return buffer;
2048 }
2049
createResultBufferBarrier(vk::VkBuffer buffer)2050 vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier(vk::VkBuffer buffer)
2051 {
2052 const vk::VkBufferMemoryBarrier bufferBarrier = {
2053 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2054 nullptr,
2055 vk::VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask
2056 vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask
2057 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
2058 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
2059 buffer, // buffer
2060 (vk::VkDeviceSize)0u, // offset
2061 DATA_SIZE, // size
2062 };
2063 return bufferBarrier;
2064 }
2065
2066 class ComputePipeline
2067 {
2068 public:
2069 ComputePipeline(const vk::DeviceInterface &vki, vk::VkDevice device, const vk::BinaryCollection &programCollection,
2070 uint32_t numDescriptorSets, const vk::VkDescriptorSetLayout *descriptorSetLayouts);
2071
getPipeline(void) const2072 inline vk::VkPipeline getPipeline(void) const
2073 {
2074 return *m_pipeline;
2075 }
getPipelineLayout(void) const2076 inline vk::VkPipelineLayout getPipelineLayout(void) const
2077 {
2078 return *m_pipelineLayout;
2079 }
2080
2081 private:
2082 static vk::Move<vk::VkPipelineLayout> createPipelineLayout(const vk::DeviceInterface &vki, vk::VkDevice device,
2083 uint32_t numDescriptorSets,
2084 const vk::VkDescriptorSetLayout *descriptorSetLayouts);
2085
2086 static vk::Move<vk::VkPipeline> createPipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2087 const vk::BinaryCollection &programCollection,
2088 vk::VkPipelineLayout layout);
2089
2090 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
2091 const vk::Unique<vk::VkPipeline> m_pipeline;
2092 };
2093
ComputePipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,uint32_t numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)2094 ComputePipeline::ComputePipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2095 const vk::BinaryCollection &programCollection, uint32_t numDescriptorSets,
2096 const vk::VkDescriptorSetLayout *descriptorSetLayouts)
2097 : m_pipelineLayout(createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts))
2098 , m_pipeline(createPipeline(vki, device, programCollection, *m_pipelineLayout))
2099 {
2100 }
2101
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)2102 vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout(
2103 const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t numDescriptorSets,
2104 const vk::VkDescriptorSetLayout *descriptorSetLayouts)
2105 {
2106 const vk::VkPipelineLayoutCreateInfo createInfo = {
2107 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2108 nullptr,
2109 (vk::VkPipelineLayoutCreateFlags)0,
2110 numDescriptorSets, // descriptorSetCount
2111 descriptorSetLayouts, // pSetLayouts
2112 0u, // pushConstantRangeCount
2113 nullptr, // pPushConstantRanges
2114 };
2115 return vk::createPipelineLayout(vki, device, &createInfo);
2116 }
2117
createPipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,vk::VkPipelineLayout layout)2118 vk::Move<vk::VkPipeline> ComputePipeline::createPipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2119 const vk::BinaryCollection &programCollection,
2120 vk::VkPipelineLayout layout)
2121 {
2122 const vk::Unique<vk::VkShaderModule> computeModule(
2123 vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u));
2124 const vk::VkPipelineShaderStageCreateInfo cs = {
2125 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2126 nullptr,
2127 (vk::VkPipelineShaderStageCreateFlags)0,
2128 vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage
2129 *computeModule, // shader
2130 "main",
2131 nullptr, // pSpecializationInfo
2132 };
2133 const vk::VkComputePipelineCreateInfo createInfo = {
2134 vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2135 nullptr,
2136 0u, // flags
2137 cs, // cs
2138 layout, // layout
2139 VK_NULL_HANDLE, // basePipelineHandle
2140 0u, // basePipelineIndex
2141 };
2142 return createComputePipeline(vki, device, VK_NULL_HANDLE, &createInfo);
2143 }
2144
2145 class ComputeCommand
2146 {
2147 public:
2148 ComputeCommand(const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkPipeline pipeline,
2149 vk::VkPipelineLayout pipelineLayout, const tcu::UVec3 &numWorkGroups,
2150 ShaderInputInterface shaderInterface, DescriptorSetCount descriptorSetCount,
2151 const vk::VkDescriptorSet *descriptorSets, int numDynamicOffsets, const uint32_t *dynamicOffsets,
2152 int numPreBarriers, const vk::VkBufferMemoryBarrier *preBarriers, int numPostBarriers,
2153 const vk::VkBufferMemoryBarrier *postBarriers, const bool bind2);
2154
2155 void submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue
2156 #ifndef CTS_USES_VULKANSC
2157 ,
2158 std::vector<UpdateTemplateHandleSp> *updateTemplates = nullptr,
2159 std::vector<RawUpdateRegistry> *updateRegistry = nullptr
2160 #endif
2161 ) const;
2162 #ifndef CTS_USES_VULKANSC
2163 void submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue, vk::DescriptorSetUpdateBuilder &updateBuilder,
2164 std::vector<uint32_t> &descriptorsPerSet) const;
2165 #endif
2166
2167 private:
2168 const bool m_bind2;
2169 const vk::DeviceInterface &m_vki;
2170 const vk::VkDevice m_device;
2171 const vk::VkPipeline m_pipeline;
2172 const vk::VkPipelineLayout m_pipelineLayout;
2173 const tcu::UVec3 m_numWorkGroups;
2174 const ShaderInputInterface m_shaderInterface;
2175 const DescriptorSetCount m_descriptorSetCount;
2176 const vk::VkDescriptorSet *const m_descriptorSets;
2177 const int m_numDynamicOffsets;
2178 const uint32_t *const m_dynamicOffsets;
2179 const int m_numPreBarriers;
2180 const vk::VkBufferMemoryBarrier *const m_preBarriers;
2181 const int m_numPostBarriers;
2182 const vk::VkBufferMemoryBarrier *const m_postBarriers;
2183 };
2184
ComputeCommand(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkPipeline pipeline,vk::VkPipelineLayout pipelineLayout,const tcu::UVec3 & numWorkGroups,ShaderInputInterface shaderInterface,DescriptorSetCount descriptorSetCount,const vk::VkDescriptorSet * descriptorSets,int numDynamicOffsets,const uint32_t * dynamicOffsets,int numPreBarriers,const vk::VkBufferMemoryBarrier * preBarriers,int numPostBarriers,const vk::VkBufferMemoryBarrier * postBarriers,const bool bind2)2185 ComputeCommand::ComputeCommand(const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkPipeline pipeline,
2186 vk::VkPipelineLayout pipelineLayout, const tcu::UVec3 &numWorkGroups,
2187 ShaderInputInterface shaderInterface, DescriptorSetCount descriptorSetCount,
2188 const vk::VkDescriptorSet *descriptorSets, int numDynamicOffsets,
2189 const uint32_t *dynamicOffsets, int numPreBarriers,
2190 const vk::VkBufferMemoryBarrier *preBarriers, int numPostBarriers,
2191 const vk::VkBufferMemoryBarrier *postBarriers, const bool bind2)
2192 : m_bind2(bind2)
2193 , m_vki(vki)
2194 , m_device(device)
2195 , m_pipeline(pipeline)
2196 , m_pipelineLayout(pipelineLayout)
2197 , m_numWorkGroups(numWorkGroups)
2198 , m_shaderInterface(shaderInterface)
2199 , m_descriptorSetCount(descriptorSetCount)
2200 , m_descriptorSets(descriptorSets)
2201 , m_numDynamicOffsets(numDynamicOffsets)
2202 , m_dynamicOffsets(dynamicOffsets)
2203 , m_numPreBarriers(numPreBarriers)
2204 , m_preBarriers(preBarriers)
2205 , m_numPostBarriers(numPostBarriers)
2206 , m_postBarriers(postBarriers)
2207 {
2208 }
2209
submitAndWait(uint32_t queueFamilyIndex,vk::VkQueue queue,std::vector<UpdateTemplateHandleSp> * updateTemplates,std::vector<RawUpdateRegistry> * updateRegistry) const2210 void ComputeCommand::submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue
2211 #ifndef CTS_USES_VULKANSC
2212 ,
2213 std::vector<UpdateTemplateHandleSp> *updateTemplates,
2214 std::vector<RawUpdateRegistry> *updateRegistry
2215 #endif
2216 ) const
2217 {
2218 const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = {
2219 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr,
2220 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
2221 queueFamilyIndex, // queueFamilyIndex
2222 };
2223 const vk::Unique<vk::VkCommandPool> cmdPool(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
2224
2225 const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo = {
2226 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
2227 nullptr,
2228 *cmdPool, // cmdPool
2229 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
2230 1u, // count
2231 };
2232
2233 const vk::Unique<vk::VkCommandBuffer> cmd(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
2234
2235 beginCommandBuffer(m_vki, *cmd);
2236
2237 m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
2238
2239 // normal update
2240 #ifndef CTS_USES_VULKANSC
2241 if (updateTemplates == nullptr)
2242 #endif
2243 {
2244 switch (m_descriptorSetCount)
2245 {
2246 case DESCRIPTOR_SET_COUNT_SINGLE:
2247 case DESCRIPTOR_SET_COUNT_MULTIPLE:
2248 {
2249 bindDescriptorSets(m_vki, *cmd, vk::VK_SHADER_STAGE_COMPUTE_BIT, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2250 vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0,
2251 getDescriptorSetCount(m_descriptorSetCount), m_descriptorSets, m_numDynamicOffsets,
2252 m_dynamicOffsets, m_bind2);
2253 break;
2254 }
2255 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
2256 {
2257 uint32_t dynamicOffsetNdx = 0u;
2258
2259 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2260 {
2261 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
2262 const uint32_t numOffsets =
2263 (!m_numDynamicOffsets) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
2264 const uint32_t *const dynamicOffsetPtr =
2265 (!m_numDynamicOffsets) ? (nullptr) : (&m_dynamicOffsets[dynamicOffsetNdx]);
2266 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
2267
2268 bindDescriptorSets(m_vki, *cmd, vk::VK_SHADER_STAGE_COMPUTE_BIT, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2269 vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, descriptorSetNdx, 1u,
2270 &m_descriptorSets[setNdx], numOffsets, dynamicOffsetPtr, m_bind2);
2271
2272 dynamicOffsetNdx += getInterfaceNumResources(m_shaderInterface);
2273 }
2274 break;
2275 }
2276 default:
2277 DE_FATAL("Impossible");
2278 }
2279 }
2280 #ifndef CTS_USES_VULKANSC
2281 // update with push template
2282 else
2283 {
2284 for (uint32_t setNdx = 0; setNdx < (uint32_t)(*updateTemplates).size(); setNdx++)
2285 m_vki.cmdPushDescriptorSetWithTemplate(*cmd, **(*updateTemplates)[setNdx], m_pipelineLayout,
2286 getDescriptorSetNdx(m_descriptorSetCount, setNdx),
2287 (const void *)(*updateRegistry)[setNdx].getRawPointer());
2288 }
2289 #endif
2290
2291 if (m_numPreBarriers)
2292 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2293 (vk::VkDependencyFlags)0, 0, nullptr, m_numPreBarriers, m_preBarriers, 0, nullptr);
2294
2295 m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
2296 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
2297 (vk::VkDependencyFlags)0, 0, nullptr, m_numPostBarriers, m_postBarriers, 0, nullptr);
2298 endCommandBuffer(m_vki, *cmd);
2299
2300 submitCommandsAndWait(m_vki, m_device, queue, cmd.get());
2301 }
2302
2303 #ifndef CTS_USES_VULKANSC
2304 //cmdPushDescriptorSet variant
submitAndWait(uint32_t queueFamilyIndex,vk::VkQueue queue,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet) const2305 void ComputeCommand::submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue,
2306 vk::DescriptorSetUpdateBuilder &updateBuilder,
2307 std::vector<uint32_t> &descriptorsPerSet) const
2308 {
2309 const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = {
2310 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr,
2311 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
2312 queueFamilyIndex, // queueFamilyIndex
2313 };
2314 const vk::Unique<vk::VkCommandPool> cmdPool(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
2315
2316 const vk::Unique<vk::VkCommandBuffer> cmd(
2317 vk::allocateCommandBuffer(m_vki, m_device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2318
2319 beginCommandBuffer(m_vki, *cmd);
2320
2321 m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
2322
2323 {
2324 uint32_t descriptorNdx = 0u;
2325 for (uint32_t setNdx = 0; setNdx < (uint32_t)descriptorsPerSet.size(); setNdx++)
2326 {
2327 const uint32_t numDescriptors = descriptorsPerSet[setNdx];
2328 updateBuilder.updateWithPush(m_vki, *cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout,
2329 getDescriptorSetNdx(m_descriptorSetCount, setNdx), descriptorNdx,
2330 numDescriptors);
2331 descriptorNdx += numDescriptors;
2332 }
2333 }
2334
2335 if (m_numPreBarriers)
2336 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2337 (vk::VkDependencyFlags)0, 0, nullptr, m_numPreBarriers, m_preBarriers, 0, nullptr);
2338
2339 m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
2340 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
2341 (vk::VkDependencyFlags)0, 0, nullptr, m_numPostBarriers, m_postBarriers, 0, nullptr);
2342 endCommandBuffer(m_vki, *cmd);
2343
2344 submitCommandsAndWait(m_vki, m_device, queue, cmd.get());
2345 }
2346 #endif
2347
2348 class BufferComputeInstance : public vkt::TestInstance
2349 {
2350 public:
2351 BufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
2352 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, bool viewOffset,
2353 bool dynamicOffset, bool dynamicOffsetNonZero, bool bind2);
2354
2355 private:
2356 vk::Move<vk::VkBuffer> createColorDataBuffer(uint32_t offset, uint32_t bufferSize, const tcu::Vec4 &value1,
2357 const tcu::Vec4 &value2, de::MovePtr<vk::Allocation> *outAllocation);
2358 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
2359 vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
2360 vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
2361 uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA,
2362 vk::VkBuffer viewB, uint32_t offsetB, vk::VkBuffer resBuf);
2363 void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA,
2364 vk::VkBuffer viewB, uint32_t offsetB, vk::VkBuffer resBuf);
2365 #ifndef CTS_USES_VULKANSC
2366 void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
2367 uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA, vk::VkBuffer viewB,
2368 uint32_t offsetB, vk::VkBuffer resBuf, bool withPush = false,
2369 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
2370 #endif
2371
2372 tcu::TestStatus iterate(void);
2373 void logTestPlan(void) const;
2374 tcu::TestStatus testResourceAccess(void);
2375
2376 enum
2377 {
2378 STATIC_OFFSET_VALUE_A = 256,
2379 DYNAMIC_OFFSET_VALUE_A = 512,
2380 STATIC_OFFSET_VALUE_B = 1024,
2381 DYNAMIC_OFFSET_VALUE_B = 768,
2382 };
2383
2384 const DescriptorUpdateMethod m_updateMethod;
2385 const vk::VkDescriptorType m_descriptorType;
2386 const DescriptorSetCount m_descriptorSetCount;
2387 const ShaderInputInterface m_shaderInterface;
2388 const bool m_setViewOffset;
2389 const bool m_setDynamicOffset;
2390 const bool m_dynamicOffsetNonZero;
2391 const bool m_bind2;
2392
2393 #ifndef CTS_USES_VULKANSC
2394 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
2395 #endif
2396 const vk::DeviceInterface &m_vki;
2397 const vk::VkDevice m_device;
2398 const vk::VkQueue m_queue;
2399 const uint32_t m_queueFamilyIndex;
2400 vk::Allocator &m_allocator;
2401
2402 const ComputeInstanceResultBuffer m_result;
2403
2404 #ifndef CTS_USES_VULKANSC
2405 std::vector<RawUpdateRegistry> m_updateRegistry;
2406 #endif
2407 vk::DescriptorSetUpdateBuilder m_updateBuilder;
2408 std::vector<uint32_t> m_descriptorsPerSet;
2409 };
2410
BufferComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero,bool bind2)2411 BufferComputeInstance::BufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
2412 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
2413 ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
2414 bool dynamicOffsetNonZero, bool bind2)
2415 : vkt::TestInstance(context)
2416 , m_updateMethod(updateMethod)
2417 , m_descriptorType(descriptorType)
2418 , m_descriptorSetCount(descriptorSetCount)
2419 , m_shaderInterface(shaderInterface)
2420 , m_setViewOffset(viewOffset)
2421 , m_setDynamicOffset(dynamicOffset)
2422 , m_dynamicOffsetNonZero(dynamicOffsetNonZero)
2423 , m_bind2(bind2)
2424 #ifndef CTS_USES_VULKANSC
2425 , m_updateTemplates()
2426 #endif
2427 , m_vki(context.getDeviceInterface())
2428 , m_device(context.getDevice())
2429 , m_queue(context.getUniversalQueue())
2430 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
2431 , m_allocator(context.getDefaultAllocator())
2432 , m_result(m_vki, m_device, m_allocator)
2433 #ifndef CTS_USES_VULKANSC
2434 , m_updateRegistry()
2435 #endif
2436 , m_updateBuilder()
2437 , m_descriptorsPerSet()
2438 {
2439 if (m_dynamicOffsetNonZero)
2440 DE_ASSERT(m_setDynamicOffset);
2441 }
2442
createColorDataBuffer(uint32_t offset,uint32_t bufferSize,const tcu::Vec4 & value1,const tcu::Vec4 & value2,de::MovePtr<vk::Allocation> * outAllocation)2443 vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer(uint32_t offset, uint32_t bufferSize,
2444 const tcu::Vec4 &value1, const tcu::Vec4 &value2,
2445 de::MovePtr<vk::Allocation> *outAllocation)
2446 {
2447 DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
2448
2449 const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
2450 const vk::VkBufferUsageFlags usageFlags =
2451 (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2452 const vk::VkBufferCreateInfo createInfo = {
2453 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
2454 nullptr,
2455 0u, // flags
2456 (vk::VkDeviceSize)bufferSize, // size
2457 usageFlags, // usage
2458 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
2459 0u, // queueFamilyCount
2460 nullptr, // pQueueFamilyIndices
2461 };
2462 vk::Move<vk::VkBuffer> buffer(vk::createBuffer(m_vki, m_device, &createInfo));
2463 de::MovePtr<vk::Allocation> allocation(
2464 allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
2465 void *mapPtr = allocation->getHostPtr();
2466
2467 if (offset)
2468 deMemset(mapPtr, 0x5A, (size_t)offset);
2469 deMemcpy((uint8_t *)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
2470 deMemcpy((uint8_t *)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
2471 deMemset((uint8_t *)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A,
2472 (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
2473
2474 flushAlloc(m_vki, m_device, *allocation);
2475
2476 *outAllocation = allocation;
2477 return buffer;
2478 }
2479
createDescriptorSetLayout(uint32_t setNdx) const2480 vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
2481 {
2482 vk::DescriptorSetLayoutBuilder builder;
2483 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
2484 uint32_t binding = 0;
2485
2486 #ifndef CTS_USES_VULKANSC
2487 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
2488 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
2489 {
2490 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
2491 }
2492 #endif
2493
2494 if (setNdx == 0)
2495 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2496 binding++);
2497
2498 switch (m_shaderInterface)
2499 {
2500 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2501 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2502 break;
2503
2504 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2505 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2506 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2507 break;
2508
2509 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2510 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 0u);
2511 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2u);
2512 break;
2513
2514 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2515 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
2516 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
2517 break;
2518
2519 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2520 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2521 break;
2522
2523 default:
2524 DE_FATAL("Impossible");
2525 }
2526
2527 return builder.build(m_vki, m_device, extraFlags);
2528 }
2529
createDescriptorPool(void) const2530 vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool(void) const
2531 {
2532 return vk::DescriptorPoolBuilder()
2533 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2534 .addType(m_descriptorType,
2535 getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
2536 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
2537 getDescriptorSetCount(m_descriptorSetCount));
2538 }
2539
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkBuffer viewA,uint32_t offsetA,vk::VkBuffer viewB,uint32_t offsetB,vk::VkBuffer resBuf)2540 vk::Move<vk::VkDescriptorSet> BufferComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
2541 vk::VkDescriptorSetLayout layout,
2542 uint32_t setNdx, vk::VkBuffer viewA,
2543 uint32_t offsetA, vk::VkBuffer viewB,
2544 uint32_t offsetB, vk::VkBuffer resBuf)
2545 {
2546 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
2547 pool, 1u, &layout};
2548
2549 vk::Move<vk::VkDescriptorSet> descriptorSet;
2550 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
2551 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
2552 {
2553 descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
2554 }
2555 else
2556 {
2557 descriptorSet = vk::Move<vk::VkDescriptorSet>();
2558 }
2559
2560 #ifndef CTS_USES_VULKANSC
2561 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
2562 {
2563 writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx, viewA, offsetA, viewB, offsetB, resBuf);
2564 }
2565 else
2566 #endif
2567 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
2568 {
2569 writeDescriptorSet(*descriptorSet, setNdx, viewA, offsetA, viewB, offsetB, resBuf);
2570 }
2571
2572 return descriptorSet;
2573 }
2574
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::VkBuffer viewA,uint32_t offsetA,vk::VkBuffer viewB,uint32_t offsetB,vk::VkBuffer resBuf)2575 void BufferComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkBuffer viewA,
2576 uint32_t offsetA, vk::VkBuffer viewB, uint32_t offsetB,
2577 vk::VkBuffer resBuf)
2578 {
2579 const vk::VkDescriptorBufferInfo resultInfo =
2580 vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
2581 const vk::VkDescriptorBufferInfo bufferInfos[2] = {
2582 vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2583 vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2584 };
2585
2586 uint32_t numDescriptors = 0u;
2587 uint32_t binding = 0u;
2588
2589 // result
2590 if (setNdx == 0)
2591 {
2592 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2593 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
2594 numDescriptors++;
2595 }
2596
2597 // buffers
2598 switch (m_shaderInterface)
2599 {
2600 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2601 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2602 m_descriptorType, &bufferInfos[0]);
2603 numDescriptors++;
2604 break;
2605
2606 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2607 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2608 m_descriptorType, &bufferInfos[0]);
2609 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2610 m_descriptorType, &bufferInfos[1]);
2611 numDescriptors += 2;
2612 break;
2613
2614 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2615 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
2616 m_descriptorType, &bufferInfos[0]);
2617 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
2618 m_descriptorType, &bufferInfos[1]);
2619 numDescriptors += 2;
2620 break;
2621
2622 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2623 m_updateBuilder.writeSingle(descriptorSet,
2624 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
2625 m_descriptorType, &bufferInfos[0]);
2626 m_updateBuilder.writeSingle(descriptorSet,
2627 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
2628 m_descriptorType, &bufferInfos[1]);
2629 numDescriptors += 2;
2630 break;
2631
2632 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2633 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2634 m_descriptorType, 2u, bufferInfos);
2635 numDescriptors++;
2636 break;
2637
2638 default:
2639 DE_FATAL("Impossible");
2640 }
2641
2642 m_descriptorsPerSet.push_back(numDescriptors);
2643
2644 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
2645 {
2646 m_updateBuilder.update(m_vki, m_device);
2647 m_updateBuilder.clear();
2648 }
2649 }
2650
2651 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkBuffer viewA,uint32_t offsetA,vk::VkBuffer viewB,uint32_t offsetB,vk::VkBuffer resBuf,bool withPush,vk::VkPipelineLayout pipelineLayout)2652 void BufferComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
2653 vk::VkDescriptorSetLayout layout, uint32_t setNdx,
2654 vk::VkBuffer viewA, uint32_t offsetA, vk::VkBuffer viewB,
2655 uint32_t offsetB, vk::VkBuffer resBuf, bool withPush,
2656 vk::VkPipelineLayout pipelineLayout)
2657 {
2658 const vk::VkDescriptorBufferInfo resultInfo =
2659 vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
2660 const vk::VkDescriptorBufferInfo bufferInfos[2] = {
2661 vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2662 vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2663 };
2664 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
2665 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
2666 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
2667 nullptr,
2668 0,
2669 0, // descriptorUpdateEntryCount
2670 nullptr, // pDescriptorUpdateEntries
2671 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
2672 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
2673 layout,
2674 vk::VK_PIPELINE_BIND_POINT_COMPUTE,
2675 pipelineLayout,
2676 setNdx};
2677 uint32_t binding = 0u;
2678 uint32_t offset = 0u;
2679 RawUpdateRegistry updateRegistry;
2680
2681 if (setNdx == 0)
2682 updateRegistry.addWriteObject(resultInfo);
2683
2684 updateRegistry.addWriteObject(bufferInfos[0]);
2685 updateRegistry.addWriteObject(bufferInfos[1]);
2686
2687 // result
2688 if (setNdx == 0)
2689 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2690 updateRegistry.getWriteObjectOffset(offset++), 0));
2691
2692 // buffers
2693 switch (m_shaderInterface)
2694 {
2695 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2696 updateEntries.push_back(
2697 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2698 break;
2699
2700 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2701 updateEntries.push_back(
2702 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2703 updateEntries.push_back(
2704 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2705 break;
2706
2707 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2708 updateEntries.push_back(
2709 createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2710 updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
2711 updateRegistry.getWriteObjectOffset(offset++), 0));
2712 break;
2713
2714 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2715 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
2716 updateRegistry.getWriteObjectOffset(offset++), 0));
2717 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
2718 updateRegistry.getWriteObjectOffset(offset++), 0));
2719 break;
2720
2721 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2722 updateEntries.push_back(createTemplateBinding(
2723 binding++, 0, 2, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), sizeof(bufferInfos[0])));
2724 break;
2725
2726 default:
2727 DE_FATAL("Impossible");
2728 }
2729
2730 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
2731 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
2732
2733 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
2734 vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
2735 m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
2736 m_updateRegistry.push_back(updateRegistry);
2737
2738 if (!withPush)
2739 {
2740 m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
2741 m_updateRegistry.back().getRawPointer());
2742 }
2743 }
2744 #endif
2745
iterate(void)2746 tcu::TestStatus BufferComputeInstance::iterate(void)
2747 {
2748 logTestPlan();
2749 return testResourceAccess();
2750 }
2751
logTestPlan(void) const2752 void BufferComputeInstance::logTestPlan(void) const
2753 {
2754 std::ostringstream msg;
2755
2756 msg << "Accessing resource in a compute program.\n"
2757 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
2758 "Multiple descriptor sets. ")
2759 << "Each descriptor set contains "
2760 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
2761 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
2762 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
2763 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
2764 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
2765 nullptr)
2766 << " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType)
2767 << " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n"
2768 << "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
2769
2770 if (isDynamicDescriptorType(m_descriptorType))
2771 {
2772 if (m_setDynamicOffset)
2773 {
2774 msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
2775 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
2776 }
2777 else
2778 {
2779 msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
2780 }
2781 }
2782
2783 msg << "Destination buffer is pre-initialized to -1.\n";
2784
2785 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
2786 }
2787
testResourceAccess(void)2788 tcu::TestStatus BufferComputeInstance::testResourceAccess(void)
2789 {
2790 enum
2791 {
2792 ADDRESSABLE_SIZE = 256, // allocate a lot more than required
2793 };
2794
2795 const bool isDynamicCase = isDynamicDescriptorType(m_descriptorType);
2796 const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
2797
2798 const tcu::Vec4 color[] = {
2799 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), // green
2800 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), // yellow
2801 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), // blue
2802 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), // red
2803 };
2804
2805 std::vector<uint32_t> bindTimeOffsets;
2806 std::vector<tcu::Vec4> colors;
2807 std::vector<uint32_t> dataOffsets;
2808 std::vector<uint32_t> viewOffsets;
2809 std::vector<uint32_t> bufferSizes;
2810 std::vector<AllocationSp> bufferMems;
2811 std::vector<BufferHandleSp> buffers;
2812
2813 for (uint32_t bufferNdx = 0;
2814 bufferNdx < getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface);
2815 bufferNdx++)
2816 {
2817 const uint32_t staticOffsets[] = {STATIC_OFFSET_VALUE_A, STATIC_OFFSET_VALUE_B};
2818
2819 const uint32_t dynamicOffset[] = {DYNAMIC_OFFSET_VALUE_A, DYNAMIC_OFFSET_VALUE_B};
2820
2821 const uint32_t parity = bufferNdx % 2;
2822 bindTimeOffsets.push_back((m_dynamicOffsetNonZero) ? (dynamicOffset[parity]) : (0u));
2823
2824 const uint32_t dataOffset =
2825 ((isDynamicCase) ? (bindTimeOffsets.back()) : 0) + ((m_setViewOffset) ? (staticOffsets[parity]) : (0u));
2826 const uint32_t viewOffset = ((m_setViewOffset) ? (staticOffsets[parity]) : (0u));
2827
2828 colors.push_back(color[bufferNdx % DE_LENGTH_OF_ARRAY(color)]);
2829 dataOffsets.push_back(dataOffset);
2830 viewOffsets.push_back(viewOffset);
2831 bufferSizes.push_back(dataOffsets.back() + ADDRESSABLE_SIZE);
2832
2833 de::MovePtr<vk::Allocation> bufferMem;
2834 vk::Move<vk::VkBuffer> buffer(createColorDataBuffer(
2835 dataOffsets.back(), bufferSizes.back(), color[(bufferNdx * 2) % DE_LENGTH_OF_ARRAY(color)],
2836 color[(bufferNdx * 2 + 1) % DE_LENGTH_OF_ARRAY(color)], &bufferMem));
2837
2838 bufferMems.push_back(AllocationSp(bufferMem.release()));
2839 buffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
2840 }
2841
2842 const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
2843 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
2844 std::vector<DescriptorSetHandleSp> descriptorSets;
2845 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
2846 std::vector<vk::VkDescriptorSet> setHandles;
2847
2848 const uint32_t numSrcBuffers =
2849 getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface);
2850
2851 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2852 {
2853 const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2854 const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2855
2856 vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
2857 vk::Move<vk::VkDescriptorSet> set =
2858 createDescriptorSet(*descriptorPool, *layout, setNdx, **buffers[ndx0], viewOffsets[ndx0], **buffers[ndx1],
2859 viewOffsets[ndx1], m_result.getBuffer());
2860
2861 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
2862 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
2863
2864 layoutHandles.push_back(**descriptorSetLayouts.back());
2865 setHandles.push_back(**descriptorSets.back());
2866
2867 // Add an empty descriptor set layout between sets 0 and 2
2868 if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
2869 {
2870 vk::DescriptorSetLayoutBuilder emptyBuilder;
2871 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
2872 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
2873
2874 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
2875 layoutHandles.push_back(**descriptorSetLayouts.back());
2876 }
2877 }
2878
2879 const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
2880 &layoutHandles.front());
2881 const vk::VkAccessFlags inputBit =
2882 (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
2883
2884 std::vector<vk::VkBufferMemoryBarrier> bufferBarriers;
2885
2886 for (uint32_t bufferNdx = 0; bufferNdx < numSrcBuffers; bufferNdx++)
2887 {
2888 const vk::VkBufferMemoryBarrier barrier = {
2889 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2890 nullptr,
2891 vk::VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
2892 inputBit, // dstAccessMask
2893 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
2894 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
2895 **buffers[bufferNdx], // buffer
2896 (vk::VkDeviceSize)0u, // offset
2897 (vk::VkDeviceSize)bufferSizes[bufferNdx], // size
2898 };
2899
2900 bufferBarriers.push_back(barrier);
2901 }
2902
2903 const uint32_t *const dynamicOffsets = (m_setDynamicOffset) ? (&bindTimeOffsets.front()) : (nullptr);
2904 const uint32_t numDynamicOffsets = (m_setDynamicOffset) ? (numSrcBuffers) : (0);
2905 const vk::VkBufferMemoryBarrier *const preBarriers = &bufferBarriers.front();
2906 const int numPreBarriers = numSrcBuffers;
2907 const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
2908 const int numPostBarriers = 1;
2909
2910 const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
2911 tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
2912 numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
2913 postBarriers, m_bind2);
2914
2915 tcu::Vec4 refQuadrantValue14 = tcu::Vec4(0.0f);
2916 tcu::Vec4 refQuadrantValue23 = tcu::Vec4(0.0f);
2917
2918 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2919 {
2920 uint32_t offset = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? 1 : 3;
2921 refQuadrantValue14 +=
2922 color[(2 * setNdx * getInterfaceNumResources(m_shaderInterface) + offset) % DE_LENGTH_OF_ARRAY(color)];
2923 refQuadrantValue23 +=
2924 color[(2 * setNdx * getInterfaceNumResources(m_shaderInterface)) % DE_LENGTH_OF_ARRAY(color)];
2925 }
2926
2927 refQuadrantValue14 = refQuadrantValue14 / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
2928 refQuadrantValue23 = refQuadrantValue23 / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
2929
2930 const tcu::Vec4 references[4] = {
2931 refQuadrantValue14,
2932 refQuadrantValue23,
2933 refQuadrantValue23,
2934 refQuadrantValue14,
2935 };
2936 tcu::Vec4 results[4];
2937
2938 #ifndef CTS_USES_VULKANSC
2939 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
2940 {
2941 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2942 {
2943 const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2944 const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2945
2946 writeDescriptorSetWithTemplate(VK_NULL_HANDLE, layoutHandles[setNdx], setNdx, **buffers[ndx0],
2947 viewOffsets[ndx0], **buffers[ndx1], viewOffsets[ndx1], m_result.getBuffer(),
2948 true, pipeline.getPipelineLayout());
2949 }
2950 compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
2951 }
2952 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
2953 {
2954 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2955 {
2956 const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2957 const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2958
2959 writeDescriptorSet(VK_NULL_HANDLE, setNdx, **buffers[ndx0], viewOffsets[ndx0], **buffers[ndx1],
2960 viewOffsets[ndx1], m_result.getBuffer());
2961 }
2962
2963 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
2964 }
2965 else
2966 #endif
2967 {
2968 compute.submitAndWait(m_queueFamilyIndex, m_queue);
2969 }
2970 m_result.readResultContentsTo(&results);
2971
2972 // verify
2973 if (results[0] == references[0] && results[1] == references[1] && results[2] == references[2] &&
2974 results[3] == references[3])
2975 {
2976 return tcu::TestStatus::pass("Pass");
2977 }
2978 else if (results[0] == tcu::Vec4(-1.0f) && results[1] == tcu::Vec4(-1.0f) && results[2] == tcu::Vec4(-1.0f) &&
2979 results[3] == tcu::Vec4(-1.0f))
2980 {
2981 m_context.getTestContext().getLog()
2982 << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
2983 return tcu::TestStatus::fail("Result buffer was not written to");
2984 }
2985 else
2986 {
2987 m_context.getTestContext().getLog()
2988 << tcu::TestLog::Message << "Error expected [" << references[0] << ", " << references[1] << ", "
2989 << references[2] << ", " << references[3] << "], got [" << results[0] << ", " << results[1] << ", "
2990 << results[2] << ", " << results[3] << "]" << tcu::TestLog::EndMessage;
2991 return tcu::TestStatus::fail("Invalid result values");
2992 }
2993 }
2994
2995 class QuadrantRendederCase : public vkt::TestCase
2996 {
2997 public:
2998 QuadrantRendederCase(tcu::TestContext &testCtx, const char *name, glu::GLSLVersion glslVersion,
2999 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3000 DescriptorSetCount descriptorSetCount);
3001
3002 private:
3003 virtual std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const = 0;
3004 virtual std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const = 0;
3005 virtual std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const = 0;
3006 virtual std::string genNoAccessSource(void) const = 0;
3007
3008 std::string genVertexSource(void) const;
3009 std::string genTessCtrlSource(void) const;
3010 std::string genTessEvalSource(void) const;
3011 std::string genGeometrySource(void) const;
3012 std::string genFragmentSource(void) const;
3013 std::string genComputeSource(void) const;
3014
3015 void initPrograms(vk::SourceCollections &programCollection) const;
3016
3017 protected:
3018 const glu::GLSLVersion m_glslVersion;
3019 const vk::VkShaderStageFlags m_exitingStages;
3020 const vk::VkShaderStageFlags m_activeStages;
3021 const DescriptorSetCount m_descriptorSetCount;
3022 };
3023
QuadrantRendederCase(tcu::TestContext & testCtx,const char * name,glu::GLSLVersion glslVersion,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount)3024 QuadrantRendederCase::QuadrantRendederCase(tcu::TestContext &testCtx, const char *name, glu::GLSLVersion glslVersion,
3025 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3026 DescriptorSetCount descriptorSetCount)
3027 : vkt::TestCase(testCtx, name)
3028 , m_glslVersion(glslVersion)
3029 , m_exitingStages(exitingStages)
3030 , m_activeStages(activeStages)
3031 , m_descriptorSetCount(descriptorSetCount)
3032 {
3033 DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages);
3034 }
3035
genVertexSource(void) const3036 std::string QuadrantRendederCase::genVertexSource(void) const
3037 {
3038 const char *const nextStageName = ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) ?
3039 ("tsc") :
3040 ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u) ? ("geo") :
3041 ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u) ? ("frag") :
3042 (nullptr);
3043 const char *const fragColorPrec =
3044 ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? "highp" : "mediump";
3045 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3046 std::ostringstream buf;
3047
3048 if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
3049 {
3050 const bool onlyVS = (m_activeStages == vk::VK_SHADER_STAGE_VERTEX_BIT);
3051
3052 // active vertex shader
3053 buf << versionDecl << "\n" << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT);
3054 buf << genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT, 0);
3055 buf << "layout(location = 0) out " << fragColorPrec << " vec4 " << nextStageName << "_color;\n"
3056 << (onlyVS ? "" :
3057 "layout(location = 1) flat out highp int " + de::toString(nextStageName) + "_quadrant_id;\n")
3058 << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) << "void main (void)\n"
3059 << "{\n"
3060 << " highp vec4 result_position;\n"
3061 << " highp int quadrant_id;\n"
3062 << s_quadrantGenVertexPosSource << " gl_Position = result_position;\n"
3063 << (onlyVS ? "" : "\t" + de::toString(nextStageName) + "_quadrant_id = quadrant_id;\n") << "\n"
3064 << " highp vec4 result_color;\n"
3065 << genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX_BIT) << " " << nextStageName
3066 << "_color = result_color;\n"
3067 << "}\n";
3068 }
3069 else
3070 {
3071 // do nothing
3072 buf << versionDecl << "\n"
3073 << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT) << "layout(location = 1) flat out highp int "
3074 << nextStageName << "_quadrant_id;\n"
3075 << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) << "void main (void)\n"
3076 << "{\n"
3077 << " highp vec4 result_position;\n"
3078 << " highp int quadrant_id;\n"
3079 << s_quadrantGenVertexPosSource << " gl_Position = result_position;\n"
3080 << " " << nextStageName << "_quadrant_id = quadrant_id;\n"
3081 << "}\n";
3082 }
3083
3084 return buf.str();
3085 }
3086
genTessCtrlSource(void) const3087 std::string QuadrantRendederCase::genTessCtrlSource(void) const
3088 {
3089 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3090 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3091 const char *const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
3092 std::ostringstream buf;
3093
3094 if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3095 {
3096 // contributing not implemented
3097 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3098
3099 // active tc shader
3100 buf << versionDecl << "\n"
3101 << tessExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
3102 << "layout(vertices=3) out;\n"
3103 << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0)
3104 << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
3105 << "layout(location = 0) out highp vec4 tes_color[];\n"
3106 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) << "void main (void)\n"
3107 << "{\n"
3108 << " highp vec4 result_color;\n"
3109 << " highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n"
3110 << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) << "\n"
3111 << " tes_color[gl_InvocationID] = result_color;\n"
3112 << "\n"
3113 << " // no dynamic input block indexing\n"
3114 << " highp vec4 position;\n"
3115 << " if (gl_InvocationID == 0)\n"
3116 << " position = gl_in[0].gl_Position;\n"
3117 << " else if (gl_InvocationID == 1)\n"
3118 << " position = gl_in[1].gl_Position;\n"
3119 << " else\n"
3120 << " position = gl_in[2].gl_Position;\n"
3121 << " gl_out[gl_InvocationID].gl_Position = position;\n"
3122 << " gl_TessLevelInner[0] = 2.8;\n"
3123 << " gl_TessLevelInner[1] = 2.8;\n"
3124 << " gl_TessLevelOuter[0] = 2.8;\n"
3125 << " gl_TessLevelOuter[1] = 2.8;\n"
3126 << " gl_TessLevelOuter[2] = 2.8;\n"
3127 << " gl_TessLevelOuter[3] = 2.8;\n"
3128 << "}\n";
3129 }
3130 else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3131 {
3132 // active te shader, tc passthru
3133 buf << versionDecl << "\n"
3134 << tessExtDecl << "layout(vertices=3) out;\n"
3135 << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
3136 << "layout(location = 1) flat out highp int tes_quadrant_id[];\n"
3137 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) << "void main (void)\n"
3138 << "{\n"
3139 << " tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n"
3140 << "\n"
3141 << " // no dynamic input block indexing\n"
3142 << " highp vec4 position;\n"
3143 << " if (gl_InvocationID == 0)\n"
3144 << " position = gl_in[0].gl_Position;\n"
3145 << " else if (gl_InvocationID == 1)\n"
3146 << " position = gl_in[1].gl_Position;\n"
3147 << " else\n"
3148 << " position = gl_in[2].gl_Position;\n"
3149 << " gl_out[gl_InvocationID].gl_Position = position;\n"
3150 << " gl_TessLevelInner[0] = 2.8;\n"
3151 << " gl_TessLevelInner[1] = 2.8;\n"
3152 << " gl_TessLevelOuter[0] = 2.8;\n"
3153 << " gl_TessLevelOuter[1] = 2.8;\n"
3154 << " gl_TessLevelOuter[2] = 2.8;\n"
3155 << " gl_TessLevelOuter[3] = 2.8;\n"
3156 << "}\n";
3157 }
3158 else
3159 {
3160 // passthrough not implemented
3161 DE_FATAL("not implemented");
3162 }
3163
3164 return buf.str();
3165 }
3166
genTessEvalSource(void) const3167 std::string QuadrantRendederCase::genTessEvalSource(void) const
3168 {
3169 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3170 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3171 const char *const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
3172 std::ostringstream buf;
3173
3174 if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3175 {
3176 // contributing not implemented
3177 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
3178
3179 // active te shader
3180 buf << versionDecl << "\n"
3181 << tessExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
3182 << "layout(triangles) in;\n"
3183 << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0)
3184 << "layout(location = 1) flat in highp int tes_quadrant_id[];\n"
3185 << "layout(location = 0) out mediump vec4 frag_color;\n"
3186 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) << "void main (void)\n"
3187 << "{\n"
3188 << " highp vec4 result_color;\n"
3189 << " highp int quadrant_id = tes_quadrant_id[0];\n"
3190 << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) << "\n"
3191 << " frag_color = result_color;\n"
3192 << " gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + "
3193 "gl_TessCoord.z * gl_in[2].gl_Position;\n"
3194 << "}\n";
3195 }
3196 else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3197 {
3198 // contributing not implemented
3199 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3200
3201 // active tc shader, te is passthru
3202 buf << versionDecl << "\n"
3203 << tessExtDecl << "layout(triangles) in;\n"
3204 << "layout(location = 0) in highp vec4 tes_color[];\n"
3205 << "layout(location = 0) out mediump vec4 frag_color;\n"
3206 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) << "void main (void)\n"
3207 << "{\n"
3208 << " frag_color = tes_color[0];\n"
3209 << " gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + "
3210 "gl_TessCoord.z * gl_in[2].gl_Position;\n"
3211 << "}\n";
3212 }
3213 else
3214 {
3215 // passthrough not implemented
3216 DE_FATAL("not implemented");
3217 }
3218
3219 return buf.str();
3220 }
3221
genGeometrySource(void) const3222 std::string QuadrantRendederCase::genGeometrySource(void) const
3223 {
3224 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3225 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3226 const char *const geomExtDecl = extRequired ? "#extension GL_EXT_geometry_shader : require\n" : "";
3227 std::ostringstream buf;
3228
3229 if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
3230 {
3231 // contributing not implemented
3232 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT);
3233
3234 // active geometry shader
3235 buf << versionDecl << "\n"
3236 << geomExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "layout(triangles) in;\n"
3237 << "layout(triangle_strip, max_vertices=4) out;\n"
3238 << genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0)
3239 << "layout(location = 1) flat in highp int geo_quadrant_id[];\n"
3240 << "layout(location = 0) out mediump vec4 frag_color;\n"
3241 << genPerVertexBlock(vk::VK_SHADER_STAGE_GEOMETRY_BIT, m_glslVersion) << "void main (void)\n"
3242 << "{\n"
3243 << " highp int quadrant_id;\n"
3244 << " highp vec4 result_color;\n"
3245 << "\n"
3246 << " quadrant_id = geo_quadrant_id[0];\n"
3247 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << " frag_color = result_color;\n"
3248 << " gl_Position = gl_in[0].gl_Position;\n"
3249 << " EmitVertex();\n"
3250 << "\n"
3251 << " quadrant_id = geo_quadrant_id[1];\n"
3252 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << " frag_color = result_color;\n"
3253 << " gl_Position = gl_in[1].gl_Position;\n"
3254 << " EmitVertex();\n"
3255 << "\n"
3256 << " quadrant_id = geo_quadrant_id[2];\n"
3257 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << " frag_color = result_color;\n"
3258 << " gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n"
3259 << " EmitVertex();\n"
3260 << "\n"
3261 << " quadrant_id = geo_quadrant_id[0];\n"
3262 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << " frag_color = result_color;\n"
3263 << " gl_Position = gl_in[2].gl_Position;\n"
3264 << " EmitVertex();\n"
3265 << "}\n";
3266 }
3267 else
3268 {
3269 // passthrough not implemented
3270 DE_FATAL("not implemented");
3271 }
3272
3273 return buf.str();
3274 }
3275
genFragmentSource(void) const3276 std::string QuadrantRendederCase::genFragmentSource(void) const
3277 {
3278 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3279 std::ostringstream buf;
3280
3281 if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
3282 {
3283 buf << versionDecl << "\n"
3284 << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
3285 << genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0);
3286
3287 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
3288 {
3289 // there are other stages, this is just a contributor
3290 buf << "layout(location = 0) in mediump vec4 frag_color;\n";
3291 }
3292
3293 buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
3294 << "layout(location = 0) out mediump vec4 o_color;\n"
3295 << "void main (void)\n"
3296 << "{\n"
3297 << " highp int quadrant_id = frag_quadrant_id;\n"
3298 << " highp vec4 result_color;\n"
3299 << genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
3300
3301 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
3302 {
3303 // just contributor
3304 buf << " if (frag_quadrant_id < 2)\n"
3305 << " o_color = result_color;\n"
3306 << " else\n"
3307 << " o_color = frag_color;\n";
3308 }
3309 else
3310 buf << " o_color = result_color;\n";
3311
3312 buf << "}\n";
3313 }
3314 else if (m_activeStages == 0u)
3315 {
3316 // special case, no active stages
3317 buf << versionDecl << "\n"
3318 << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
3319 << "layout(location = 0) out mediump vec4 o_color;\n"
3320 << "void main (void)\n"
3321 << "{\n"
3322 << " highp int quadrant_id = frag_quadrant_id;\n"
3323 << " highp vec4 result_color;\n"
3324 << genNoAccessSource() << " o_color = result_color;\n"
3325 << "}\n";
3326 }
3327 else
3328 {
3329 // passthrough
3330 buf << versionDecl << "\n"
3331 << "layout(location = 0) in mediump vec4 frag_color;\n"
3332 "layout(location = 0) out mediump vec4 o_color;\n"
3333 "void main (void)\n"
3334 "{\n"
3335 " o_color = frag_color;\n"
3336 "}\n";
3337 }
3338
3339 return buf.str();
3340 }
3341
genComputeSource(void) const3342 std::string QuadrantRendederCase::genComputeSource(void) const
3343 {
3344 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3345 std::ostringstream buf;
3346
3347 buf << versionDecl << "\n"
3348 << genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT)
3349 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3350 << genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT, 1)
3351 << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
3352 << "{\n"
3353 << " highp vec4 read_colors[4];\n"
3354 << "} b_out;\n"
3355 << "void main (void)\n"
3356 << "{\n"
3357 << " highp int quadrant_id = int(gl_WorkGroupID.x);\n"
3358 << " highp vec4 result_color;\n"
3359 << genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE_BIT)
3360 << " b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
3361 << "}\n";
3362
3363 return buf.str();
3364 }
3365
initPrograms(vk::SourceCollections & programCollection) const3366 void QuadrantRendederCase::initPrograms(vk::SourceCollections &programCollection) const
3367 {
3368 if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
3369 programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource());
3370
3371 if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3372 programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource());
3373
3374 if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3375 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource());
3376
3377 if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
3378 programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource());
3379
3380 if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
3381 programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource());
3382
3383 if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u)
3384 programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource());
3385 }
3386
3387 class BufferDescriptorCase : public QuadrantRendederCase
3388 {
3389 public:
3390 enum
3391 {
3392 FLAG_VIEW_OFFSET = (1u << 1u),
3393 FLAG_DYNAMIC_OFFSET_ZERO = (1u << 2u),
3394 FLAG_DYNAMIC_OFFSET_NONZERO = (1u << 3u),
3395 };
3396 // enum continues where resource flags ends
3397 DE_STATIC_ASSERT((uint32_t)FLAG_VIEW_OFFSET == (uint32_t)RESOURCE_FLAG_LAST);
3398
3399 BufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name,
3400 bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
3401 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3402 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, uint32_t flags,
3403 const bool bind2);
3404
3405 private:
3406 std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
3407 std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
3408 std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
3409 std::string genNoAccessSource(void) const;
3410
3411 vkt::TestInstance *createInstance(vkt::Context &context) const;
3412
3413 void checkSupport(Context &context) const;
3414
3415 const DescriptorUpdateMethod m_updateMethod;
3416 const bool m_viewOffset;
3417 const bool m_dynamicOffsetSet;
3418 const bool m_dynamicOffsetNonZero;
3419 const bool m_isPrimaryCmdBuf;
3420 const vk::VkDescriptorType m_descriptorType;
3421 const DescriptorSetCount m_descriptorSetCount;
3422 const ShaderInputInterface m_shaderInterface;
3423 const bool m_bind2;
3424 };
3425
BufferDescriptorCase(tcu::TestContext & testCtx,DescriptorUpdateMethod updateMethod,const char * name,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,uint32_t flags,const bool bind2)3426 BufferDescriptorCase::BufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod,
3427 const char *name, bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
3428 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3429 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
3430 uint32_t flags, const bool bind2)
3431 : QuadrantRendederCase(testCtx, name, glu::GLSL_VERSION_310_ES, exitingStages, activeStages, descriptorSetCount)
3432 , m_updateMethod(updateMethod)
3433 , m_viewOffset((flags & FLAG_VIEW_OFFSET) != 0u)
3434 , m_dynamicOffsetSet((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u)
3435 , m_dynamicOffsetNonZero((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u)
3436 , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
3437 , m_descriptorType(descriptorType)
3438 , m_descriptorSetCount(descriptorSetCount)
3439 , m_shaderInterface(shaderInterface)
3440 , m_bind2(bind2)
3441 {
3442 }
3443
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const3444 std::string BufferDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
3445 {
3446 DE_UNREF(stage);
3447 return "";
3448 }
3449
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const3450 std::string BufferDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const
3451 {
3452 DE_UNREF(stage);
3453
3454 const bool isUniform = isUniformDescriptorType(m_descriptorType);
3455 const char *const storageType = (isUniform) ? ("uniform") : ("buffer");
3456 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
3457
3458 std::ostringstream buf;
3459
3460 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
3461 {
3462 // Result buffer is bound only to the first descriptor set in compute shader cases
3463 const int descBinding =
3464 numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
3465 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
3466 const uint32_t descriptorSet = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
3467
3468 switch (m_shaderInterface)
3469 {
3470 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3471 buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3472 << " BufferName" << setNdxPostfix << "\n"
3473 << "{\n"
3474 << " highp vec4 colorA;\n"
3475 << " highp vec4 colorB;\n"
3476 << "} b_instance" << setNdxPostfix << ";\n";
3477 break;
3478
3479 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3480 buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3481 << " BufferName" << setNdxPostfix << "A\n"
3482 << "{\n"
3483 << " highp vec4 colorA;\n"
3484 << " highp vec4 colorB;\n"
3485 << "} b_instance" << setNdxPostfix << "A;\n"
3486 << "layout(set = " << descriptorSet << ", binding = " << (descBinding + 1) << ", std140) "
3487 << storageType << " BufferName" << setNdxPostfix << "B\n"
3488 << "{\n"
3489 << " highp vec4 colorA;\n"
3490 << " highp vec4 colorB;\n"
3491 << "} b_instance" << setNdxPostfix << "B;\n";
3492 break;
3493
3494 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
3495 buf << "layout(set = " << descriptorSet << ", binding = " << de::toString(descBinding) << ", std140) "
3496 << storageType << " BufferName" << setNdxPostfix << "A\n"
3497 << "{\n"
3498 << " highp vec4 colorA;\n"
3499 << " highp vec4 colorB;\n"
3500 << "} b_instance" << setNdxPostfix << "A;\n"
3501 << "layout(set = " << descriptorSet << ", binding = " << de::toString(descBinding + 2) << ", std140) "
3502 << storageType << " BufferName" << setNdxPostfix << "B\n"
3503 << "{\n"
3504 << " highp vec4 colorA;\n"
3505 << " highp vec4 colorB;\n"
3506 << "} b_instance" << setNdxPostfix << "B;\n";
3507 break;
3508
3509 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
3510 buf << "layout(set = " << descriptorSet << ", binding = " << de::toString(getArbitraryBindingIndex(0))
3511 << ", std140) " << storageType << " BufferName" << setNdxPostfix << "A\n"
3512 << "{\n"
3513 << " highp vec4 colorA;\n"
3514 << " highp vec4 colorB;\n"
3515 << "} b_instance" << setNdxPostfix << "A;\n"
3516 << "layout(set = " << descriptorSet << ", binding = " << de::toString(getArbitraryBindingIndex(1))
3517 << ", std140) " << storageType << " BufferName" << setNdxPostfix << "B\n"
3518 << "{\n"
3519 << " highp vec4 colorA;\n"
3520 << " highp vec4 colorB;\n"
3521 << "} b_instance" << setNdxPostfix << "B;\n";
3522 break;
3523
3524 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3525 buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3526 << " BufferName" << setNdxPostfix << "\n"
3527 << "{\n"
3528 << " highp vec4 colorA;\n"
3529 << " highp vec4 colorB;\n"
3530 << "} b_instances" << setNdxPostfix << "[2];\n";
3531 break;
3532
3533 default:
3534 DE_FATAL("Impossible");
3535 }
3536 }
3537 return buf.str();
3538 }
3539
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const3540 std::string BufferDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
3541 {
3542 DE_UNREF(stage);
3543
3544 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
3545 std::ostringstream buf;
3546
3547 buf << " result_color = vec4(0.0);\n";
3548
3549 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
3550 {
3551 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
3552
3553 switch (m_shaderInterface)
3554 {
3555 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3556 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
3557 << " result_color += b_instance" << setNdxPostfix << ".colorA;\n"
3558 << " else\n"
3559 << " result_color += b_instance" << setNdxPostfix << ".colorB;\n";
3560 break;
3561
3562 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3563 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
3564 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
3565 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
3566 << " result_color += b_instance" << setNdxPostfix << "A.colorA;\n"
3567 << " else\n"
3568 << " result_color += b_instance" << setNdxPostfix << "B.colorB;\n";
3569 break;
3570
3571 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3572 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
3573 << " result_color += b_instances" << setNdxPostfix << "[0].colorA;\n"
3574 << " else\n"
3575 << " result_color += b_instances" << setNdxPostfix << "[1].colorB;\n";
3576 break;
3577
3578 default:
3579 DE_FATAL("Impossible");
3580 }
3581 }
3582
3583 if (getDescriptorSetCount(m_descriptorSetCount) > 1)
3584 buf << " result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
3585
3586 return buf.str();
3587 }
3588
genNoAccessSource(void) const3589 std::string BufferDescriptorCase::genNoAccessSource(void) const
3590 {
3591 return " if (quadrant_id == 1 || quadrant_id == 2)\n"
3592 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
3593 " else\n"
3594 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
3595 }
3596
createInstance(vkt::Context & context) const3597 vkt::TestInstance *BufferDescriptorCase::createInstance(vkt::Context &context) const
3598 {
3599 verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
3600 m_updateMethod, m_descriptorType, m_activeStages);
3601
3602 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
3603 {
3604 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
3605 return new BufferComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
3606 m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero,
3607 m_bind2);
3608 }
3609 else
3610 return new BufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
3611 m_descriptorSetCount, m_activeStages, m_exitingStages, m_shaderInterface,
3612 m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero, m_bind2);
3613 }
3614
checkSupport(Context & context) const3615 void BufferDescriptorCase::checkSupport(Context &context) const
3616 {
3617 if (m_bind2)
3618 context.requireDeviceFunctionality("VK_KHR_maintenance6");
3619 }
3620
3621 class ImageInstanceImages
3622 {
3623 public:
3624 ImageInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3625 vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3626 vk::VkImageViewType viewType, int numImages, uint32_t numLevels, uint32_t baseMipLevel,
3627 uint32_t baseArraySlice);
3628
3629 private:
3630 static std::vector<tcu::TextureLevelPyramid> createSourceImages(int numImages, int numLevels,
3631 vk::VkImageViewType viewType,
3632 tcu::TextureFormat imageFormat);
3633
3634 static std::vector<ImageHandleSp> createImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3635 vk::Allocator &allocator, uint32_t queueFamilyIndex,
3636 vk::VkQueue queue, vk::VkDescriptorType descriptorType,
3637 vk::VkImageViewType viewType, std::vector<AllocationSp> &imageMemory,
3638 const std::vector<tcu::TextureLevelPyramid> &sourceImages);
3639
3640 static std::vector<ImageViewHandleSp> createImageViews(const vk::DeviceInterface &vki, vk::VkDevice device,
3641 vk::VkImageViewType viewType,
3642 const std::vector<tcu::TextureLevelPyramid> &sourceImages,
3643 const std::vector<ImageHandleSp> &images,
3644 uint32_t baseMipLevel, uint32_t baseArraySlice);
3645
3646 static vk::Move<vk::VkImage> createImage(const vk::DeviceInterface &vki, vk::VkDevice device,
3647 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3648 vk::VkImageViewType viewType, const tcu::TextureLevelPyramid &sourceImage,
3649 de::MovePtr<vk::Allocation> *outAllocation);
3650
3651 static vk::Move<vk::VkImageView> createImageView(const vk::DeviceInterface &vki, vk::VkDevice device,
3652 vk::VkImageViewType viewType,
3653 const tcu::TextureLevelPyramid &sourceImage, vk::VkImage image,
3654 uint32_t baseMipLevel, uint32_t baseArraySlice);
3655
3656 static void populateSourceImage(tcu::TextureLevelPyramid *dst, vk::VkImageViewType viewType, int imageNdx);
3657
3658 static void uploadImage(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3659 vk::VkQueue queue, vk::Allocator &allocator, vk::VkImage image, vk::VkImageLayout layout,
3660 vk::VkImageViewType viewType, const tcu::TextureLevelPyramid &data);
3661
3662 protected:
3663 enum
3664 {
3665 IMAGE_SIZE = 64,
3666 ARRAY_SIZE = 2,
3667 };
3668
3669 const vk::VkImageViewType m_viewType;
3670 const uint32_t m_baseMipLevel;
3671 const uint32_t m_baseArraySlice;
3672 const tcu::TextureFormat m_imageFormat;
3673 const std::vector<tcu::TextureLevelPyramid> m_sourceImage;
3674 std::vector<AllocationSp> m_imageMemory;
3675 const std::vector<ImageHandleSp> m_image;
3676 const std::vector<ImageViewHandleSp> m_imageView;
3677 };
3678
ImageInstanceImages(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,vk::VkImageViewType viewType,int numImages,uint32_t numLevels,uint32_t baseMipLevel,uint32_t baseArraySlice)3679 ImageInstanceImages::ImageInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3680 vk::VkQueue queue, vk::Allocator &allocator,
3681 vk::VkDescriptorType descriptorType, vk::VkImageViewType viewType,
3682 int numImages, uint32_t numLevels, uint32_t baseMipLevel,
3683 uint32_t baseArraySlice)
3684 : m_viewType(viewType)
3685 , m_baseMipLevel(baseMipLevel)
3686 , m_baseArraySlice(baseArraySlice)
3687 , m_imageFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
3688 , m_sourceImage(createSourceImages(numImages, numLevels, viewType, m_imageFormat))
3689 , m_imageMemory()
3690 , m_image(createImages(vki, device, allocator, queueFamilyIndex, queue, descriptorType, viewType, m_imageMemory,
3691 m_sourceImage))
3692 , m_imageView(createImageViews(vki, device, viewType, m_sourceImage, m_image, m_baseMipLevel, m_baseArraySlice))
3693 {
3694 }
3695
createSourceImages(int numImages,int numLevels,vk::VkImageViewType viewType,tcu::TextureFormat imageFormat)3696 std::vector<tcu::TextureLevelPyramid> ImageInstanceImages::createSourceImages(int numImages, int numLevels,
3697 vk::VkImageViewType viewType,
3698 tcu::TextureFormat imageFormat)
3699 {
3700 std::vector<tcu::TextureLevelPyramid> sourceImages(numImages, tcu::TextureLevelPyramid(imageFormat, numLevels));
3701
3702 for (int imageNdx = 0; imageNdx < numImages; imageNdx++)
3703 populateSourceImage(&sourceImages.at(imageNdx), viewType, imageNdx);
3704
3705 return sourceImages;
3706 }
3707
createImages(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::VkDescriptorType descriptorType,vk::VkImageViewType viewType,std::vector<AllocationSp> & imageMemory,const std::vector<tcu::TextureLevelPyramid> & sourceImages)3708 std::vector<ImageHandleSp> ImageInstanceImages::createImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3709 vk::Allocator &allocator, uint32_t queueFamilyIndex,
3710 vk::VkQueue queue, vk::VkDescriptorType descriptorType,
3711 vk::VkImageViewType viewType,
3712 std::vector<AllocationSp> &imageMemory,
3713 const std::vector<tcu::TextureLevelPyramid> &sourceImages)
3714 {
3715 std::vector<ImageHandleSp> images;
3716 const vk::VkImageLayout layout = getImageLayoutForDescriptorType(descriptorType);
3717
3718 for (int imageNdx = 0; imageNdx < (int)sourceImages.size(); imageNdx++)
3719 {
3720 de::MovePtr<vk::Allocation> memory;
3721 vk::Move<vk::VkImage> image =
3722 createImage(vki, device, allocator, descriptorType, viewType, sourceImages[imageNdx], &memory);
3723
3724 uploadImage(vki, device, queueFamilyIndex, queue, allocator, *image, layout, viewType, sourceImages[imageNdx]);
3725
3726 imageMemory.push_back(AllocationSp(memory.release()));
3727 images.push_back(ImageHandleSp(new ImageHandleUp(image)));
3728 }
3729 return images;
3730 }
3731
createImageViews(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkImageViewType viewType,const std::vector<tcu::TextureLevelPyramid> & sourceImages,const std::vector<ImageHandleSp> & images,uint32_t baseMipLevel,uint32_t baseArraySlice)3732 std::vector<ImageViewHandleSp> ImageInstanceImages::createImageViews(
3733 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkImageViewType viewType,
3734 const std::vector<tcu::TextureLevelPyramid> &sourceImages, const std::vector<ImageHandleSp> &images,
3735 uint32_t baseMipLevel, uint32_t baseArraySlice)
3736 {
3737 std::vector<ImageViewHandleSp> imageViews;
3738 for (int imageNdx = 0; imageNdx < (int)sourceImages.size(); imageNdx++)
3739 {
3740 vk::Move<vk::VkImageView> imageView = createImageView(vki, device, viewType, sourceImages[imageNdx],
3741 **images[imageNdx], baseMipLevel, baseArraySlice);
3742 imageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imageView)));
3743 }
3744 return imageViews;
3745 }
3746
createImage(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & sourceImage,de::MovePtr<vk::Allocation> * outAllocation)3747 vk::Move<vk::VkImage> ImageInstanceImages::createImage(const vk::DeviceInterface &vki, vk::VkDevice device,
3748 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3749 vk::VkImageViewType viewType,
3750 const tcu::TextureLevelPyramid &sourceImage,
3751 de::MovePtr<vk::Allocation> *outAllocation)
3752 {
3753 const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
3754 const bool isCube = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
3755 const bool isStorage = (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
3756 const uint32_t readUsage = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
3757 const uint32_t arraySize =
3758 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3759 (baseLevel.getHeight()) :
3760 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ?
3761 (baseLevel.getDepth()) :
3762 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3763 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3764 (baseLevel.getDepth()) // cube: numFaces * numLayers
3765 :
3766 (0);
3767 const vk::VkExtent3D extent = {
3768 // x
3769 (uint32_t)baseLevel.getWidth(),
3770
3771 // y
3772 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3773 (1u) :
3774 (uint32_t)baseLevel.getHeight(),
3775
3776 // z
3777 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((uint32_t)baseLevel.getDepth()) : (1u),
3778 };
3779 const vk::VkImageCreateInfo createInfo = {
3780 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3781 nullptr,
3782 isCube ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (vk::VkImageCreateFlags)0,
3783 viewTypeToImageType(viewType), // imageType
3784 vk::mapTextureFormat(baseLevel.getFormat()), // format
3785 extent, // extent
3786 (uint32_t)sourceImage.getNumLevels(), // mipLevels
3787 arraySize, // arraySize
3788 vk::VK_SAMPLE_COUNT_1_BIT, // samples
3789 vk::VK_IMAGE_TILING_OPTIMAL, // tiling
3790 readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT, // usage
3791 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
3792 0u, // queueFamilyCount
3793 nullptr, // pQueueFamilyIndices
3794 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
3795 };
3796 vk::Move<vk::VkImage> image(vk::createImage(vki, device, &createInfo));
3797
3798 *outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any);
3799 return image;
3800 }
3801
createImageView(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & sourceImage,vk::VkImage image,uint32_t baseMipLevel,uint32_t baseArraySlice)3802 vk::Move<vk::VkImageView> ImageInstanceImages::createImageView(const vk::DeviceInterface &vki, vk::VkDevice device,
3803 vk::VkImageViewType viewType,
3804 const tcu::TextureLevelPyramid &sourceImage,
3805 vk::VkImage image, uint32_t baseMipLevel,
3806 uint32_t baseArraySlice)
3807 {
3808 const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
3809 const uint32_t viewTypeBaseSlice =
3810 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3811 (6 * baseArraySlice) :
3812 (baseArraySlice);
3813 const uint32_t viewArraySize =
3814 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D) ? (1) :
3815 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (baseLevel.getHeight() - viewTypeBaseSlice) :
3816 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D) ? (1) :
3817 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (baseLevel.getDepth() - viewTypeBaseSlice) :
3818 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3819 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE) ? (6) :
3820 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth() -
3821 viewTypeBaseSlice) // cube: numFaces * numLayers
3822 :
3823 (0);
3824
3825 DE_ASSERT(viewArraySize > 0);
3826
3827 const vk::VkImageSubresourceRange resourceRange = {
3828 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
3829 baseMipLevel, // baseMipLevel
3830 sourceImage.getNumLevels() - baseMipLevel, // mipLevels
3831 viewTypeBaseSlice, // baseArraySlice
3832 viewArraySize, // arraySize
3833 };
3834 const vk::VkImageViewCreateInfo createInfo = {
3835 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
3836 nullptr,
3837 (vk::VkImageViewCreateFlags)0,
3838 image, // image
3839 viewType, // viewType
3840 vk::mapTextureFormat(baseLevel.getFormat()), // format
3841 {vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B,
3842 vk::VK_COMPONENT_SWIZZLE_A}, // channels
3843 resourceRange, // subresourceRange
3844 };
3845 return vk::createImageView(vki, device, &createInfo);
3846 }
3847
populateSourceImage(tcu::TextureLevelPyramid * dst,vk::VkImageViewType viewType,int imageNdx)3848 void ImageInstanceImages::populateSourceImage(tcu::TextureLevelPyramid *dst, vk::VkImageViewType viewType, int imageNdx)
3849 {
3850 const int numLevels = dst->getNumLevels();
3851
3852 for (int level = 0; level < numLevels; ++level)
3853 {
3854 const int width = IMAGE_SIZE >> level;
3855 const int height = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3856 (ARRAY_SIZE) :
3857 (IMAGE_SIZE >> level);
3858 const int depth =
3859 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) :
3860 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (ARRAY_SIZE) :
3861 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3862 (6 * ARRAY_SIZE) :
3863 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (IMAGE_SIZE >> level) :
3864 (1);
3865
3866 dst->allocLevel(level, width, height, depth);
3867
3868 {
3869 const tcu::PixelBufferAccess levelAccess = dst->getLevel(level);
3870
3871 for (int z = 0; z < depth; ++z)
3872 for (int y = 0; y < height; ++y)
3873 for (int x = 0; x < width; ++x)
3874 {
3875 const int gradPos = x + y + z;
3876 const int gradMax = width + height + depth - 3;
3877
3878 int red = 255 * gradPos / gradMax; //!< gradient from 0 -> max (detects large offset errors)
3879 int green =
3880 ((gradPos % 2 == 0) ? (127) : (0)) +
3881 ((gradPos % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
3882 int blue =
3883 (128 * level / numLevels) +
3884 ((imageNdx % 2 == 0) ? 127 : 0); //!< level and image index (detects incorrect lod / image)
3885
3886 DE_ASSERT(de::inRange(red, 0, 255));
3887 DE_ASSERT(de::inRange(green, 0, 255));
3888 DE_ASSERT(de::inRange(blue, 0, 255));
3889
3890 if (imageNdx % 3 == 0)
3891 red = 255 - red;
3892 if (imageNdx % 4 == 0)
3893 green = 255 - green;
3894 if (imageNdx % 5 == 0)
3895 blue = 255 - blue;
3896
3897 levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z);
3898 }
3899 }
3900 }
3901 }
3902
uploadImage(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::Allocator & allocator,vk::VkImage image,vk::VkImageLayout layout,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & data)3903 void ImageInstanceImages::uploadImage(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3904 vk::VkQueue queue, vk::Allocator &allocator, vk::VkImage image,
3905 vk::VkImageLayout layout, vk::VkImageViewType viewType,
3906 const tcu::TextureLevelPyramid &data)
3907 {
3908 const uint32_t arraySize =
3909 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3910 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3911 (6 * (uint32_t)ARRAY_SIZE) :
3912 ((uint32_t)ARRAY_SIZE);
3913 const uint32_t dataBufferSize = getTextureLevelPyramidDataSize(data);
3914 const vk::VkBufferCreateInfo bufferCreateInfo = {
3915 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
3916 nullptr,
3917 0u, // flags
3918 dataBufferSize, // size
3919 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
3920 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
3921 0u, // queueFamilyCount
3922 nullptr, // pQueueFamilyIndices
3923 };
3924
3925 const vk::Unique<vk::VkBuffer> dataBuffer(vk::createBuffer(vki, device, &bufferCreateInfo));
3926 const de::MovePtr<vk::Allocation> dataBufferMemory =
3927 allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible);
3928 std::vector<vk::VkBufferImageCopy> copySlices;
3929 // copy data to buffer
3930 writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, viewType, ©Slices);
3931 flushAlloc(vki, device, *dataBufferMemory);
3932
3933 // copy buffer to image
3934 copyBufferToImage(vki, device, queue, queueFamilyIndex, *dataBuffer, dataBufferSize, copySlices, nullptr,
3935 vk::VK_IMAGE_ASPECT_COLOR_BIT, data.getNumLevels(), arraySize, image, layout);
3936 }
3937
3938 class ImageFetchInstanceImages : private ImageInstanceImages
3939 {
3940 public:
3941 ImageFetchInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3942 vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3943 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
3944 vk::VkImageViewType viewType, uint32_t numLevels, uint32_t baseMipLevel,
3945 uint32_t baseArraySlice);
3946
3947 static tcu::IVec3 getFetchPos(vk::VkImageViewType viewType, uint32_t baseMipLevel, uint32_t baseArraySlice,
3948 int fetchPosNdx);
3949
3950 tcu::Vec4 fetchImageValue(int fetchPosNdx, int setNdx) const;
3951
getSourceImage(int ndx) const3952 inline tcu::TextureLevelPyramid getSourceImage(int ndx) const
3953 {
3954 return m_sourceImage[ndx];
3955 }
getImageView(int ndx) const3956 inline vk::VkImageView getImageView(int ndx) const
3957 {
3958 return **m_imageView[ndx % m_imageView.size()];
3959 }
3960
3961 private:
3962 enum
3963 {
3964 // some arbitrary sample points for all four quadrants
3965 SAMPLE_POINT_0_X = 6,
3966 SAMPLE_POINT_0_Y = 13,
3967 SAMPLE_POINT_0_Z = 49,
3968
3969 SAMPLE_POINT_1_X = 51,
3970 SAMPLE_POINT_1_Y = 40,
3971 SAMPLE_POINT_1_Z = 44,
3972
3973 SAMPLE_POINT_2_X = 42,
3974 SAMPLE_POINT_2_Y = 26,
3975 SAMPLE_POINT_2_Z = 19,
3976
3977 SAMPLE_POINT_3_X = 25,
3978 SAMPLE_POINT_3_Y = 25,
3979 SAMPLE_POINT_3_Z = 18,
3980 };
3981
3982 const ShaderInputInterface m_shaderInterface;
3983 };
3984
ImageFetchInstanceImages(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t numLevels,uint32_t baseMipLevel,uint32_t baseArraySlice)3985 ImageFetchInstanceImages::ImageFetchInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3986 uint32_t queueFamilyIndex, vk::VkQueue queue,
3987 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3988 DescriptorSetCount descriptorSetCount,
3989 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
3990 uint32_t numLevels, uint32_t baseMipLevel, uint32_t baseArraySlice)
3991 : ImageInstanceImages(vki, device, queueFamilyIndex, queue, allocator, descriptorType, viewType,
3992 getDescriptorSetCount(descriptorSetCount) *
3993 getInterfaceNumResources(shaderInterface), // numImages
3994 numLevels, baseMipLevel, baseArraySlice)
3995 , m_shaderInterface(shaderInterface)
3996 {
3997 }
3998
isImageViewTypeArray(vk::VkImageViewType type)3999 bool isImageViewTypeArray(vk::VkImageViewType type)
4000 {
4001 return type == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
4002 type == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
4003 }
4004
getFetchPos(vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,int fetchPosNdx)4005 tcu::IVec3 ImageFetchInstanceImages::getFetchPos(vk::VkImageViewType viewType, uint32_t baseMipLevel,
4006 uint32_t baseArraySlice, int fetchPosNdx)
4007 {
4008 const tcu::IVec3 fetchPositions[4] = {
4009 tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z),
4010 tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z),
4011 tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z),
4012 tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z),
4013 };
4014 const tcu::IVec3 coord = de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
4015 const uint32_t imageSize = (uint32_t)IMAGE_SIZE >> baseMipLevel;
4016 const uint32_t arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
4017
4018 switch (viewType)
4019 {
4020 case vk::VK_IMAGE_VIEW_TYPE_1D:
4021 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
4022 return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0);
4023 case vk::VK_IMAGE_VIEW_TYPE_2D:
4024 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
4025 return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize);
4026 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
4027 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
4028 return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6));
4029 case vk::VK_IMAGE_VIEW_TYPE_3D:
4030 return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize);
4031 default:
4032 DE_FATAL("Impossible");
4033 return tcu::IVec3();
4034 }
4035 }
4036
fetchImageValue(int fetchPosNdx,int setNdx) const4037 tcu::Vec4 ImageFetchInstanceImages::fetchImageValue(int fetchPosNdx, int setNdx) const
4038 {
4039 DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4));
4040
4041 const tcu::TextureLevelPyramid &fetchSrcA = getSourceImage(setNdx * getInterfaceNumResources(m_shaderInterface));
4042 const tcu::TextureLevelPyramid &fetchSrcB =
4043 (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ?
4044 fetchSrcA :
4045 getSourceImage(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
4046 const tcu::TextureLevelPyramid &fetchSrc =
4047 ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB
4048 tcu::IVec3 fetchPos = getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
4049
4050 // add base array layer into the appropriate coordinate, based on the view type
4051 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
4052 fetchPos.z() += 6 * m_baseArraySlice;
4053 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
4054 fetchPos.y() += m_baseArraySlice;
4055 else
4056 fetchPos.z() += m_baseArraySlice;
4057
4058 return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z());
4059 }
4060
4061 class ImageFetchRenderInstance : public SingleCmdRenderInstance
4062 {
4063 public:
4064 ImageFetchRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
4065 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4066 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
4067 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
4068 uint32_t baseArraySlice, const bool bind2);
4069
4070 private:
4071 static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
4072 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4073 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
4074 DescriptorUpdateMethod updateMethod);
4075
4076 static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
4077 const vk::DeviceInterface &vki, vk::VkDevice device,
4078 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
4079
4080 static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
4081 vk::VkDescriptorType descriptorType,
4082 DescriptorSetCount descriptorSetCount,
4083 ShaderInputInterface shaderInterface);
4084
4085 static std::vector<DescriptorSetHandleSp> createDescriptorSets(
4086 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
4087 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4088 ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
4089 vk::VkDescriptorPool pool, const ImageFetchInstanceImages &images,
4090 vk::DescriptorSetUpdateBuilder &updateBuilder,
4091 #ifndef CTS_USES_VULKANSC
4092 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
4093 #endif
4094 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
4095
4096 static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
4097 vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
4098 vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool, vk::VkImageView viewA,
4099 vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4100 vk::DescriptorSetUpdateBuilder &updateBuilder,
4101 std::vector<uint32_t> &descriptorsPerSet,
4102 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
4103
4104 #ifndef CTS_USES_VULKANSC
4105 static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
4106 vk::VkDescriptorType descriptorType,
4107 ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout,
4108 vk::VkDescriptorPool pool, vk::VkImageView viewA, vk::VkImageView viewB,
4109 vk::VkDescriptorSet descriptorSet,
4110 std::vector<UpdateTemplateHandleSp> &updateTemplates,
4111 std::vector<RawUpdateRegistry> ®istry, bool withPush = false,
4112 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
4113 #endif
4114
4115 void logTestPlan(void) const;
4116 vk::VkPipelineLayout getPipelineLayout(void) const;
4117 void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
4118 tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
4119
4120 enum
4121 {
4122 RENDER_SIZE = 128,
4123 };
4124
4125 const DescriptorUpdateMethod m_updateMethod;
4126 const vk::VkDescriptorType m_descriptorType;
4127 const DescriptorSetCount m_descriptorSetCount;
4128 const vk::VkShaderStageFlags m_stageFlags;
4129 const vk::VkShaderStageFlags m_existingStages;
4130 const ShaderInputInterface m_shaderInterface;
4131 const vk::VkImageViewType m_viewType;
4132 const uint32_t m_numLevels;
4133 const uint32_t m_baseMipLevel;
4134 const uint32_t m_baseArraySlice;
4135
4136 #ifndef CTS_USES_VULKANSC
4137 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
4138 std::vector<RawUpdateRegistry> m_updateRegistry;
4139 #endif
4140 vk::DescriptorSetUpdateBuilder m_updateBuilder;
4141 const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
4142 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
4143 const ImageFetchInstanceImages m_images;
4144 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
4145 std::vector<uint32_t> m_descriptorsPerSet;
4146 const std::vector<DescriptorSetHandleSp> m_descriptorSets;
4147 };
4148
ImageFetchRenderInstance(vkt::Context & context,DescriptorUpdateMethod updateMethod,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,const bool bind2)4149 ImageFetchRenderInstance::ImageFetchRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
4150 bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
4151 DescriptorSetCount descriptorSetCount,
4152 vk::VkShaderStageFlags stageFlags,
4153 vk::VkShaderStageFlags existingStages,
4154 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
4155 uint32_t baseMipLevel, uint32_t baseArraySlice, const bool bind2)
4156 : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
4157 , m_updateMethod(updateMethod)
4158 , m_descriptorType(descriptorType)
4159 , m_descriptorSetCount(descriptorSetCount)
4160 , m_stageFlags(stageFlags)
4161 , m_existingStages(existingStages)
4162 , m_shaderInterface(shaderInterface)
4163 , m_viewType(viewType)
4164 , m_numLevels(baseMipLevel + 1u)
4165 , m_baseMipLevel(baseMipLevel)
4166 , m_baseArraySlice(baseArraySlice)
4167 #ifndef CTS_USES_VULKANSC
4168 , m_updateTemplates()
4169 , m_updateRegistry()
4170 #endif
4171 , m_updateBuilder()
4172 , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
4173 m_shaderInterface, m_stageFlags, m_updateMethod))
4174 , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
4175 , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
4176 m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice)
4177 , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
4178 , m_descriptorsPerSet()
4179 , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
4180 m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool, m_images,
4181 m_updateBuilder,
4182 #ifndef CTS_USES_VULKANSC
4183 m_updateTemplates, m_updateRegistry,
4184 #endif
4185 m_descriptorsPerSet, *m_pipelineLayout))
4186 {
4187 }
4188
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)4189 std::vector<DescriptorSetLayoutHandleSp> ImageFetchRenderInstance::createDescriptorSetLayouts(
4190 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4191 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
4192 DescriptorUpdateMethod updateMethod)
4193 {
4194 #ifdef CTS_USES_VULKANSC
4195 DE_UNREF(updateMethod);
4196 #endif
4197 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
4198 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
4199
4200 #ifndef CTS_USES_VULKANSC
4201 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
4202 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4203 {
4204 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
4205 }
4206 #endif
4207
4208 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
4209 {
4210 vk::DescriptorSetLayoutBuilder builder;
4211
4212 switch (shaderInterface)
4213 {
4214 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4215 builder.addSingleBinding(descriptorType, stageFlags);
4216 break;
4217
4218 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4219 builder.addSingleBinding(descriptorType, stageFlags);
4220 builder.addSingleBinding(descriptorType, stageFlags);
4221 break;
4222
4223 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4224 builder.addSingleIndexedBinding(descriptorType, stageFlags, 0u);
4225 builder.addSingleIndexedBinding(descriptorType, stageFlags, 2u);
4226 break;
4227
4228 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4229 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
4230 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
4231 break;
4232
4233 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4234 builder.addArrayBinding(descriptorType, 2u, stageFlags);
4235 break;
4236
4237 default:
4238 DE_FATAL("Impossible");
4239 }
4240
4241 vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
4242 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
4243
4244 // Add an empty descriptor set layout between sets 0 and 2
4245 if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
4246 {
4247 vk::DescriptorSetLayoutBuilder emptyBuilder;
4248 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
4249 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
4250 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
4251 }
4252 }
4253 return descriptorSetLayouts;
4254 }
4255
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)4256 vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout(
4257 const vk::DeviceInterface &vki, vk::VkDevice device,
4258 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
4259 {
4260 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
4261 for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
4262 layoutHandles.push_back(**descriptorSetLayout[setNdx]);
4263
4264 const vk::VkPipelineLayoutCreateInfo createInfo = {
4265 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4266 nullptr,
4267 (vk::VkPipelineLayoutCreateFlags)0,
4268 (uint32_t)layoutHandles.size(), // descriptorSetCount
4269 &layoutHandles.front(), // pSetLayouts
4270 0u, // pushConstantRangeCount
4271 nullptr, // pPushConstantRanges
4272 };
4273 return vk::createPipelineLayout(vki, device, &createInfo);
4274 }
4275
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)4276 vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
4277 vk::VkDevice device,
4278 vk::VkDescriptorType descriptorType,
4279 DescriptorSetCount descriptorSetCount,
4280 ShaderInputInterface shaderInterface)
4281 {
4282 return vk::DescriptorPoolBuilder()
4283 .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
4284 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
4285 getDescriptorSetCount(descriptorSetCount));
4286 }
4287
createDescriptorSets(const vk::DeviceInterface & vki,DescriptorUpdateMethod updateMethod,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayouts,vk::VkDescriptorPool pool,const ImageFetchInstanceImages & images,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & updateRegistry,std::vector<uint32_t> & descriptorsPerSet,vk::VkPipelineLayout pipelineLayout)4288 std::vector<DescriptorSetHandleSp> ImageFetchRenderInstance::createDescriptorSets(
4289 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
4290 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
4291 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool,
4292 const ImageFetchInstanceImages &images, vk::DescriptorSetUpdateBuilder &updateBuilder,
4293 #ifndef CTS_USES_VULKANSC
4294 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
4295 #endif
4296 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
4297 {
4298 #ifdef CTS_USES_VULKANSC
4299 DE_UNREF(pipelineLayout);
4300 #endif
4301 std::vector<DescriptorSetHandleSp> descriptorSets;
4302
4303 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
4304 {
4305 vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
4306
4307 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
4308 pool, 1u, &layout};
4309
4310 vk::VkImageView viewA = images.getImageView(setNdx * getInterfaceNumResources(shaderInterface));
4311 vk::VkImageView viewB = images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1);
4312
4313 vk::Move<vk::VkDescriptorSet> descriptorSet;
4314 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
4315 updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4316 {
4317 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
4318 }
4319 else
4320 {
4321 descriptorSet = vk::Move<vk::VkDescriptorSet>();
4322 }
4323
4324 #ifndef CTS_USES_VULKANSC
4325 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
4326 {
4327 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB,
4328 *descriptorSet, updateTemplates, updateRegistry);
4329 }
4330 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4331 {
4332 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB,
4333 *descriptorSet, updateTemplates, updateRegistry, true, pipelineLayout);
4334 }
4335 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4336 {
4337 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
4338 updateBuilder, descriptorsPerSet, updateMethod);
4339 }
4340 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4341 #endif
4342 {
4343 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
4344 updateBuilder, descriptorsPerSet);
4345 }
4346
4347 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
4348 }
4349 return descriptorSets;
4350 }
4351
writeDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkImageView viewA,vk::VkImageView viewB,vk::VkDescriptorSet descriptorSet,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)4352 void ImageFetchRenderInstance::writeDescriptorSet(
4353 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4354 ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
4355 vk::VkImageView viewA, vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4356 vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
4357 DescriptorUpdateMethod updateMethod)
4358 {
4359 DE_UNREF(layout);
4360 DE_UNREF(pool);
4361 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(descriptorType);
4362 const vk::VkDescriptorImageInfo imageInfos[2] = {
4363 makeDescriptorImageInfo(viewA, imageLayout),
4364 makeDescriptorImageInfo(viewB, imageLayout),
4365 };
4366 uint32_t numDescriptors = 0u;
4367
4368 switch (shaderInterface)
4369 {
4370 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4371 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4372 &imageInfos[0]);
4373 numDescriptors++;
4374 break;
4375
4376 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4377 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4378 &imageInfos[0]);
4379 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
4380 &imageInfos[1]);
4381 numDescriptors += 2;
4382 break;
4383
4384 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4385 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4386 &imageInfos[0]);
4387 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
4388 &imageInfos[1]);
4389 numDescriptors += 2;
4390 break;
4391
4392 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4393 updateBuilder.writeSingle(descriptorSet,
4394 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
4395 descriptorType, &imageInfos[0]);
4396 updateBuilder.writeSingle(descriptorSet,
4397 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
4398 descriptorType, &imageInfos[1]);
4399 numDescriptors += 2;
4400 break;
4401
4402 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4403 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4404 2u, imageInfos);
4405 numDescriptors++;
4406 break;
4407
4408 default:
4409 DE_FATAL("Impossible");
4410 }
4411
4412 descriptorsPerSet.push_back(numDescriptors);
4413
4414 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4415 {
4416 updateBuilder.update(vki, device);
4417 updateBuilder.clear();
4418 }
4419 }
4420
4421 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkImageView viewA,vk::VkImageView viewB,vk::VkDescriptorSet descriptorSet,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)4422 void ImageFetchRenderInstance::writeDescriptorSetWithTemplate(
4423 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4424 ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
4425 vk::VkImageView viewA, vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4426 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry, bool withPush,
4427 vk::VkPipelineLayout pipelineLayout)
4428 {
4429 DE_UNREF(pool);
4430 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
4431 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
4432 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
4433 nullptr,
4434 0,
4435 0, // updateCount
4436 nullptr, // pUpdates
4437 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
4438 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
4439 layout,
4440 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4441 pipelineLayout,
4442 0};
4443 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(descriptorType);
4444 const vk::VkDescriptorImageInfo imageInfos[2] = {
4445 makeDescriptorImageInfo(viewA, imageLayout),
4446 makeDescriptorImageInfo(viewB, imageLayout),
4447 };
4448
4449 RawUpdateRegistry updateRegistry;
4450
4451 updateRegistry.addWriteObject(imageInfos[0]);
4452 updateRegistry.addWriteObject(imageInfos[1]);
4453
4454 switch (shaderInterface)
4455 {
4456 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4457 updateEntries.push_back(
4458 createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4459 break;
4460
4461 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4462 updateEntries.push_back(
4463 createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4464 updateEntries.push_back(
4465 createTemplateBinding(1, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
4466 break;
4467
4468 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4469 updateEntries.push_back(
4470 createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4471 updateEntries.push_back(
4472 createTemplateBinding(2, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
4473 break;
4474
4475 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4476 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
4477 updateRegistry.getWriteObjectOffset(0), 0));
4478 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
4479 updateRegistry.getWriteObjectOffset(1), 0));
4480 break;
4481
4482 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4483 updateEntries.push_back(createTemplateBinding(0, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
4484 sizeof(imageInfos[0])));
4485 break;
4486
4487 default:
4488 DE_FATAL("Impossible");
4489 }
4490
4491 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
4492 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
4493
4494 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
4495 vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
4496 updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
4497 registry.push_back(updateRegistry);
4498
4499 if (!withPush)
4500 {
4501 vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
4502 registry.back().getRawPointer());
4503 }
4504 }
4505 #endif
4506
logTestPlan(void) const4507 void ImageFetchRenderInstance::logTestPlan(void) const
4508 {
4509 std::ostringstream msg;
4510
4511 msg << "Rendering 2x2 grid.\n"
4512 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
4513 "Multiple descriptor sets. ")
4514 << "Each descriptor set contains "
4515 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4516 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4517 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
4518 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
4519 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4520 nullptr)
4521 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
4522 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4523
4524 if (m_baseMipLevel)
4525 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4526 if (m_baseArraySlice)
4527 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4528
4529 if (m_stageFlags == 0u)
4530 {
4531 msg << "Descriptors are not accessed in any shader stage.\n";
4532 }
4533 else
4534 {
4535 msg << "Color in each cell is fetched using the descriptor(s):\n";
4536
4537 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4538 {
4539 msg << "Test sample " << resultNdx << ": fetching at position "
4540 << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4541
4542 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4543 {
4544 const int srcResourceNdx = (resultNdx % 2); // ABAB source
4545 msg << " from descriptor " << srcResourceNdx;
4546 }
4547
4548 msg << "\n";
4549 }
4550
4551 msg << "Descriptors are accessed in {"
4552 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
4553 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
4554 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
4555 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
4556 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.";
4557 }
4558
4559 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
4560 }
4561
getPipelineLayout(void) const4562 vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout(void) const
4563 {
4564 return *m_pipelineLayout;
4565 }
4566
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const4567 void ImageFetchRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
4568 {
4569 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
4570 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4571 {
4572 std::vector<vk::VkDescriptorSet> sets;
4573 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4574 sets.push_back(**m_descriptorSets[setNdx]);
4575
4576 switch (m_descriptorSetCount)
4577 {
4578 case DESCRIPTOR_SET_COUNT_SINGLE:
4579 case DESCRIPTOR_SET_COUNT_MULTIPLE:
4580 {
4581 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4582 getPipelineLayout(), 0, (int)sets.size(), &sets.front(), 0, nullptr, m_bind2);
4583 break;
4584 }
4585 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
4586 {
4587 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4588 {
4589 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
4590 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4591 getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], 0, nullptr, m_bind2);
4592 }
4593 break;
4594 }
4595 default:
4596 DE_FATAL("Impossible");
4597 }
4598 }
4599 #ifndef CTS_USES_VULKANSC
4600 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4601 {
4602 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4603 m_vki.cmdPushDescriptorSetWithTemplate(cmd, **m_updateTemplates[setNdx], getPipelineLayout(),
4604 getDescriptorSetNdx(m_descriptorSetCount, setNdx),
4605 (const void *)m_updateRegistry[setNdx].getRawPointer());
4606 }
4607 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4608 {
4609 uint32_t descriptorNdx = 0u;
4610 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4611 {
4612 const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
4613 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout,
4614 getDescriptorSetNdx(m_descriptorSetCount, setNdx), descriptorNdx,
4615 numDescriptors);
4616 descriptorNdx += numDescriptors;
4617 }
4618 }
4619 #endif
4620
4621 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
4622 }
4623
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const4624 tcu::TestStatus ImageFetchRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
4625 {
4626 const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
4627 const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
4628 const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
4629 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
4630
4631 tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
4632
4633 tcu::Vec4 sample0 = tcu::Vec4(0.0f);
4634 tcu::Vec4 sample1 = tcu::Vec4(0.0f);
4635 tcu::Vec4 sample2 = tcu::Vec4(0.0f);
4636 tcu::Vec4 sample3 = tcu::Vec4(0.0f);
4637
4638 for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
4639 {
4640 sample0 += (!doFetch) ? (yellow) : (m_images.fetchImageValue(0, setNdx));
4641 sample1 += (!doFetch) ? (green) : (m_images.fetchImageValue(1, setNdx));
4642 sample2 += (!doFetch) ? (green) : (m_images.fetchImageValue(2, setNdx));
4643 sample3 += (!doFetch) ? (yellow) : (m_images.fetchImageValue(3, setNdx));
4644 }
4645
4646 if (numDescriptorSets > 1)
4647 {
4648 sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
4649 sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
4650 sample2 = sample2 / tcu::Vec4(float(numDescriptorSets));
4651 sample3 = sample3 / tcu::Vec4(float(numDescriptorSets));
4652 }
4653
4654 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
4655
4656 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
4657 result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
4658 return tcu::TestStatus::fail("Image verification failed");
4659 else
4660 return tcu::TestStatus::pass("Pass");
4661 }
4662
4663 class ImageFetchComputeInstance : public vkt::TestInstance
4664 {
4665 public:
4666 ImageFetchComputeInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
4667 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4668 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
4669 uint32_t baseArraySlice, const bool bind2);
4670
4671 private:
4672 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
4673 vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
4674 vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
4675 uint32_t setNdx);
4676 void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
4677 #ifndef CTS_USES_VULKANSC
4678 void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
4679 uint32_t setNdx, bool withPush = false,
4680 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
4681 #endif
4682
4683 tcu::TestStatus iterate(void);
4684 void logTestPlan(void) const;
4685 tcu::TestStatus testResourceAccess(void);
4686
4687 const DescriptorUpdateMethod m_updateMethod;
4688 const vk::VkDescriptorType m_descriptorType;
4689 const DescriptorSetCount m_descriptorSetCount;
4690 const ShaderInputInterface m_shaderInterface;
4691 const vk::VkImageViewType m_viewType;
4692 const uint32_t m_numLevels;
4693 const uint32_t m_baseMipLevel;
4694 const uint32_t m_baseArraySlice;
4695 const bool m_bind2;
4696 #ifndef CTS_USES_VULKANSC
4697 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
4698 #endif
4699 const vk::DeviceInterface &m_vki;
4700 const vk::VkDevice m_device;
4701 const vk::VkQueue m_queue;
4702 const uint32_t m_queueFamilyIndex;
4703 vk::Allocator &m_allocator;
4704 const ComputeInstanceResultBuffer m_result;
4705 const ImageFetchInstanceImages m_images;
4706 #ifndef CTS_USES_VULKANSC
4707 std::vector<RawUpdateRegistry> m_updateRegistry;
4708 #endif
4709 vk::DescriptorSetUpdateBuilder m_updateBuilder;
4710 std::vector<uint32_t> m_descriptorsPerSet;
4711 };
4712
ImageFetchComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,const bool bind2)4713 ImageFetchComputeInstance::ImageFetchComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
4714 vk::VkDescriptorType descriptorType,
4715 DescriptorSetCount descriptorSetCount,
4716 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
4717 uint32_t baseMipLevel, uint32_t baseArraySlice, const bool bind2)
4718 : vkt::TestInstance(context)
4719 , m_updateMethod(updateMethod)
4720 , m_descriptorType(descriptorType)
4721 , m_descriptorSetCount(descriptorSetCount)
4722 , m_shaderInterface(shaderInterface)
4723 , m_viewType(viewType)
4724 , m_numLevels(baseMipLevel + 1u)
4725 , m_baseMipLevel(baseMipLevel)
4726 , m_baseArraySlice(baseArraySlice)
4727 , m_bind2(bind2)
4728 #ifndef CTS_USES_VULKANSC
4729 , m_updateTemplates()
4730 #endif
4731 , m_vki(context.getDeviceInterface())
4732 , m_device(context.getDevice())
4733 , m_queue(context.getUniversalQueue())
4734 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
4735 , m_allocator(context.getDefaultAllocator())
4736 , m_result(m_vki, m_device, m_allocator)
4737 , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
4738 m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice)
4739 #ifndef CTS_USES_VULKANSC
4740 , m_updateRegistry()
4741 #endif
4742 , m_updateBuilder()
4743 , m_descriptorsPerSet()
4744 {
4745 }
4746
createDescriptorSetLayout(uint32_t setNdx) const4747 vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
4748 {
4749 vk::DescriptorSetLayoutBuilder builder;
4750 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
4751 uint32_t binding = 0;
4752
4753 #ifndef CTS_USES_VULKANSC
4754 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
4755 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4756 {
4757 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
4758 }
4759 #endif
4760
4761 if (setNdx == 0)
4762 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
4763 binding++);
4764
4765 switch (m_shaderInterface)
4766 {
4767 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4768 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4769 break;
4770
4771 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4772 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4773 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4774 break;
4775
4776 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4777 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding);
4778 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2);
4779 break;
4780
4781 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4782 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
4783 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
4784 break;
4785
4786 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4787 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4788 break;
4789
4790 default:
4791 DE_FATAL("Impossible");
4792 }
4793
4794 return builder.build(m_vki, m_device, extraFlags);
4795 }
4796
createDescriptorPool(void) const4797 vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool(void) const
4798 {
4799 return vk::DescriptorPoolBuilder()
4800 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4801 .addType(m_descriptorType,
4802 getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
4803 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
4804 getDescriptorSetCount(m_descriptorSetCount));
4805 }
4806
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx)4807 vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
4808 vk::VkDescriptorSetLayout layout,
4809 uint32_t setNdx)
4810 {
4811 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
4812 pool, 1u, &layout};
4813
4814 vk::Move<vk::VkDescriptorSet> descriptorSet;
4815 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
4816 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4817 {
4818 descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
4819 }
4820 else
4821 {
4822 descriptorSet = vk::Move<vk::VkDescriptorSet>();
4823 }
4824
4825 #ifndef CTS_USES_VULKANSC
4826 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
4827 {
4828 writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx);
4829 }
4830 else
4831 #endif
4832 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4833 {
4834 writeDescriptorSet(*descriptorSet, setNdx);
4835 }
4836
4837 return descriptorSet;
4838 }
4839
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)4840 void ImageFetchComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
4841 {
4842 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
4843 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4844 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(m_descriptorType);
4845 const vk::VkDescriptorImageInfo imageInfos[2] = {
4846 makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
4847 imageLayout),
4848 makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
4849 imageLayout),
4850 };
4851
4852 uint32_t binding = 0u;
4853 uint32_t numDescriptors = 0u;
4854
4855 // result
4856 if (setNdx == 0)
4857 {
4858 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4859 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4860 numDescriptors++;
4861 }
4862
4863 // images
4864 switch (m_shaderInterface)
4865 {
4866 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4867 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4868 m_descriptorType, &imageInfos[0]);
4869 numDescriptors++;
4870 break;
4871
4872 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4873 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4874 m_descriptorType, &imageInfos[0]);
4875 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4876 m_descriptorType, &imageInfos[1]);
4877 numDescriptors += 2;
4878 break;
4879
4880 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4881 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
4882 m_descriptorType, &imageInfos[0]);
4883 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
4884 m_descriptorType, &imageInfos[1]);
4885 numDescriptors += 2;
4886 break;
4887
4888 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4889 m_updateBuilder.writeSingle(descriptorSet,
4890 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
4891 m_descriptorType, &imageInfos[0]);
4892 m_updateBuilder.writeSingle(descriptorSet,
4893 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
4894 m_descriptorType, &imageInfos[1]);
4895 numDescriptors += 2;
4896 break;
4897
4898 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4899 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4900 m_descriptorType, 2u, imageInfos);
4901 numDescriptors++;
4902 break;
4903
4904 default:
4905 DE_FATAL("Impossible");
4906 }
4907
4908 m_descriptorsPerSet.push_back(numDescriptors);
4909
4910 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4911 {
4912 m_updateBuilder.update(m_vki, m_device);
4913 m_updateBuilder.clear();
4914 }
4915 }
4916
4917 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)4918 void ImageFetchComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
4919 vk::VkDescriptorSetLayout layout, uint32_t setNdx,
4920 bool withPush, vk::VkPipelineLayout pipelineLayout)
4921 {
4922 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
4923 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4924 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(m_descriptorType);
4925 const vk::VkDescriptorImageInfo imageInfos[2] = {
4926 makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
4927 imageLayout),
4928 makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
4929 imageLayout),
4930 };
4931 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
4932 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
4933 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
4934 nullptr,
4935 0,
4936 0, // updateCount
4937 nullptr, // pUpdates
4938 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
4939 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
4940 layout,
4941 vk::VK_PIPELINE_BIND_POINT_COMPUTE,
4942 pipelineLayout,
4943 setNdx};
4944
4945 uint32_t binding = 0u;
4946 uint32_t offset = 0u;
4947 RawUpdateRegistry updateRegistry;
4948
4949 if (setNdx == 0)
4950 updateRegistry.addWriteObject(resultInfo);
4951
4952 updateRegistry.addWriteObject(imageInfos[0]);
4953 updateRegistry.addWriteObject(imageInfos[1]);
4954
4955 // result
4956 if (setNdx == 0)
4957 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
4958 updateRegistry.getWriteObjectOffset(offset++), 0));
4959
4960 // images
4961 switch (m_shaderInterface)
4962 {
4963 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4964 updateEntries.push_back(
4965 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4966 break;
4967
4968 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4969 updateEntries.push_back(
4970 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4971 updateEntries.push_back(
4972 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4973 break;
4974
4975 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4976 updateEntries.push_back(
4977 createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4978 updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
4979 updateRegistry.getWriteObjectOffset(offset++), 0));
4980 break;
4981
4982 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4983 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
4984 updateRegistry.getWriteObjectOffset(offset++), 0));
4985 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
4986 updateRegistry.getWriteObjectOffset(offset++), 0));
4987 break;
4988
4989 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4990 updateEntries.push_back(createTemplateBinding(
4991 binding++, 0, 2, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), sizeof(imageInfos[0])));
4992 break;
4993
4994 default:
4995 DE_FATAL("Impossible");
4996 }
4997
4998 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
4999 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
5000
5001 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
5002 vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
5003 m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
5004 m_updateRegistry.push_back(updateRegistry);
5005
5006 if (!withPush)
5007 {
5008 m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
5009 m_updateRegistry.back().getRawPointer());
5010 }
5011 }
5012 #endif
5013
iterate(void)5014 tcu::TestStatus ImageFetchComputeInstance::iterate(void)
5015 {
5016 logTestPlan();
5017 return testResourceAccess();
5018 }
5019
logTestPlan(void) const5020 void ImageFetchComputeInstance::logTestPlan(void) const
5021 {
5022 std::ostringstream msg;
5023
5024 msg << "Fetching 4 values from image in compute shader.\n"
5025 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
5026 "Multiple descriptor sets. ")
5027 << "Each descriptor set contains "
5028 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
5029 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
5030 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
5031 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
5032 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
5033 nullptr)
5034 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5035 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
5036
5037 if (m_baseMipLevel)
5038 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
5039 if (m_baseArraySlice)
5040 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
5041
5042 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5043 {
5044 msg << "Test sample " << resultNdx << ": fetch at position "
5045 << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
5046
5047 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5048 {
5049 const int srcResourceNdx = (resultNdx % 2); // ABAB source
5050 msg << " from descriptor " << srcResourceNdx;
5051 }
5052
5053 msg << "\n";
5054 }
5055
5056 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
5057 }
5058
testResourceAccess(void)5059 tcu::TestStatus ImageFetchComputeInstance::testResourceAccess(void)
5060 {
5061 const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
5062 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
5063 std::vector<DescriptorSetHandleSp> descriptorSets;
5064 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
5065 std::vector<vk::VkDescriptorSet> setHandles;
5066
5067 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5068 {
5069 vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
5070 vk::Move<vk::VkDescriptorSet> set = createDescriptorSet(*descriptorPool, *layout, setNdx);
5071
5072 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
5073 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
5074
5075 layoutHandles.push_back(**descriptorSetLayouts.back());
5076 setHandles.push_back(**descriptorSets.back());
5077
5078 // Add an empty descriptor set layout between sets 0 and 2
5079 if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
5080 {
5081 vk::DescriptorSetLayoutBuilder emptyBuilder;
5082 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
5083 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
5084
5085 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
5086 layoutHandles.push_back(**descriptorSetLayouts.back());
5087 }
5088 }
5089
5090 const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
5091 &layoutHandles.front());
5092 const uint32_t *const dynamicOffsets = nullptr;
5093 const int numDynamicOffsets = 0;
5094 const vk::VkBufferMemoryBarrier *const preBarriers = nullptr;
5095 const int numPreBarriers = 0;
5096 const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
5097 const int numPostBarriers = 1;
5098
5099 const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
5100 tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
5101 numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
5102 postBarriers, m_bind2);
5103
5104 tcu::Vec4 results[4];
5105 bool anyResultSet = false;
5106 bool allResultsOk = true;
5107
5108 #ifndef CTS_USES_VULKANSC
5109 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5110 {
5111 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5112 writeDescriptorSetWithTemplate(VK_NULL_HANDLE, layoutHandles[setNdx], setNdx, true,
5113 pipeline.getPipelineLayout());
5114
5115 compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
5116 }
5117 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5118 {
5119 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5120 writeDescriptorSet(VK_NULL_HANDLE, setNdx);
5121
5122 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
5123 }
5124 else
5125 #endif
5126 {
5127 compute.submitAndWait(m_queueFamilyIndex, m_queue);
5128 }
5129 m_result.readResultContentsTo(&results);
5130
5131 // verify
5132 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5133 {
5134 const tcu::Vec4 result = results[resultNdx];
5135
5136 tcu::Vec4 reference = tcu::Vec4(0.0f);
5137 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5138 reference += m_images.fetchImageValue(resultNdx, setNdx);
5139
5140 if (getDescriptorSetCount(m_descriptorSetCount) > 1)
5141 reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
5142
5143 const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
5144
5145 if (result != tcu::Vec4(-1.0f))
5146 anyResultSet = true;
5147
5148 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
5149 {
5150 allResultsOk = false;
5151
5152 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test sample " << resultNdx << ": Expected "
5153 << reference << ", got " << result << tcu::TestLog::EndMessage;
5154 }
5155 }
5156
5157 // read back and verify
5158 if (allResultsOk)
5159 return tcu::TestStatus::pass("Pass");
5160 else if (anyResultSet)
5161 return tcu::TestStatus::fail("Invalid result values");
5162 else
5163 {
5164 m_context.getTestContext().getLog()
5165 << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
5166 return tcu::TestStatus::fail("Result buffer was not written to");
5167 }
5168 }
5169
5170 class ImageSampleInstanceImages : private ImageInstanceImages
5171 {
5172 public:
5173 ImageSampleInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
5174 vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
5175 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
5176 vk::VkImageViewType viewType, uint32_t numLevels, uint32_t baseMipLevel,
5177 uint32_t baseArraySlice, bool immutable);
5178
5179 static std::vector<tcu::Sampler> getRefSamplers(DescriptorSetCount descriptorSetCount,
5180 ShaderInputInterface shaderInterface);
5181
5182 static std::vector<SamplerHandleSp> getSamplers(const vk::DeviceInterface &vki, vk::VkDevice device,
5183 std::vector<tcu::Sampler> &refSamplers,
5184 const tcu::TextureFormat imageFormat);
5185
5186 static tcu::Vec4 getSamplePos(vk::VkImageViewType viewType, uint32_t baseMipLevel, uint32_t baseArraySlice,
5187 int samplePosNdx);
5188 tcu::Vec4 fetchSampleValue(int samplePosNdx, int setNdx) const;
5189
getSourceImage(int ndx) const5190 inline tcu::TextureLevelPyramid getSourceImage(int ndx) const
5191 {
5192 return m_sourceImage[ndx % m_sourceImage.size()];
5193 }
getImageView(int ndx) const5194 inline vk::VkImageView getImageView(int ndx) const
5195 {
5196 return **m_imageView[ndx % m_imageView.size()];
5197 }
getRefSampler(int ndx) const5198 inline tcu::Sampler getRefSampler(int ndx) const
5199 {
5200 return m_refSampler[ndx % m_refSampler.size()];
5201 }
getSampler(int ndx) const5202 inline vk::VkSampler getSampler(int ndx) const
5203 {
5204 return **m_sampler[ndx % m_sampler.size()];
5205 }
isImmutable(void) const5206 inline bool isImmutable(void) const
5207 {
5208 return m_isImmutable;
5209 }
5210
5211 private:
5212 static int getNumImages(vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5213 ShaderInputInterface shaderInterface);
5214 static tcu::Sampler createRefSampler(int ndx);
5215 static vk::Move<vk::VkSampler> createSampler(const vk::DeviceInterface &vki, vk::VkDevice device,
5216 const tcu::Sampler &sampler, const tcu::TextureFormat &format);
5217
5218 static tcu::Texture1DArrayView getRef1DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5219 uint32_t baseArraySlice,
5220 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5221 static tcu::Texture2DArrayView getRef2DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5222 uint32_t baseArraySlice,
5223 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5224 static tcu::Texture3DView getRef3DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5225 uint32_t baseArraySlice,
5226 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5227 static tcu::TextureCubeArrayView getRefCubeView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5228 uint32_t baseArraySlice,
5229 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5230
5231 const vk::VkDescriptorType m_descriptorType;
5232 const ShaderInputInterface m_shaderInterface;
5233 const bool m_isImmutable;
5234
5235 std::vector<tcu::Sampler> m_refSampler;
5236 std::vector<SamplerHandleSp> m_sampler;
5237 };
5238
ImageSampleInstanceImages(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t numLevels,uint32_t baseMipLevel,uint32_t baseArraySlice,bool immutable)5239 ImageSampleInstanceImages::ImageSampleInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device,
5240 uint32_t queueFamilyIndex, vk::VkQueue queue,
5241 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
5242 DescriptorSetCount descriptorSetCount,
5243 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
5244 uint32_t numLevels, uint32_t baseMipLevel, uint32_t baseArraySlice,
5245 bool immutable)
5246 : ImageInstanceImages(vki, device, queueFamilyIndex, queue, allocator, descriptorType, viewType,
5247 getNumImages(descriptorType, descriptorSetCount, shaderInterface), numLevels, baseMipLevel,
5248 baseArraySlice)
5249 , m_descriptorType(descriptorType)
5250 , m_shaderInterface(shaderInterface)
5251 , m_isImmutable(immutable)
5252 , m_refSampler(getRefSamplers(descriptorSetCount, shaderInterface))
5253 , m_sampler(getSamplers(vki, device, m_refSampler, m_imageFormat))
5254 {
5255 }
5256
getRefSamplers(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5257 std::vector<tcu::Sampler> ImageSampleInstanceImages::getRefSamplers(DescriptorSetCount descriptorSetCount,
5258 ShaderInputInterface shaderInterface)
5259 {
5260 std::vector<tcu::Sampler> refSamplers;
5261 for (uint32_t samplerNdx = 0;
5262 samplerNdx < getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
5263 samplerNdx++)
5264 refSamplers.push_back(createRefSampler(samplerNdx));
5265
5266 return refSamplers;
5267 }
5268
getSamplers(const vk::DeviceInterface & vki,vk::VkDevice device,std::vector<tcu::Sampler> & refSamplers,const tcu::TextureFormat imageFormat)5269 std::vector<SamplerHandleSp> ImageSampleInstanceImages::getSamplers(const vk::DeviceInterface &vki, vk::VkDevice device,
5270 std::vector<tcu::Sampler> &refSamplers,
5271 const tcu::TextureFormat imageFormat)
5272 {
5273 std::vector<SamplerHandleSp> samplers;
5274 for (uint32_t samplerNdx = 0; samplerNdx < (uint32_t)refSamplers.size(); samplerNdx++)
5275 {
5276 vk::Move<vk::VkSampler> sampler = createSampler(vki, device, refSamplers[samplerNdx], imageFormat);
5277 samplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
5278 }
5279 return samplers;
5280 }
5281
getSamplePos(vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,int samplePosNdx)5282 tcu::Vec4 ImageSampleInstanceImages::getSamplePos(vk::VkImageViewType viewType, uint32_t baseMipLevel,
5283 uint32_t baseArraySlice, int samplePosNdx)
5284 {
5285 DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
5286
5287 const uint32_t imageSize = (uint32_t)IMAGE_SIZE >> baseMipLevel;
5288 const uint32_t arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
5289
5290 // choose arbitrary values that are not ambiguous with NEAREST filtering
5291
5292 switch (viewType)
5293 {
5294 case vk::VK_IMAGE_VIEW_TYPE_1D:
5295 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5296 case vk::VK_IMAGE_VIEW_TYPE_2D:
5297 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5298 case vk::VK_IMAGE_VIEW_TYPE_3D:
5299 {
5300 const tcu::Vec3 coords[4] = {
5301 tcu::Vec3(0.75f, 0.5f, (float)(12u % imageSize) + 0.25f),
5302
5303 tcu::Vec3((float)(23u % imageSize) + 0.25f, (float)(73u % imageSize) + 0.5f,
5304 (float)(16u % imageSize) + 0.5f + (float)imageSize),
5305
5306 tcu::Vec3(-(float)(43u % imageSize) + 0.25f, (float)(84u % imageSize) + 0.5f + (float)imageSize,
5307 (float)(117u % imageSize) + 0.75f),
5308
5309 tcu::Vec3((float)imageSize + 0.5f, (float)(75u % imageSize) + 0.25f,
5310 (float)(83u % imageSize) + 0.25f + (float)imageSize),
5311 };
5312 const uint32_t slices[4] = {
5313 0u % arraySize,
5314 4u % arraySize,
5315 9u % arraySize,
5316 2u % arraySize,
5317 };
5318
5319 switch (viewType)
5320 {
5321 case vk::VK_IMAGE_VIEW_TYPE_1D:
5322 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5323 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, (float)slices[samplePosNdx], 0.0f, 0.0f);
5324 case vk::VK_IMAGE_VIEW_TYPE_2D:
5325 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5326 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, coords[samplePosNdx].y() / (float)imageSize,
5327 (float)slices[samplePosNdx], 0.0f);
5328 case vk::VK_IMAGE_VIEW_TYPE_3D:
5329 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, coords[samplePosNdx].y() / (float)imageSize,
5330 coords[samplePosNdx].z() / (float)imageSize, 0.0f);
5331 default:
5332 DE_FATAL("Impossible");
5333 return tcu::Vec4();
5334 }
5335 }
5336
5337 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
5338 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
5339 {
5340 // \note these values are in [0, texSize]*3 space for convenience
5341 const tcu::Vec3 coords[4] = {
5342 tcu::Vec3(0.75f, 0.5f, (float)imageSize),
5343
5344 tcu::Vec3((float)(13u % imageSize) + 0.25f, 0.0f, (float)(16u % imageSize) + 0.5f),
5345
5346 tcu::Vec3(0.0f, (float)(84u % imageSize) + 0.5f, (float)(10u % imageSize) + 0.75f),
5347
5348 tcu::Vec3((float)imageSize, (float)(75u % imageSize) + 0.25f, (float)(83u % imageSize) + 0.75f),
5349 };
5350 const uint32_t slices[4] = {
5351 1u % arraySize,
5352 2u % arraySize,
5353 9u % arraySize,
5354 5u % arraySize,
5355 };
5356
5357 DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize));
5358 DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize));
5359 DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize));
5360
5361 // map to [-1, 1]*3 space
5362 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f,
5363 coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f,
5364 coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f, (float)slices[samplePosNdx]);
5365 }
5366
5367 default:
5368 DE_FATAL("Impossible");
5369 return tcu::Vec4();
5370 }
5371 }
5372
fetchSampleValue(int samplePosNdx,int setNdx) const5373 tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue(int samplePosNdx, int setNdx) const
5374 {
5375 DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
5376
5377 // texture order is ABAB
5378 const bool isSamplerCase = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
5379 const uint32_t numImages = (isSamplerCase) ? 1 : getInterfaceNumResources(m_shaderInterface);
5380 const tcu::TextureLevelPyramid &sampleSrcA = getSourceImage(setNdx * numImages);
5381 const tcu::TextureLevelPyramid &sampleSrcB =
5382 (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? sampleSrcA : getSourceImage(setNdx * numImages + 1);
5383 const tcu::TextureLevelPyramid &sampleSrc = (isSamplerCase) ? (sampleSrcA) :
5384 ((samplePosNdx % 2) == 0) ? (sampleSrcA) :
5385 (sampleSrcB);
5386
5387 // sampler order is ABAB
5388 const tcu::Sampler &samplerA = getRefSampler(setNdx * getInterfaceNumResources(m_shaderInterface));
5389 const tcu::Sampler &samplerB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ?
5390 (samplerA) :
5391 getRefSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
5392 const tcu::Sampler &sampler = ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB);
5393
5394 const tcu::Vec4 samplePos = getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
5395 const float lod = 0.0f;
5396 std::vector<tcu::ConstPixelBufferAccess> levelStorage;
5397
5398 switch (m_viewType)
5399 {
5400 case vk::VK_IMAGE_VIEW_TYPE_1D:
5401 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5402 return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5403 .sample(sampler, samplePos.x(), samplePos.y(), lod);
5404 case vk::VK_IMAGE_VIEW_TYPE_2D:
5405 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5406 return getRef2DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5407 .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
5408 case vk::VK_IMAGE_VIEW_TYPE_3D:
5409 return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5410 .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
5411 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
5412 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
5413 return getRefCubeView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5414 .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), samplePos.w(), lod);
5415
5416 default:
5417 {
5418 DE_FATAL("Impossible");
5419 return tcu::Vec4();
5420 }
5421 }
5422 }
5423
getNumImages(vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5424 int ImageSampleInstanceImages::getNumImages(vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5425 ShaderInputInterface shaderInterface)
5426 {
5427 // If we are testing separate samplers, just one image is enough
5428 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5429 return getDescriptorSetCount(descriptorSetCount);
5430 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5431 {
5432 // combined: numImages == numSamplers
5433 return getInterfaceNumResources(shaderInterface) * getDescriptorSetCount(descriptorSetCount);
5434 }
5435 else
5436 {
5437 DE_FATAL("Impossible");
5438 return 0;
5439 }
5440 }
5441
createRefSampler(int ndx)5442 tcu::Sampler ImageSampleInstanceImages::createRefSampler(int ndx)
5443 {
5444 if (ndx % 2 == 0)
5445 {
5446 // linear, wrapping
5447 return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
5448 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
5449 tcu::Vec4(0.0f), true);
5450 }
5451 else
5452 {
5453 // nearest, clamping
5454 return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
5455 tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
5456 tcu::Vec4(0.0f), true);
5457 }
5458 }
5459
createSampler(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::Sampler & sampler,const tcu::TextureFormat & format)5460 vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler(const vk::DeviceInterface &vki, vk::VkDevice device,
5461 const tcu::Sampler &sampler,
5462 const tcu::TextureFormat &format)
5463 {
5464 const vk::VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, format);
5465
5466 return vk::createSampler(vki, device, &createInfo);
5467 }
5468
getRef1DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5469 tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView(const tcu::TextureLevelPyramid &source,
5470 uint32_t baseMipLevel, uint32_t baseArraySlice,
5471 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5472 {
5473 DE_ASSERT(levelStorage->empty());
5474
5475 const uint32_t numSlices = (uint32_t)source.getLevel(0).getHeight();
5476 const uint32_t numLevels = (uint32_t)source.getNumLevels();
5477
5478 // cut pyramid from baseMipLevel
5479 for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5480 {
5481 // cut levels from baseArraySlice
5482 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5483 const tcu::ConstPixelBufferAccess cutLevel =
5484 tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice);
5485 levelStorage->push_back(cutLevel);
5486 }
5487
5488 return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front());
5489 }
5490
getRef2DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5491 tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView(const tcu::TextureLevelPyramid &source,
5492 uint32_t baseMipLevel, uint32_t baseArraySlice,
5493 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5494 {
5495 DE_ASSERT(levelStorage->empty());
5496
5497 const uint32_t numSlices = (uint32_t)source.getLevel(0).getDepth();
5498 const uint32_t numLevels = (uint32_t)source.getNumLevels();
5499
5500 // cut pyramid from baseMipLevel
5501 for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5502 {
5503 // cut levels from baseArraySlice
5504 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5505 const tcu::ConstPixelBufferAccess cutLevel =
5506 tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(),
5507 numSlices - baseArraySlice);
5508 levelStorage->push_back(cutLevel);
5509 }
5510
5511 return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front());
5512 }
5513
getRef3DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5514 tcu::Texture3DView ImageSampleInstanceImages::getRef3DView(const tcu::TextureLevelPyramid &source,
5515 uint32_t baseMipLevel, uint32_t baseArraySlice,
5516 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5517 {
5518 DE_ASSERT(levelStorage->empty());
5519 DE_ASSERT(baseArraySlice == 0);
5520 DE_UNREF(baseArraySlice);
5521
5522 const uint32_t numLevels = (uint32_t)source.getNumLevels();
5523
5524 // cut pyramid from baseMipLevel
5525 for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5526 levelStorage->push_back(source.getLevel(level));
5527
5528 return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front());
5529 }
5530
getRefCubeView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5531 tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView(
5532 const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel, uint32_t baseArraySlice,
5533 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5534 {
5535 DE_ASSERT(levelStorage->empty());
5536
5537 const uint32_t numSlices = (uint32_t)source.getLevel(0).getDepth() / 6;
5538 const uint32_t numLevels = (uint32_t)source.getNumLevels();
5539
5540 // cut pyramid from baseMipLevel
5541 for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5542 {
5543 // cut levels from baseArraySlice
5544 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5545 const tcu::ConstPixelBufferAccess cutLevel =
5546 tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(),
5547 (numSlices - baseArraySlice) * 6);
5548 levelStorage->push_back(cutLevel);
5549 }
5550
5551 return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front());
5552 }
5553
5554 class ImageSampleRenderInstance : public SingleCmdRenderInstance
5555 {
5556 public:
5557 ImageSampleRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
5558 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5559 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
5560 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
5561 uint32_t baseArraySlice, bool isImmutable, const bool bind2);
5562
5563 private:
5564 static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
5565 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
5566 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
5567 const ImageSampleInstanceImages &images, DescriptorUpdateMethod updateMethod);
5568
5569 static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
5570 const vk::DeviceInterface &vki, vk::VkDevice device,
5571 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
5572
5573 static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
5574 vk::VkDescriptorType descriptorType,
5575 DescriptorSetCount descriptorSetCount,
5576 ShaderInputInterface shaderInterface);
5577
5578 static std::vector<DescriptorSetHandleSp> createDescriptorSets(
5579 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
5580 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5581 ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
5582 vk::VkDescriptorPool pool, bool isImmutable, const ImageSampleInstanceImages &images,
5583 vk::DescriptorSetUpdateBuilder &updateBuilder,
5584 #ifndef CTS_USES_VULKANSC
5585 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
5586 #endif
5587 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
5588
5589 static void writeSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5590 ShaderInputInterface shaderInterface, bool isImmutable,
5591 const ImageSampleInstanceImages &images, vk::VkDescriptorSet descriptorSet,
5592 uint32_t setNdx, vk::DescriptorSetUpdateBuilder &updateBuilder,
5593 std::vector<uint32_t> &descriptorsPerSet,
5594 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
5595
5596 static void writeImageSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5597 ShaderInputInterface shaderInterface, bool isImmutable,
5598 const ImageSampleInstanceImages &images,
5599 vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
5600 vk::DescriptorSetUpdateBuilder &updateBuilder,
5601 std::vector<uint32_t> &descriptorsPerSet,
5602 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
5603
5604 static void writeSamplerDescriptorSetWithTemplate(
5605 const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
5606 ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
5607 vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
5608 #ifndef CTS_USES_VULKANSC
5609 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry,
5610 #endif
5611 bool withPush = false, vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
5612
5613 static void writeImageSamplerDescriptorSetWithTemplate(
5614 const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
5615 ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
5616 vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
5617 #ifndef CTS_USES_VULKANSC
5618 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry,
5619 #endif
5620 bool withPush = false, vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
5621
5622 void logTestPlan(void) const;
5623 vk::VkPipelineLayout getPipelineLayout(void) const;
5624 void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
5625 tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
5626
5627 enum
5628 {
5629 RENDER_SIZE = 128,
5630 };
5631
5632 const DescriptorUpdateMethod m_updateMethod;
5633 const vk::VkDescriptorType m_descriptorType;
5634 const DescriptorSetCount m_descriptorSetCount;
5635 const vk::VkShaderStageFlags m_stageFlags;
5636 const vk::VkShaderStageFlags m_existingStages;
5637 const ShaderInputInterface m_shaderInterface;
5638 const vk::VkImageViewType m_viewType;
5639 const uint32_t m_numLevels;
5640 const uint32_t m_baseMipLevel;
5641 const uint32_t m_baseArraySlice;
5642
5643 #ifndef CTS_USES_VULKANSC
5644 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
5645 std::vector<RawUpdateRegistry> m_updateRegistry;
5646 #endif
5647 vk::DescriptorSetUpdateBuilder m_updateBuilder;
5648 const ImageSampleInstanceImages m_images;
5649 std::vector<uint32_t> m_descriptorsPerSet;
5650 const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
5651 const vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
5652 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
5653 const std::vector<DescriptorSetHandleSp> m_descriptorSets;
5654 };
5655
ImageSampleRenderInstance(vkt::Context & context,DescriptorUpdateMethod updateMethod,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,bool isImmutable,const bool bind2)5656 ImageSampleRenderInstance::ImageSampleRenderInstance(
5657 vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
5658 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, vk::VkShaderStageFlags stageFlags,
5659 vk::VkShaderStageFlags existingStages, ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
5660 uint32_t baseMipLevel, uint32_t baseArraySlice, bool isImmutable, const bool bind2)
5661 : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
5662 , m_updateMethod(updateMethod)
5663 , m_descriptorType(descriptorType)
5664 , m_descriptorSetCount(descriptorSetCount)
5665 , m_stageFlags(stageFlags)
5666 , m_existingStages(existingStages)
5667 , m_shaderInterface(shaderInterface)
5668 , m_viewType(viewType)
5669 , m_numLevels(baseMipLevel + 1u)
5670 , m_baseMipLevel(baseMipLevel)
5671 , m_baseArraySlice(baseArraySlice)
5672 #ifndef CTS_USES_VULKANSC
5673 , m_updateTemplates()
5674 , m_updateRegistry()
5675 #endif
5676 , m_updateBuilder()
5677 , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
5678 m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice, isImmutable)
5679 , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
5680 m_shaderInterface, m_stageFlags, m_images, m_updateMethod))
5681 , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
5682 , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
5683 , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
5684 m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool, isImmutable,
5685 m_images, m_updateBuilder,
5686 #ifndef CTS_USES_VULKANSC
5687 m_updateTemplates, m_updateRegistry,
5688 #endif
5689 m_descriptorsPerSet, *m_pipelineLayout))
5690 {
5691 }
5692
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,const ImageSampleInstanceImages & images,DescriptorUpdateMethod updateMethod)5693 std::vector<DescriptorSetLayoutHandleSp> ImageSampleRenderInstance::createDescriptorSetLayouts(
5694 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
5695 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
5696 const ImageSampleInstanceImages &images, DescriptorUpdateMethod updateMethod)
5697 {
5698 #ifdef CTS_USES_VULKANSC
5699 DE_UNREF(updateMethod);
5700 #endif
5701 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
5702
5703 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
5704 {
5705 const vk::VkSampler samplers[2] = {
5706 images.getSampler(setNdx * getInterfaceNumResources(shaderInterface)),
5707 images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1),
5708 };
5709
5710 vk::DescriptorSetLayoutBuilder builder;
5711 const bool addSeparateImage = descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER;
5712 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
5713
5714 #ifndef CTS_USES_VULKANSC
5715 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
5716 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5717 {
5718 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
5719 }
5720 #endif
5721
5722 // (combined)samplers follow
5723 switch (shaderInterface)
5724 {
5725 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5726 if (addSeparateImage)
5727 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5728 builder.addSingleSamplerBinding(descriptorType, stageFlags,
5729 (images.isImmutable()) ? (&samplers[0]) : (nullptr));
5730 break;
5731
5732 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5733 if (addSeparateImage)
5734 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5735 builder.addSingleSamplerBinding(descriptorType, stageFlags,
5736 (images.isImmutable()) ? (&samplers[0]) : (nullptr));
5737 builder.addSingleSamplerBinding(descriptorType, stageFlags,
5738 (images.isImmutable()) ? (&samplers[1]) : (nullptr));
5739 break;
5740
5741 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5742 builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, 0u,
5743 (images.isImmutable()) ? (&samplers[0]) : (nullptr));
5744 if (addSeparateImage)
5745 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags, 1u);
5746 builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, 2u,
5747 (images.isImmutable()) ? (&samplers[1]) : (nullptr));
5748 break;
5749
5750 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
5751 if (addSeparateImage)
5752 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5753 builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0),
5754 (images.isImmutable()) ? (&samplers[0]) : (nullptr));
5755 builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1),
5756 (images.isImmutable()) ? (&samplers[1]) : (nullptr));
5757 break;
5758
5759 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5760 if (addSeparateImage)
5761 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5762 builder.addArraySamplerBinding(descriptorType, 2u, stageFlags,
5763 (images.isImmutable()) ? (samplers) : (nullptr));
5764 break;
5765
5766 default:
5767 DE_FATAL("Impossible");
5768 }
5769
5770 vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
5771 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
5772
5773 // Add an empty descriptor set layout between sets 0 and 2
5774 if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
5775 {
5776 vk::DescriptorSetLayoutBuilder emptyBuilder;
5777 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
5778 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
5779 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
5780 }
5781 }
5782
5783 return descriptorSetLayouts;
5784 }
5785
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)5786 vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout(
5787 const vk::DeviceInterface &vki, vk::VkDevice device,
5788 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
5789 {
5790 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
5791 for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
5792 layoutHandles.push_back(**descriptorSetLayout[setNdx]);
5793
5794 const vk::VkPipelineLayoutCreateInfo createInfo = {
5795 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
5796 nullptr,
5797 (vk::VkPipelineLayoutCreateFlags)0,
5798 (uint32_t)layoutHandles.size(), // descriptorSetCount
5799 &layoutHandles.front(), // pSetLayouts
5800 0u, // pushConstantRangeCount
5801 nullptr, // pPushConstantRanges
5802 };
5803 return vk::createPipelineLayout(vki, device, &createInfo);
5804 }
5805
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5806 vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
5807 vk::VkDevice device,
5808 vk::VkDescriptorType descriptorType,
5809 DescriptorSetCount descriptorSetCount,
5810 ShaderInputInterface shaderInterface)
5811 {
5812 vk::DescriptorPoolBuilder builder;
5813
5814 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5815 {
5816 // separate samplers need image to sample
5817 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, getDescriptorSetCount(descriptorSetCount));
5818
5819 // also need sample to use, indifferent of whether immutable or not
5820 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER,
5821 getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface));
5822 }
5823 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5824 {
5825 // combined image samplers
5826 builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
5827 getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface));
5828 }
5829 else
5830 DE_FATAL("Impossible");
5831
5832 return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
5833 getDescriptorSetCount(descriptorSetCount));
5834 }
5835
createDescriptorSets(const vk::DeviceInterface & vki,DescriptorUpdateMethod updateMethod,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayouts,vk::VkDescriptorPool pool,bool isImmutable,const ImageSampleInstanceImages & images,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & updateRegistry,std::vector<uint32_t> & descriptorsPerSet,vk::VkPipelineLayout pipelineLayout)5836 std::vector<DescriptorSetHandleSp> ImageSampleRenderInstance::createDescriptorSets(
5837 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
5838 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
5839 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool, bool isImmutable,
5840 const ImageSampleInstanceImages &images, vk::DescriptorSetUpdateBuilder &updateBuilder,
5841 #ifndef CTS_USES_VULKANSC
5842 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
5843 #endif
5844 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
5845 {
5846 #ifdef CTS_USES_VULKANSC
5847 DE_UNREF(pipelineLayout);
5848 #endif
5849 std::vector<DescriptorSetHandleSp> descriptorSets;
5850
5851 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
5852 {
5853 vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
5854
5855 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
5856 pool, 1u, &layout};
5857
5858 vk::Move<vk::VkDescriptorSet> descriptorSet;
5859 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
5860 updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5861 {
5862 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
5863 }
5864 else
5865 {
5866 descriptorSet = vk::Move<vk::VkDescriptorSet>();
5867 }
5868
5869 #ifndef CTS_USES_VULKANSC
5870 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
5871 {
5872 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5873 writeSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface, isImmutable,
5874 images, *descriptorSet, setNdx, layout, updateTemplates,
5875 updateRegistry);
5876 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5877 writeImageSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface,
5878 isImmutable, images, *descriptorSet, setNdx, layout,
5879 updateTemplates, updateRegistry);
5880 else
5881 DE_FATAL("Impossible");
5882 }
5883 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5884 {
5885 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5886 writeSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface, isImmutable,
5887 images, VK_NULL_HANDLE, setNdx, layout, updateTemplates,
5888 updateRegistry, true, pipelineLayout);
5889 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5890 writeImageSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface,
5891 isImmutable, images, VK_NULL_HANDLE, setNdx, layout,
5892 updateTemplates, updateRegistry, true, pipelineLayout);
5893 else
5894 DE_FATAL("Impossible");
5895 }
5896 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5897 {
5898 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5899 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, setNdx,
5900 updateBuilder, descriptorsPerSet, updateMethod);
5901 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5902 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet,
5903 setNdx, updateBuilder, descriptorsPerSet, updateMethod);
5904 else
5905 DE_FATAL("Impossible");
5906 }
5907 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
5908 #endif
5909 {
5910 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5911 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, setNdx,
5912 updateBuilder, descriptorsPerSet);
5913 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5914 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet,
5915 setNdx, updateBuilder, descriptorsPerSet);
5916 else
5917 DE_FATAL("Impossible");
5918 }
5919
5920 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
5921 }
5922 return descriptorSets;
5923 }
5924
writeSamplerDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)5925 void ImageSampleRenderInstance::writeSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5926 ShaderInputInterface shaderInterface, bool isImmutable,
5927 const ImageSampleInstanceImages &images,
5928 vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
5929 vk::DescriptorSetUpdateBuilder &updateBuilder,
5930 std::vector<uint32_t> &descriptorsPerSet,
5931 DescriptorUpdateMethod updateMethod)
5932 {
5933 const vk::VkDescriptorImageInfo imageInfo =
5934 makeDescriptorImageInfo(images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
5935 vk::VkDescriptorImageInfo samplersInfos[2] = {
5936 makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
5937 makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
5938 };
5939
5940 if (isImmutable)
5941 {
5942 samplersInfos[0].sampler = VK_NULL_HANDLE;
5943 samplersInfos[1].sampler = VK_NULL_HANDLE;
5944 }
5945
5946 const uint32_t samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
5947 uint32_t numDescriptors = 1u;
5948
5949 // stand alone texture
5950 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(samplerLocation),
5951 vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
5952
5953 // samplers
5954 if (!isImmutable || (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH))
5955 {
5956 switch (shaderInterface)
5957 {
5958 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5959 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5960 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5961 numDescriptors++;
5962 break;
5963
5964 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5965 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5966 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5967 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
5968 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5969 numDescriptors += 2;
5970 break;
5971
5972 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5973 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
5974 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5975 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
5976 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5977 numDescriptors += 2;
5978 break;
5979
5980 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
5981 updateBuilder.writeSingle(descriptorSet,
5982 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
5983 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5984 updateBuilder.writeSingle(descriptorSet,
5985 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
5986 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5987 numDescriptors += 2;
5988 break;
5989
5990 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5991 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5992 vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
5993 numDescriptors++;
5994 break;
5995
5996 default:
5997 DE_FATAL("Impossible");
5998 }
5999 }
6000
6001 descriptorsPerSet.push_back(numDescriptors);
6002
6003 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6004 {
6005 updateBuilder.update(vki, device);
6006 updateBuilder.clear();
6007 }
6008 }
6009
writeImageSamplerDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)6010 void ImageSampleRenderInstance::writeImageSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
6011 ShaderInputInterface shaderInterface, bool isImmutable,
6012 const ImageSampleInstanceImages &images,
6013 vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
6014 vk::DescriptorSetUpdateBuilder &updateBuilder,
6015 std::vector<uint32_t> &descriptorsPerSet,
6016 DescriptorUpdateMethod updateMethod)
6017 {
6018 const vk::VkSampler samplers[2] = {
6019 (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ?
6020 VK_NULL_HANDLE :
6021 (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6022 (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ?
6023 VK_NULL_HANDLE :
6024 (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6025 };
6026 const vk::VkDescriptorImageInfo imageSamplers[2] = {
6027 vk::makeDescriptorImageInfo(samplers[0],
6028 images.getImageView(setNdx * getInterfaceNumResources(shaderInterface)),
6029 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6030 vk::makeDescriptorImageInfo(samplers[1],
6031 images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1),
6032 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6033 };
6034 uint32_t numDescriptors = 0u;
6035
6036 // combined image samplers
6037 switch (shaderInterface)
6038 {
6039 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6040 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6041 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6042 numDescriptors++;
6043 break;
6044
6045 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6046 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6047 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6048 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
6049 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6050 numDescriptors += 2;
6051 break;
6052
6053 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6054 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6055 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6056 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
6057 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6058 numDescriptors += 2;
6059 break;
6060
6061 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6062 updateBuilder.writeSingle(descriptorSet,
6063 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
6064 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6065 updateBuilder.writeSingle(descriptorSet,
6066 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
6067 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6068 numDescriptors += 2;
6069 break;
6070
6071 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6072 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6073 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
6074 numDescriptors++;
6075 break;
6076
6077 default:
6078 DE_FATAL("Impossible");
6079 }
6080
6081 descriptorsPerSet.push_back(numDescriptors);
6082
6083 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6084 {
6085 updateBuilder.update(vki, device);
6086 updateBuilder.clear();
6087 }
6088 }
6089
6090 #ifndef CTS_USES_VULKANSC
writeSamplerDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::VkDescriptorSetLayout layout,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)6091 void ImageSampleRenderInstance::writeSamplerDescriptorSetWithTemplate(
6092 const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
6093 ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
6094 vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
6095 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry, bool withPush,
6096 vk::VkPipelineLayout pipelineLayout)
6097 {
6098 const vk::VkDescriptorImageInfo imageInfo =
6099 makeDescriptorImageInfo(images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
6100 const vk::VkDescriptorImageInfo samplersInfos[2] = {
6101 makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6102 makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6103 };
6104
6105 const uint32_t samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
6106
6107 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
6108 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
6109 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
6110 nullptr,
6111 0,
6112 0, // updateCount
6113 nullptr, // pUpdates
6114 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
6115 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
6116 layout,
6117 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6118 pipelineLayout,
6119 getDescriptorSetNdx(descriptorSetCount, setNdx)};
6120
6121 RawUpdateRegistry updateRegistry;
6122
6123 updateRegistry.addWriteObject(imageInfo);
6124 updateRegistry.addWriteObject(samplersInfos[0]);
6125 updateRegistry.addWriteObject(samplersInfos[1]);
6126
6127 // stand alone texture
6128 updateEntries.push_back(createTemplateBinding(samplerLocation, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
6129 updateRegistry.getWriteObjectOffset(0), 0));
6130
6131 // samplers
6132 if (!isImmutable || withPush)
6133 {
6134 switch (shaderInterface)
6135 {
6136 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6137 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6138 updateRegistry.getWriteObjectOffset(1), 0));
6139 break;
6140
6141 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6142 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6143 updateRegistry.getWriteObjectOffset(1), 0));
6144 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6145 updateRegistry.getWriteObjectOffset(2), 0));
6146 break;
6147
6148 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6149 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6150 updateRegistry.getWriteObjectOffset(1), 0));
6151 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6152 updateRegistry.getWriteObjectOffset(2), 0));
6153 break;
6154
6155 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6156 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
6157 vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6158 updateRegistry.getWriteObjectOffset(1), 0));
6159 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
6160 vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6161 updateRegistry.getWriteObjectOffset(2), 0));
6162 break;
6163
6164 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6165 updateEntries.push_back(createTemplateBinding(1, 0, 2, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6166 updateRegistry.getWriteObjectOffset(1),
6167 sizeof(samplersInfos[0])));
6168 break;
6169
6170 default:
6171 DE_FATAL("Impossible");
6172 }
6173 }
6174
6175 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
6176 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
6177
6178 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
6179 vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
6180 updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
6181 registry.push_back(updateRegistry);
6182
6183 if (!withPush)
6184 {
6185 vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
6186 registry.back().getRawPointer());
6187 }
6188 }
6189
writeImageSamplerDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::VkDescriptorSetLayout layout,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)6190 void ImageSampleRenderInstance::writeImageSamplerDescriptorSetWithTemplate(
6191 const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
6192 ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
6193 vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
6194 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry, bool withPush,
6195 vk::VkPipelineLayout pipelineLayout)
6196 {
6197 const vk::VkSampler samplers[2] = {
6198 (isImmutable && !withPush) ? VK_NULL_HANDLE :
6199 (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6200 (isImmutable && !withPush) ? VK_NULL_HANDLE :
6201 (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6202 };
6203 const vk::VkDescriptorImageInfo imageSamplers[2] = {
6204 vk::makeDescriptorImageInfo(samplers[0],
6205 images.getImageView(setNdx * getInterfaceNumResources(shaderInterface)),
6206 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6207 vk::makeDescriptorImageInfo(samplers[1],
6208 images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1),
6209 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6210 };
6211
6212 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
6213 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
6214 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
6215 nullptr,
6216 0,
6217 0, // updateCount
6218 nullptr, // pUpdates
6219 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
6220 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
6221 layout,
6222 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6223 pipelineLayout,
6224 getDescriptorSetNdx(descriptorSetCount, setNdx)};
6225
6226 RawUpdateRegistry updateRegistry;
6227
6228 updateRegistry.addWriteObject(imageSamplers[0]);
6229 updateRegistry.addWriteObject(imageSamplers[1]);
6230
6231 // combined image samplers
6232 switch (shaderInterface)
6233 {
6234 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6235 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6236 updateRegistry.getWriteObjectOffset(0), 0));
6237 break;
6238
6239 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6240 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6241 updateRegistry.getWriteObjectOffset(0), 0));
6242 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6243 updateRegistry.getWriteObjectOffset(1), 0));
6244 break;
6245
6246 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6247 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6248 updateRegistry.getWriteObjectOffset(0), 0));
6249 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6250 updateRegistry.getWriteObjectOffset(1), 0));
6251 break;
6252
6253 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6254 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
6255 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6256 updateRegistry.getWriteObjectOffset(0), 0));
6257 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
6258 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6259 updateRegistry.getWriteObjectOffset(1), 0));
6260 break;
6261
6262 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6263 updateEntries.push_back(createTemplateBinding(0, 0, 2, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6264 updateRegistry.getWriteObjectOffset(0),
6265 sizeof(imageSamplers[0])));
6266 break;
6267
6268 default:
6269 DE_FATAL("Impossible");
6270 }
6271
6272 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
6273 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
6274
6275 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
6276 vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
6277 updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
6278 registry.push_back(updateRegistry);
6279
6280 if (!withPush)
6281 {
6282 vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
6283 registry.back().getRawPointer());
6284 }
6285 }
6286 #endif
6287
logTestPlan(void) const6288 void ImageSampleRenderInstance::logTestPlan(void) const
6289 {
6290 std::ostringstream msg;
6291
6292 msg << "Rendering 2x2 grid.\n";
6293
6294 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6295 {
6296 msg << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
6297 "Multiple descriptor sets. ")
6298 << "Each descriptor set contains "
6299 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
6300 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
6301 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
6302 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
6303 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
6304 nullptr)
6305 << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
6306 }
6307 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6308 {
6309 msg << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
6310 "Multiple descriptor sets. ")
6311 << "Each descriptor set contains "
6312 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
6313 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
6314 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
6315 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
6316 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
6317 nullptr)
6318 << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
6319 }
6320 else
6321 DE_FATAL("Impossible");
6322
6323 msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
6324
6325 if (m_baseMipLevel)
6326 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
6327 if (m_baseArraySlice)
6328 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
6329
6330 if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
6331 msg << "Sampler mode is LINEAR, with WRAP\n";
6332 else
6333 msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
6334
6335 if (m_stageFlags == 0u)
6336 {
6337 msg << "Descriptors are not accessed in any shader stage.\n";
6338 }
6339 else
6340 {
6341 msg << "Color in each cell is fetched using the descriptor(s):\n";
6342
6343 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
6344 {
6345 msg << "Test sample " << resultNdx << ": sample at position "
6346 << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
6347
6348 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
6349 {
6350 const int srcResourceNdx = (resultNdx % 2); // ABAB source
6351
6352 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6353 msg << " using sampler " << srcResourceNdx;
6354 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6355 msg << " from combined image sampler " << srcResourceNdx;
6356 else
6357 DE_FATAL("Impossible");
6358 }
6359 msg << "\n";
6360 }
6361
6362 msg << "Descriptors are accessed in {"
6363 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
6364 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
6365 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
6366 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
6367 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.";
6368 }
6369
6370 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
6371 }
6372
getPipelineLayout(void) const6373 vk::VkPipelineLayout ImageSampleRenderInstance::getPipelineLayout(void) const
6374 {
6375 return *m_pipelineLayout;
6376 }
6377
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const6378 void ImageSampleRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
6379 {
6380 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
6381 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6382 {
6383 std::vector<vk::VkDescriptorSet> setHandles;
6384 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
6385 setHandles.push_back(**m_descriptorSets[setNdx]);
6386
6387 switch (m_descriptorSetCount)
6388 {
6389 case DESCRIPTOR_SET_COUNT_SINGLE:
6390 case DESCRIPTOR_SET_COUNT_MULTIPLE:
6391 {
6392 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6393 getPipelineLayout(), 0u, (int)setHandles.size(), &setHandles.front(), 0u, nullptr,
6394 m_bind2);
6395 break;
6396 }
6397 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
6398 {
6399 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
6400 {
6401 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
6402 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6403 getPipelineLayout(), descriptorSetNdx, 1u, &setHandles[setNdx], 0u, nullptr,
6404 m_bind2);
6405 }
6406 break;
6407 }
6408 default:
6409 DE_FATAL("Impossible");
6410 }
6411 }
6412 #ifndef CTS_USES_VULKANSC
6413 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
6414 {
6415 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
6416 {
6417 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
6418 m_vki.cmdPushDescriptorSetWithTemplate(cmd, **m_updateTemplates[setNdx], getPipelineLayout(),
6419 descriptorSetNdx,
6420 (const void *)m_updateRegistry[setNdx].getRawPointer());
6421 }
6422 }
6423 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6424 {
6425 uint32_t descriptorNdx = 0u;
6426 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
6427 {
6428 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
6429 const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
6430 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout,
6431 descriptorSetNdx, descriptorNdx, numDescriptors);
6432 descriptorNdx += numDescriptors;
6433 }
6434 }
6435 #endif
6436
6437 m_vki.cmdDraw(cmd, 6u * 4u, 1u, 0u, 0u); // render four quads (two separate triangles)
6438 }
6439
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const6440 tcu::TestStatus ImageSampleRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
6441 {
6442 const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
6443 const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
6444 const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
6445 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
6446 const tcu::RGBA threshold = tcu::RGBA(
6447 8, 8, 8, 8); // source image is high-frequency so the threshold is quite large to tolerate sampling errors
6448
6449 tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
6450
6451 tcu::Vec4 sample0 = tcu::Vec4(0.0f);
6452 tcu::Vec4 sample1 = tcu::Vec4(0.0f);
6453 tcu::Vec4 sample2 = tcu::Vec4(0.0f);
6454 tcu::Vec4 sample3 = tcu::Vec4(0.0f);
6455
6456 for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
6457 {
6458 sample0 += (!doFetch) ? (yellow) : (m_images.fetchSampleValue(0, setNdx));
6459 sample1 += (!doFetch) ? (green) : (m_images.fetchSampleValue(1, setNdx));
6460 sample2 += (!doFetch) ? (green) : (m_images.fetchSampleValue(2, setNdx));
6461 sample3 += (!doFetch) ? (yellow) : (m_images.fetchSampleValue(3, setNdx));
6462 }
6463
6464 if (numDescriptorSets > 1)
6465 {
6466 sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
6467 sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
6468 sample2 = sample2 / tcu::Vec4(float(numDescriptorSets));
6469 sample3 = sample3 / tcu::Vec4(float(numDescriptorSets));
6470 }
6471
6472 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
6473
6474 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
6475 result, threshold, tcu::COMPARE_LOG_RESULT))
6476 return tcu::TestStatus::fail("Image verification failed");
6477 else
6478 return tcu::TestStatus::pass("Pass");
6479 }
6480
6481 class ImageSampleComputeInstance : public vkt::TestInstance
6482 {
6483 public:
6484 ImageSampleComputeInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
6485 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
6486 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
6487 uint32_t baseMipLevel, uint32_t baseArraySlice, bool isImmutableSampler,
6488 const bool bind2);
6489
6490 private:
6491 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
6492 vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
6493 vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
6494 uint32_t setNdx);
6495 void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, uint32_t setNdx,
6496 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
6497 void writeImageSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
6498 #ifndef CTS_USES_VULKANSC
6499 void writeImageSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
6500 uint32_t setNdx, bool withPush = false,
6501 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
6502 #endif
6503 void writeSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
6504 #ifndef CTS_USES_VULKANSC
6505 void writeSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
6506 uint32_t setNdx, bool withPush = false,
6507 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
6508 #endif
6509
6510 tcu::TestStatus iterate(void);
6511 void logTestPlan(void) const;
6512 tcu::TestStatus testResourceAccess(void);
6513
6514 const DescriptorUpdateMethod m_updateMethod;
6515 const vk::VkDescriptorType m_descriptorType;
6516 const DescriptorSetCount m_descriptorSetCount;
6517 const ShaderInputInterface m_shaderInterface;
6518 const vk::VkImageViewType m_viewType;
6519 const uint32_t m_numLevels;
6520 const uint32_t m_baseMipLevel;
6521 const uint32_t m_baseArraySlice;
6522 const bool m_isImmutableSampler;
6523 const bool m_bind2;
6524 #ifndef CTS_USES_VULKANSC
6525 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
6526 #endif
6527
6528 const vk::DeviceInterface &m_vki;
6529 const vk::VkDevice m_device;
6530 const vk::VkQueue m_queue;
6531 const uint32_t m_queueFamilyIndex;
6532 vk::Allocator &m_allocator;
6533 const ComputeInstanceResultBuffer m_result;
6534 const ImageSampleInstanceImages m_images;
6535 #ifndef CTS_USES_VULKANSC
6536 std::vector<RawUpdateRegistry> m_updateRegistry;
6537 #endif
6538 vk::DescriptorSetUpdateBuilder m_updateBuilder;
6539 std::vector<uint32_t> m_descriptorsPerSet;
6540 };
6541
ImageSampleComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,bool isImmutableSampler,const bool bind2)6542 ImageSampleComputeInstance::ImageSampleComputeInstance(
6543 Context &context, DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
6544 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
6545 uint32_t baseMipLevel, uint32_t baseArraySlice, bool isImmutableSampler, const bool bind2)
6546 : vkt::TestInstance(context)
6547 , m_updateMethod(updateMethod)
6548 , m_descriptorType(descriptorType)
6549 , m_descriptorSetCount(descriptorSetCount)
6550 , m_shaderInterface(shaderInterface)
6551 , m_viewType(viewType)
6552 , m_numLevels(baseMipLevel + 1u)
6553 , m_baseMipLevel(baseMipLevel)
6554 , m_baseArraySlice(baseArraySlice)
6555 , m_isImmutableSampler(isImmutableSampler)
6556 , m_bind2(bind2)
6557 #ifndef CTS_USES_VULKANSC
6558 , m_updateTemplates()
6559 #endif
6560 , m_vki(context.getDeviceInterface())
6561 , m_device(context.getDevice())
6562 , m_queue(context.getUniversalQueue())
6563 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
6564 , m_allocator(context.getDefaultAllocator())
6565 , m_result(m_vki, m_device, m_allocator)
6566 , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
6567 m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice, isImmutableSampler)
6568 #ifndef CTS_USES_VULKANSC
6569 , m_updateRegistry()
6570 #endif
6571 , m_updateBuilder()
6572 , m_descriptorsPerSet()
6573 {
6574 }
6575
createDescriptorSetLayout(uint32_t setNdx) const6576 vk::Move<vk::VkDescriptorSetLayout> ImageSampleComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
6577 {
6578 const vk::VkSampler samplers[2] = {
6579 m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface)),
6580 m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
6581 };
6582
6583 vk::DescriptorSetLayoutBuilder builder;
6584 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
6585 uint32_t binding = 0;
6586
6587 #ifndef CTS_USES_VULKANSC
6588 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
6589 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6590 {
6591 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
6592 }
6593 #endif
6594
6595 // result buffer
6596 if (setNdx == 0)
6597 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6598 binding++);
6599
6600 // (combined)samplers follow
6601 switch (m_shaderInterface)
6602 {
6603 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6604 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6605 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6606 binding++);
6607 builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding++,
6608 (m_images.isImmutable()) ? (&samplers[0]) : (nullptr));
6609 break;
6610
6611 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6612 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6613 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6614 binding++);
6615 builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding++,
6616 (m_images.isImmutable()) ? (&samplers[0]) : (nullptr));
6617 builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding++,
6618 (m_images.isImmutable()) ? (&samplers[1]) : (nullptr));
6619 break;
6620
6621 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6622 builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding,
6623 (m_images.isImmutable()) ? (&samplers[0]) : (nullptr));
6624 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6625 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6626 binding + 1u);
6627 builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2u,
6628 (m_images.isImmutable()) ? (&samplers[1]) : (nullptr));
6629 break;
6630
6631 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6632 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6633 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6634 binding++);
6635 builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6636 getArbitraryBindingIndex(0),
6637 (m_images.isImmutable()) ? (&samplers[0]) : (nullptr));
6638 builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6639 getArbitraryBindingIndex(1),
6640 (m_images.isImmutable()) ? (&samplers[1]) : (nullptr));
6641 break;
6642
6643 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6644 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6645 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6646 binding++);
6647 builder.addArraySamplerBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6648 (m_images.isImmutable()) ? (samplers) : (nullptr));
6649 break;
6650
6651 default:
6652 DE_FATAL("Impossible");
6653 }
6654
6655 return builder.build(m_vki, m_device, extraFlags);
6656 }
6657
createDescriptorPool(void) const6658 vk::Move<vk::VkDescriptorPool> ImageSampleComputeInstance::createDescriptorPool(void) const
6659 {
6660 vk::DescriptorPoolBuilder builder;
6661
6662 builder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
6663 builder.addType(m_descriptorType,
6664 getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface));
6665
6666 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6667 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, getDescriptorSetCount(m_descriptorSetCount));
6668
6669 return builder.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6670 getDescriptorSetCount(m_descriptorSetCount));
6671 }
6672
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx)6673 vk::Move<vk::VkDescriptorSet> ImageSampleComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
6674 vk::VkDescriptorSetLayout layout,
6675 uint32_t setNdx)
6676 {
6677 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
6678 pool, 1u, &layout};
6679
6680 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
6681 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6682 {
6683 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
6684 writeDescriptorSet(*descriptorSet, layout, setNdx);
6685
6686 return descriptorSet;
6687 }
6688
6689 return vk::Move<vk::VkDescriptorSet>();
6690 }
6691
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkPipelineLayout pipelineLayout)6692 void ImageSampleComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
6693 uint32_t setNdx, vk::VkPipelineLayout pipelineLayout)
6694 {
6695 #ifdef CTS_USES_VULKANSC
6696 DE_UNREF(layout);
6697 DE_UNREF(pipelineLayout);
6698 #else
6699 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
6700 {
6701 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6702 writeSamplerDescriptorSetWithTemplate(descriptorSet, layout, setNdx);
6703 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6704 writeImageSamplerDescriptorSetWithTemplate(descriptorSet, layout, setNdx);
6705 else
6706 DE_FATAL("Impossible");
6707 }
6708 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
6709 {
6710 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6711 writeSamplerDescriptorSetWithTemplate(descriptorSet, layout, setNdx, true, pipelineLayout);
6712 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6713 writeImageSamplerDescriptorSetWithTemplate(descriptorSet, layout, setNdx, true, pipelineLayout);
6714 else
6715 DE_FATAL("Impossible");
6716 }
6717 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6718 {
6719 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6720 writeSamplerDescriptorSet(descriptorSet, setNdx);
6721 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6722 writeImageSamplerDescriptorSet(descriptorSet, setNdx);
6723 else
6724 DE_FATAL("Impossible");
6725 }
6726 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6727 #endif
6728 {
6729 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6730 writeSamplerDescriptorSet(descriptorSet, setNdx);
6731 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6732 writeImageSamplerDescriptorSet(descriptorSet, setNdx);
6733 else
6734 DE_FATAL("Impossible");
6735 }
6736 }
6737
writeSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)6738 void ImageSampleComputeInstance::writeSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
6739 {
6740 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
6741 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
6742 const vk::VkDescriptorImageInfo imageInfo =
6743 makeDescriptorImageInfo(m_images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
6744 const vk::VkDescriptorImageInfo samplersInfos[2] = {
6745 makeDescriptorImageInfo(m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
6746 makeDescriptorImageInfo(m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)),
6747 };
6748 uint32_t binding = 0u;
6749 uint32_t numDescriptors = 0u;
6750
6751 // result
6752 if (setNdx == 0)
6753 {
6754 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6755 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
6756 numDescriptors++;
6757 }
6758
6759 // stand alone texture
6760 {
6761 const uint32_t texutreBinding =
6762 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? (binding + 1) : (binding++);
6763 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(texutreBinding),
6764 vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
6765 numDescriptors++;
6766 }
6767
6768 // samplers
6769 if (!m_isImmutableSampler || (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH))
6770 {
6771 switch (m_shaderInterface)
6772 {
6773 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6774 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6775 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
6776 numDescriptors++;
6777 break;
6778
6779 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6780 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6781 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
6782 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6783 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
6784 numDescriptors += 2;
6785 break;
6786
6787 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6788 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
6789 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
6790 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
6791 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
6792 numDescriptors += 2;
6793 break;
6794
6795 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6796 m_updateBuilder.writeSingle(descriptorSet,
6797 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
6798 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
6799 m_updateBuilder.writeSingle(descriptorSet,
6800 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
6801 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
6802 numDescriptors += 2;
6803 break;
6804
6805 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6806 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6807 vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
6808 numDescriptors++;
6809 break;
6810
6811 default:
6812 DE_FATAL("Impossible");
6813 }
6814 }
6815
6816 m_descriptorsPerSet.push_back(numDescriptors);
6817
6818 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6819 {
6820 m_updateBuilder.update(m_vki, m_device);
6821 m_updateBuilder.clear();
6822 }
6823 }
6824
6825 #ifndef CTS_USES_VULKANSC
writeSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)6826 void ImageSampleComputeInstance::writeSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
6827 vk::VkDescriptorSetLayout layout,
6828 uint32_t setNdx, bool withPush,
6829 vk::VkPipelineLayout pipelineLayout)
6830 {
6831 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
6832 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
6833 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
6834 const vk::VkDescriptorImageInfo imageInfo =
6835 makeDescriptorImageInfo(m_images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
6836 const vk::VkDescriptorImageInfo samplersInfos[2] = {
6837 makeDescriptorImageInfo(m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
6838 makeDescriptorImageInfo(m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)),
6839 };
6840 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
6841 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
6842 nullptr,
6843 0,
6844 0, // updateCount
6845 nullptr, // pUpdates
6846 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
6847 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
6848 layout,
6849 vk::VK_PIPELINE_BIND_POINT_COMPUTE,
6850 pipelineLayout,
6851 getDescriptorSetNdx(m_descriptorSetCount, setNdx)};
6852 uint32_t binding = 0u;
6853 uint32_t offset = 0u;
6854 RawUpdateRegistry updateRegistry;
6855
6856 if (setNdx == 0)
6857 updateRegistry.addWriteObject(resultInfo);
6858
6859 updateRegistry.addWriteObject(imageInfo);
6860 updateRegistry.addWriteObject(samplersInfos[0]);
6861 updateRegistry.addWriteObject(samplersInfos[1]);
6862
6863 // result
6864 if (setNdx == 0)
6865 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
6866 updateRegistry.getWriteObjectOffset(offset++), 0));
6867
6868 // stand alone texture
6869 {
6870 const uint32_t textureBinding =
6871 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? (binding + 1) : (binding++);
6872 updateEntries.push_back(createTemplateBinding(textureBinding, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
6873 updateRegistry.getWriteObjectOffset(offset++), 0));
6874 }
6875
6876 // samplers
6877 if (!m_isImmutableSampler || withPush)
6878 {
6879 switch (m_shaderInterface)
6880 {
6881 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6882 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6883 updateRegistry.getWriteObjectOffset(offset++), 0));
6884 break;
6885
6886 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6887 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6888 updateRegistry.getWriteObjectOffset(offset++), 0));
6889 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6890 updateRegistry.getWriteObjectOffset(offset++), 0));
6891 break;
6892
6893 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6894 updateEntries.push_back(createTemplateBinding(binding, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6895 updateRegistry.getWriteObjectOffset(offset++), 0));
6896 updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6897 updateRegistry.getWriteObjectOffset(offset++), 0));
6898 break;
6899
6900 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6901 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
6902 vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6903 updateRegistry.getWriteObjectOffset(offset++), 0));
6904 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
6905 vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6906 updateRegistry.getWriteObjectOffset(offset++), 0));
6907 break;
6908
6909 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6910 updateEntries.push_back(createTemplateBinding(binding++, 0, 2, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6911 updateRegistry.getWriteObjectOffset(offset++),
6912 sizeof(samplersInfos[0])));
6913 break;
6914
6915 default:
6916 DE_FATAL("Impossible");
6917 }
6918 }
6919
6920 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
6921 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
6922
6923 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
6924 vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
6925 m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
6926 m_updateRegistry.push_back(updateRegistry);
6927
6928 if (!withPush)
6929 {
6930 m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
6931 m_updateRegistry.back().getRawPointer());
6932 }
6933 }
6934 #endif
6935
writeImageSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)6936 void ImageSampleComputeInstance::writeImageSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
6937 {
6938 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
6939 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
6940 const vk::VkSampler samplers[2] = {
6941 (m_isImmutableSampler && (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) ?
6942 VK_NULL_HANDLE :
6943 (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
6944 (m_isImmutableSampler && (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) ?
6945 VK_NULL_HANDLE :
6946 (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)),
6947 };
6948 const vk::VkDescriptorImageInfo imageSamplers[2] = {
6949 makeDescriptorImageInfo(samplers[0],
6950 m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
6951 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6952 makeDescriptorImageInfo(samplers[1],
6953 m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
6954 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6955 };
6956 uint32_t binding = 0u;
6957 uint32_t numDescriptors = 0u;
6958
6959 // result
6960 if (setNdx == 0)
6961 {
6962 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6963 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
6964 numDescriptors++;
6965 }
6966
6967 // combined image samplers
6968 switch (m_shaderInterface)
6969 {
6970 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6971 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6972 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6973 numDescriptors++;
6974 break;
6975
6976 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6977 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6978 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6979 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6980 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6981 numDescriptors += 2;
6982 break;
6983
6984 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6985 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
6986 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6987 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2u),
6988 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6989 numDescriptors += 2;
6990 break;
6991
6992 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6993 m_updateBuilder.writeSingle(descriptorSet,
6994 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
6995 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6996 m_updateBuilder.writeSingle(descriptorSet,
6997 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
6998 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6999 numDescriptors += 2;
7000 break;
7001
7002 case SHADER_INPUT_DESCRIPTOR_ARRAY:
7003 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
7004 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
7005 numDescriptors++;
7006 break;
7007
7008 default:
7009 DE_FATAL("Impossible");
7010 }
7011
7012 m_descriptorsPerSet.push_back(numDescriptors);
7013
7014 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
7015 {
7016 m_updateBuilder.update(m_vki, m_device);
7017 m_updateBuilder.clear();
7018 }
7019 }
7020
7021 #ifndef CTS_USES_VULKANSC
writeImageSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)7022 void ImageSampleComputeInstance::writeImageSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
7023 vk::VkDescriptorSetLayout layout,
7024 uint32_t setNdx, bool withPush,
7025 vk::VkPipelineLayout pipelineLayout)
7026 {
7027 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
7028 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
7029 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
7030 const vk::VkSampler samplers[2] = {
7031 (m_isImmutableSampler && !withPush) ?
7032 VK_NULL_HANDLE :
7033 (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
7034 (m_isImmutableSampler && !withPush) ?
7035 VK_NULL_HANDLE :
7036 (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)),
7037 };
7038 const vk::VkDescriptorImageInfo imageSamplers[2] = {
7039 makeDescriptorImageInfo(samplers[0],
7040 m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
7041 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
7042 makeDescriptorImageInfo(samplers[1],
7043 m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
7044 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
7045 };
7046 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
7047 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
7048 nullptr,
7049 0,
7050 0, // updateCount
7051 nullptr, // pUpdates
7052 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
7053 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
7054 layout,
7055 vk::VK_PIPELINE_BIND_POINT_COMPUTE,
7056 pipelineLayout,
7057 getDescriptorSetNdx(m_descriptorSetCount, setNdx)};
7058
7059 uint32_t binding = 0u;
7060 uint32_t offset = 0u;
7061 RawUpdateRegistry updateRegistry;
7062
7063 if (setNdx == 0)
7064 updateRegistry.addWriteObject(resultInfo);
7065
7066 updateRegistry.addWriteObject(imageSamplers[0]);
7067 updateRegistry.addWriteObject(imageSamplers[1]);
7068
7069 // result
7070 if (setNdx == 0)
7071 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
7072 updateRegistry.getWriteObjectOffset(offset++), 0));
7073
7074 // combined image samplers
7075 switch (m_shaderInterface)
7076 {
7077 case SHADER_INPUT_SINGLE_DESCRIPTOR:
7078 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7079 updateRegistry.getWriteObjectOffset(offset++), 0));
7080 break;
7081
7082 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
7083 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7084 updateRegistry.getWriteObjectOffset(offset++), 0));
7085 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7086 updateRegistry.getWriteObjectOffset(offset++), 0));
7087 break;
7088
7089 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
7090 updateEntries.push_back(createTemplateBinding(binding, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7091 updateRegistry.getWriteObjectOffset(offset++), 0));
7092 updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7093 updateRegistry.getWriteObjectOffset(offset++), 0));
7094 break;
7095
7096 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
7097 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
7098 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7099 updateRegistry.getWriteObjectOffset(offset++), 0));
7100 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
7101 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7102 updateRegistry.getWriteObjectOffset(offset++), 0));
7103 break;
7104
7105 case SHADER_INPUT_DESCRIPTOR_ARRAY:
7106 updateEntries.push_back(createTemplateBinding(binding++, 0, 2, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7107 updateRegistry.getWriteObjectOffset(offset++),
7108 sizeof(imageSamplers[0])));
7109 break;
7110
7111 default:
7112 DE_FATAL("Impossible");
7113 }
7114
7115 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
7116 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
7117
7118 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
7119 vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
7120 m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
7121 m_updateRegistry.push_back(updateRegistry);
7122
7123 if (!withPush)
7124 {
7125 m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
7126 m_updateRegistry.back().getRawPointer());
7127 }
7128 }
7129 #endif
7130
iterate(void)7131 tcu::TestStatus ImageSampleComputeInstance::iterate(void)
7132 {
7133 logTestPlan();
7134 return testResourceAccess();
7135 }
7136
logTestPlan(void) const7137 void ImageSampleComputeInstance::logTestPlan(void) const
7138 {
7139 std::ostringstream msg;
7140
7141 msg << "Accessing resource in a compute program.\n";
7142
7143 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
7144 {
7145 msg << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
7146 "Multiple descriptor sets. ")
7147 << "Each descriptor set contains "
7148 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
7149 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
7150 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
7151 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
7152 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
7153 nullptr)
7154 << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
7155 }
7156 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
7157 {
7158 msg << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
7159 "Multiple descriptor sets. ")
7160 << "Each descriptor set contains "
7161 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
7162 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
7163 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
7164 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
7165 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
7166 nullptr)
7167 << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
7168 }
7169 else
7170 DE_FATAL("Impossible");
7171
7172 msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
7173
7174 if (m_baseMipLevel)
7175 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
7176 if (m_baseArraySlice)
7177 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
7178
7179 if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
7180 msg << "Sampler mode is LINEAR, with WRAP\n";
7181 else
7182 msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
7183
7184 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
7185 {
7186 msg << "Test sample " << resultNdx << ": sample at position "
7187 << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
7188
7189 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
7190 {
7191 const int srcResourceNdx = (resultNdx % 2); // ABAB source
7192
7193 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
7194 msg << " using sampler " << srcResourceNdx;
7195 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
7196 msg << " from combined image sampler " << srcResourceNdx;
7197 else
7198 DE_FATAL("Impossible");
7199 }
7200 msg << "\n";
7201 }
7202
7203 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
7204 }
7205
testResourceAccess(void)7206 tcu::TestStatus ImageSampleComputeInstance::testResourceAccess(void)
7207 {
7208 const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
7209 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
7210 std::vector<DescriptorSetHandleSp> descriptorSets;
7211 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
7212 std::vector<vk::VkDescriptorSet> setHandles;
7213
7214 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
7215 {
7216 vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
7217 vk::Move<vk::VkDescriptorSet> set = createDescriptorSet(*descriptorPool, *layout, setNdx);
7218
7219 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
7220 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
7221
7222 layoutHandles.push_back(**descriptorSetLayouts.back());
7223 setHandles.push_back(**descriptorSets.back());
7224
7225 // Add an empty descriptor set layout between sets 0 and 2
7226 if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
7227 {
7228 vk::DescriptorSetLayoutBuilder emptyBuilder;
7229 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
7230 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
7231
7232 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
7233 layoutHandles.push_back(**descriptorSetLayouts.back());
7234 }
7235 }
7236
7237 const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
7238 &layoutHandles.front());
7239 const uint32_t *const dynamicOffsets = nullptr;
7240 const int numDynamicOffsets = 0;
7241 const vk::VkBufferMemoryBarrier *const preBarriers = nullptr;
7242 const int numPreBarriers = 0;
7243 const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
7244 const int numPostBarriers = 1;
7245
7246 const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
7247 tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
7248 numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
7249 postBarriers, m_bind2);
7250
7251 tcu::Vec4 results[4];
7252 bool anyResultSet = false;
7253 bool allResultsOk = true;
7254
7255 #ifndef CTS_USES_VULKANSC
7256 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
7257 {
7258 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
7259 writeDescriptorSet(VK_NULL_HANDLE, layoutHandles[getDescriptorSetNdx(m_descriptorSetCount, setNdx)], setNdx,
7260 pipeline.getPipelineLayout()); // descriptor set not applicable
7261
7262 compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
7263 }
7264 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
7265 {
7266 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
7267 writeDescriptorSet(VK_NULL_HANDLE, layoutHandles[getDescriptorSetNdx(m_descriptorSetCount, setNdx)], setNdx,
7268 pipeline.getPipelineLayout()); // descriptor set not applicable
7269
7270 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
7271 }
7272 else
7273 #endif
7274 {
7275 compute.submitAndWait(m_queueFamilyIndex, m_queue);
7276 }
7277 m_result.readResultContentsTo(&results);
7278
7279 // verify
7280 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
7281 {
7282 // source image is high-frequency so the threshold is quite large to tolerate sampling errors
7283 const tcu::Vec4 samplingThreshold = tcu::Vec4(8.0f / 255.0f);
7284 const tcu::Vec4 result = results[resultNdx];
7285 tcu::Vec4 reference = tcu::Vec4(0.0f);
7286
7287 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
7288 reference += m_images.fetchSampleValue(resultNdx, setNdx);
7289
7290 reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
7291
7292 if (result != tcu::Vec4(-1.0f))
7293 anyResultSet = true;
7294
7295 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), samplingThreshold)))
7296 {
7297 allResultsOk = false;
7298
7299 m_context.getTestContext().getLog()
7300 << tcu::TestLog::Message << "Test sample " << resultNdx << ":\n"
7301 << "\tSampling at " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx)
7302 << "\n"
7303 << "\tError expected " << reference << ", got " << result << tcu::TestLog::EndMessage;
7304 }
7305 }
7306
7307 // read back and verify
7308 if (allResultsOk)
7309 return tcu::TestStatus::pass("Pass");
7310 else if (anyResultSet)
7311 return tcu::TestStatus::fail("Invalid result values");
7312 else
7313 {
7314 m_context.getTestContext().getLog()
7315 << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
7316 return tcu::TestStatus::fail("Result buffer was not written to");
7317 }
7318 }
7319
7320 class ImageDescriptorCase : public QuadrantRendederCase
7321 {
7322 public:
7323 enum
7324 {
7325 FLAG_BASE_MIP = (1u << 1u),
7326 FLAG_BASE_SLICE = (1u << 2u),
7327 };
7328 // enum continues where resource flags ends
7329 DE_STATIC_ASSERT((uint32_t)FLAG_BASE_MIP == (uint32_t)RESOURCE_FLAG_LAST);
7330
7331 ImageDescriptorCase(tcu::TestContext &testCtx, const char *name, bool isPrimaryCmdBuf,
7332 DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
7333 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
7334 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
7335 vk::VkImageViewType viewType, uint32_t flags, const bool bind2);
7336
7337 void checkSupport(Context &context) const;
7338
7339 private:
7340 std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
7341 std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
7342 std::string genFetchCoordStr(int fetchPosNdx) const;
7343 std::string genSampleCoordStr(int samplePosNdx) const;
7344 std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
7345 std::string genNoAccessSource(void) const;
7346
7347 vkt::TestInstance *createInstance(vkt::Context &context) const;
7348
7349 private:
7350 const bool m_isPrimaryCmdBuf;
7351 const DescriptorUpdateMethod m_updateMethod;
7352 const vk::VkDescriptorType m_descriptorType;
7353 const DescriptorSetCount m_descriptorSetCount;
7354 const ShaderInputInterface m_shaderInterface;
7355 const vk::VkImageViewType m_viewType;
7356 const uint32_t m_baseMipLevel;
7357 const uint32_t m_baseArraySlice;
7358 const bool m_isImmutableSampler;
7359 const bool m_bind2;
7360 };
7361
ImageDescriptorCase(tcu::TestContext & testCtx,const char * name,bool isPrimaryCmdBuf,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t flags,const bool bind2)7362 ImageDescriptorCase::ImageDescriptorCase(tcu::TestContext &testCtx, const char *name, bool isPrimaryCmdBuf,
7363 DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
7364 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
7365 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
7366 vk::VkImageViewType viewType, uint32_t flags, const bool bind2)
7367 : QuadrantRendederCase(testCtx, name,
7368 // \note 1D textures are not supported in ES
7369 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
7370 glu::GLSL_VERSION_440 :
7371 glu::GLSL_VERSION_310_ES,
7372 exitingStages, activeStages, descriptorSetCount)
7373 , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
7374 , m_updateMethod(updateMethod)
7375 , m_descriptorType(descriptorType)
7376 , m_descriptorSetCount(descriptorSetCount)
7377 , m_shaderInterface(shaderInterface)
7378 , m_viewType(viewType)
7379 , m_baseMipLevel(((flags & FLAG_BASE_MIP) != 0) ? (1u) : (0u))
7380 , m_baseArraySlice(((flags & FLAG_BASE_SLICE) != 0) ? (1u) : (0u))
7381 , m_isImmutableSampler((flags & RESOURCE_FLAG_IMMUTABLE_SAMPLER) != 0)
7382 , m_bind2(bind2)
7383 {
7384 }
7385
checkSupport(Context & context) const7386 void ImageDescriptorCase::checkSupport(Context &context) const
7387 {
7388 if (m_baseMipLevel == 1u)
7389 {
7390 vk::VkImageFormatProperties properties;
7391 const auto &vki = context.getInstanceInterface();
7392 const auto physicalDevice = context.getPhysicalDevice();
7393 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
7394 const vk::VkImageType type = viewTypeToImageType(m_viewType);
7395 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
7396 const bool isStorage = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
7397 const uint32_t readUsage = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
7398 const auto usage = readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
7399
7400 if (vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, 0, &properties) ==
7401 vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
7402 TCU_THROW(NotSupportedError, "Required format not supported");
7403 if (properties.maxMipLevels < 2u)
7404 TCU_THROW(NotSupportedError, "Required mipmap count not supported");
7405 }
7406
7407 if (m_bind2)
7408 context.requireDeviceFunctionality("VK_KHR_maintenance6");
7409 }
7410
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const7411 std::string ImageDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
7412 {
7413 DE_UNREF(stage);
7414
7415 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
7416 return "#extension GL_OES_texture_cube_map_array : require\n";
7417 else
7418 return "";
7419 }
7420
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const7421 std::string ImageDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const
7422 {
7423 DE_UNREF(stage);
7424
7425 // Vulkan-style resources are arrays implicitly, OpenGL-style are not
7426 const std::string dimensionBase =
7427 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1D") :
7428 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2D") :
7429 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D") :
7430 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("Cube") :
7431 (nullptr);
7432 const std::string dimensionArray =
7433 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1DArray") :
7434 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2DArray") :
7435 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D") :
7436 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray") :
7437 (nullptr);
7438 const std::string dimension = isImageViewTypeArray(m_viewType) ? dimensionArray : dimensionBase;
7439 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
7440
7441 std::string buf;
7442
7443 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
7444 {
7445 // Result buffer is bound only to the first descriptor set in compute shader cases
7446 const int descBinding =
7447 numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
7448 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
7449 const uint32_t descriptorSet = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
7450
7451 switch (m_shaderInterface)
7452 {
7453 case SHADER_INPUT_SINGLE_DESCRIPTOR:
7454 {
7455 switch (m_descriptorType)
7456 {
7457 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7458 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7459 ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7460 ";\n"
7461 "layout(set = " +
7462 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7463 ") uniform highp sampler u_separateSampler" + setNdxPostfix + ";\n";
7464 break;
7465 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7466 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7467 ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + ";\n";
7468 break;
7469 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7470 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7471 ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + ";\n";
7472 break;
7473 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7474 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7475 ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + ";\n";
7476 break;
7477 default:
7478 DE_FATAL("invalid descriptor");
7479 }
7480 break;
7481 }
7482 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
7483 {
7484 switch (m_descriptorType)
7485 {
7486 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7487 if (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)
7488 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7489 ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7490 ";\n"
7491 "layout(set = " +
7492 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7493 ") uniform highp sampler u_separateSampler" + setNdxPostfix +
7494 "A;\n"
7495 "layout(set = " +
7496 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7497 ") uniform highp sampler u_separateSampler" + setNdxPostfix + "B;\n";
7498 else
7499 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7500 ") uniform highp sampler u_separateSampler" + setNdxPostfix +
7501 "A;\n"
7502 "layout(set = " +
7503 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7504 ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7505 ";\n"
7506 "layout(set = " +
7507 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7508 ") uniform highp sampler u_separateSampler" + setNdxPostfix + "B;\n";
7509 break;
7510 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7511 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7512 ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix +
7513 "A;\n"
7514 "layout(set = " +
7515 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7516 ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + "B;\n";
7517 break;
7518 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7519 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7520 ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix +
7521 "A;\n"
7522 "layout(set = " +
7523 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7524 ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + "B;\n";
7525 break;
7526 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7527 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7528 ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix +
7529 "A;\n"
7530 "layout(set = " +
7531 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7532 ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + "B;\n";
7533 break;
7534 default:
7535 DE_FATAL("invalid descriptor");
7536 }
7537 break;
7538 }
7539 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
7540 {
7541 switch (m_descriptorType)
7542 {
7543 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7544 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7545 ") uniform highp sampler u_separateSampler" + setNdxPostfix +
7546 "A;\n"
7547 "layout(set = " +
7548 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7549 ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7550 ";\n"
7551 "layout(set = " +
7552 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7553 ") uniform highp sampler u_separateSampler" + setNdxPostfix + "B;\n";
7554 break;
7555 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7556 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7557 ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix +
7558 "A;\n"
7559 "layout(set = " +
7560 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7561 ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + "B;\n";
7562 break;
7563 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7564 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7565 ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix +
7566 "A;\n"
7567 "layout(set = " +
7568 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7569 ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + "B;\n";
7570 break;
7571 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7572 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7573 ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix +
7574 "A;\n"
7575 "layout(set = " +
7576 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7577 ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + "B;\n";
7578 break;
7579 default:
7580 DE_FATAL("invalid descriptor");
7581 }
7582 break;
7583 }
7584 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
7585 {
7586 switch (m_descriptorType)
7587 {
7588 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7589 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7590 ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7591 ";\n"
7592 "layout(set = " +
7593 de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(0)) +
7594 ") uniform highp sampler u_separateSampler" + setNdxPostfix +
7595 "A;\n"
7596 "layout(set = " +
7597 de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(1)) +
7598 ") uniform highp sampler u_separateSampler" + setNdxPostfix + "B;\n";
7599 break;
7600 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7601 buf += "layout(set = " + de::toString(descriptorSet) +
7602 ", binding = " + de::toString(getArbitraryBindingIndex(0)) + ") uniform highp sampler" +
7603 dimension + " u_combinedTextureSampler" + setNdxPostfix +
7604 "A;\n"
7605 "layout(set = " +
7606 de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(1)) +
7607 ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + "B;\n";
7608 break;
7609 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7610 buf += "layout(set = " + de::toString(descriptorSet) +
7611 ", binding = " + de::toString(getArbitraryBindingIndex(0)) + ") uniform highp texture" +
7612 dimensionBase + " u_separateTexture" + setNdxPostfix +
7613 "A;\n"
7614 "layout(set = " +
7615 de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(1)) +
7616 ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + "B;\n";
7617 break;
7618 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7619 buf += "layout(set = " + de::toString(descriptorSet) +
7620 ", binding = " + de::toString(getArbitraryBindingIndex(0)) +
7621 ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix +
7622 "A;\n"
7623 "layout(set = " +
7624 de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(1)) +
7625 ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + "B;\n";
7626 break;
7627 default:
7628 DE_FATAL("invalid descriptor");
7629 }
7630 break;
7631 }
7632 case SHADER_INPUT_DESCRIPTOR_ARRAY:
7633 {
7634 switch (m_descriptorType)
7635 {
7636 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7637 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7638 ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7639 ";\n"
7640 "layout(set = " +
7641 de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7642 ") uniform highp sampler u_separateSampler" + setNdxPostfix + "[2];\n";
7643 break;
7644 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7645 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7646 ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + "[2];\n";
7647 break;
7648 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7649 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7650 ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + "[2];\n";
7651 break;
7652 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7653 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7654 ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + "[2];\n";
7655 break;
7656 default:
7657 DE_FATAL("invalid descriptor");
7658 }
7659 break;
7660 }
7661 default:
7662 DE_FATAL("Impossible");
7663 }
7664 }
7665 return buf;
7666 }
7667
genFetchCoordStr(int fetchPosNdx) const7668 std::string ImageDescriptorCase::genFetchCoordStr(int fetchPosNdx) const
7669 {
7670 DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
7671 m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
7672 const tcu::IVec3 fetchPos =
7673 ImageFetchInstanceImages::getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
7674
7675 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
7676 {
7677 return de::toString(fetchPos.x());
7678 }
7679 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
7680 {
7681 std::ostringstream buf;
7682 buf << "ivec2(" << fetchPos.x() << ", " << fetchPos.y() << ")";
7683 return buf.str();
7684 }
7685 else
7686 {
7687 std::ostringstream buf;
7688 buf << "ivec3(" << fetchPos.x() << ", " << fetchPos.y() << ", " << fetchPos.z() << ")";
7689 return buf.str();
7690 }
7691 }
7692
genSampleCoordStr(int samplePosNdx) const7693 std::string ImageDescriptorCase::genSampleCoordStr(int samplePosNdx) const
7694 {
7695 DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER ||
7696 m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
7697 const tcu::Vec4 fetchPos =
7698 ImageSampleInstanceImages::getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
7699
7700 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
7701 {
7702 std::ostringstream buf;
7703 buf << "float(" << fetchPos.x() << ")";
7704 return buf.str();
7705 }
7706 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
7707 {
7708 std::ostringstream buf;
7709 buf << "vec2(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "))";
7710 return buf.str();
7711 }
7712 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
7713 {
7714 std::ostringstream buf;
7715 buf << "vec4(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z()
7716 << "), float(" << fetchPos.w() << "))";
7717 return buf.str();
7718 }
7719 else
7720 {
7721 std::ostringstream buf;
7722 buf << "vec3(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "))";
7723 return buf.str();
7724 }
7725 }
7726
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const7727 std::string ImageDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
7728 {
7729 DE_UNREF(stage);
7730
7731 const char *const dimension = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D) ? ("1D") :
7732 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1DArray") :
7733 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D) ? ("2D") :
7734 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2DArray") :
7735 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D") :
7736 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE) ? ("Cube") :
7737 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray") :
7738 (nullptr);
7739 const char *const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") :
7740 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("A") :
7741 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("A") :
7742 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? ("A") :
7743 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]") :
7744 (nullptr);
7745 const char *const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") :
7746 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("B") :
7747 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("B") :
7748 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? ("B") :
7749 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]") :
7750 (nullptr);
7751 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
7752
7753 std::ostringstream buf;
7754
7755 buf << " result_color = vec4(0.0);\n";
7756
7757 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
7758 {
7759 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
7760
7761 switch (m_descriptorType)
7762 {
7763 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7764 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7765 {
7766 const std::string coodStr[4] = {
7767 genSampleCoordStr(0),
7768 genSampleCoordStr(1),
7769 genSampleCoordStr(2),
7770 genSampleCoordStr(3),
7771 };
7772
7773 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
7774 {
7775 buf << " if (quadrant_id == 0)\n"
7776 << " result_color += textureLod(sampler" << dimension << "(u_separateTexture"
7777 << setNdxPostfix << ", u_separateSampler" << setNdxPostfix << accessPostfixA << "), " << coodStr[0]
7778 << ", 0.0);\n"
7779 << " else if (quadrant_id == 1)\n"
7780 << " result_color += textureLod(sampler" << dimension << "(u_separateTexture"
7781 << setNdxPostfix << ", u_separateSampler" << setNdxPostfix << accessPostfixB << "), " << coodStr[1]
7782 << ", 0.0);\n"
7783 << " else if (quadrant_id == 2)\n"
7784 << " result_color += textureLod(sampler" << dimension << "(u_separateTexture"
7785 << setNdxPostfix << ", u_separateSampler" << setNdxPostfix << accessPostfixA << "), " << coodStr[2]
7786 << ", 0.0);\n"
7787 << " else\n"
7788 << " result_color += textureLod(sampler" << dimension << "(u_separateTexture"
7789 << setNdxPostfix << ", u_separateSampler" << setNdxPostfix << accessPostfixB << "), " << coodStr[3]
7790 << ", 0.0);\n";
7791 }
7792 else
7793 {
7794 buf << " if (quadrant_id == 0)\n"
7795 << " result_color += textureLod(u_combinedTextureSampler" << setNdxPostfix << accessPostfixA
7796 << ", " << coodStr[0] << ", 0.0);\n"
7797 << " else if (quadrant_id == 1)\n"
7798 << " result_color += textureLod(u_combinedTextureSampler" << setNdxPostfix << accessPostfixB
7799 << ", " << coodStr[1] << ", 0.0);\n"
7800 << " else if (quadrant_id == 2)\n"
7801 << " result_color += textureLod(u_combinedTextureSampler" << setNdxPostfix << accessPostfixA
7802 << ", " << coodStr[2] << ", 0.0);\n"
7803 << " else\n"
7804 << " result_color += textureLod(u_combinedTextureSampler" << setNdxPostfix << accessPostfixB
7805 << ", " << coodStr[3] << ", 0.0);\n";
7806 }
7807 break;
7808 }
7809
7810 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7811 {
7812 const std::string coodStr[4] = {
7813 genFetchCoordStr(0),
7814 genFetchCoordStr(1),
7815 genFetchCoordStr(2),
7816 genFetchCoordStr(3),
7817 };
7818
7819 buf << " if (quadrant_id == 0)\n"
7820 << " result_color += imageLoad(u_image" << setNdxPostfix << accessPostfixA << ", " << coodStr[0]
7821 << ");\n"
7822 << " else if (quadrant_id == 1)\n"
7823 << " result_color += imageLoad(u_image" << setNdxPostfix << accessPostfixB << ", " << coodStr[1]
7824 << ");\n"
7825 << " else if (quadrant_id == 2)\n"
7826 << " result_color += imageLoad(u_image" << setNdxPostfix << accessPostfixA << ", " << coodStr[2]
7827 << ");\n"
7828 << " else\n"
7829 << " result_color += imageLoad(u_image" << setNdxPostfix << accessPostfixB << ", " << coodStr[3]
7830 << ");\n";
7831 break;
7832 }
7833
7834 default:
7835 DE_FATAL("invalid descriptor");
7836 }
7837 }
7838
7839 if (getDescriptorSetCount(m_descriptorSetCount) > 1)
7840 buf << " result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
7841
7842 return buf.str();
7843 }
7844
genNoAccessSource(void) const7845 std::string ImageDescriptorCase::genNoAccessSource(void) const
7846 {
7847 return " if (quadrant_id == 1 || quadrant_id == 2)\n"
7848 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
7849 " else\n"
7850 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
7851 }
7852
createInstance(vkt::Context & context) const7853 vkt::TestInstance *ImageDescriptorCase::createInstance(vkt::Context &context) const
7854 {
7855 verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
7856 m_updateMethod, m_descriptorType, m_activeStages, m_viewType);
7857
7858 switch (m_descriptorType)
7859 {
7860 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7861 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7862 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
7863 {
7864 DE_ASSERT(m_isPrimaryCmdBuf);
7865 return new ImageSampleComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
7866 m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice,
7867 m_isImmutableSampler, m_bind2);
7868 }
7869 else
7870 return new ImageSampleRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
7871 m_descriptorSetCount, m_activeStages, m_exitingStages,
7872 m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice,
7873 m_isImmutableSampler, m_bind2);
7874
7875 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7876 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7877 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
7878 {
7879 DE_ASSERT(m_isPrimaryCmdBuf);
7880 return new ImageFetchComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
7881 m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice,
7882 m_bind2);
7883 }
7884 else
7885 return new ImageFetchRenderInstance(
7886 context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType, m_descriptorSetCount, m_activeStages,
7887 m_exitingStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_bind2);
7888
7889 default:
7890 DE_FATAL("Impossible");
7891 return nullptr;
7892 }
7893 }
7894
7895 class TexelBufferInstanceBuffers
7896 {
7897 public:
7898 TexelBufferInstanceBuffers(vkt::Context &context, const vk::DeviceInterface &vki, vk::VkDevice device,
7899 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
7900 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
7901 bool hasViewOffset);
7902
7903 private:
7904 static std::vector<de::ArrayBuffer<uint8_t>> createSourceBuffers(tcu::TextureFormat imageFormat,
7905 uint32_t numTexelBuffers);
7906
7907 static std::vector<tcu::ConstPixelBufferAccess> createSourceViews(
7908 const std::vector<de::ArrayBuffer<uint8_t>> &sourceBuffers, tcu::TextureFormat imageFormat,
7909 uint32_t numTexelBuffers, uint32_t viewOffset);
7910
7911 static std::vector<BufferHandleSp> createBuffers(const vk::DeviceInterface &vki, vk::VkDevice device,
7912 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
7913 const std::vector<de::ArrayBuffer<uint8_t>> &sourceBuffers,
7914 std::vector<AllocationSp> &bufferMemory,
7915 tcu::TextureFormat imageFormat, uint32_t numTexelBuffers,
7916 uint32_t viewOffset);
7917
7918 static std::vector<BufferViewHandleSp> createBufferViews(const vk::DeviceInterface &vki, vk::VkDevice device,
7919 const std::vector<BufferHandleSp> &buffers,
7920 tcu::TextureFormat imageFormat, uint32_t numTexelBuffers,
7921 uint32_t viewOffset);
7922
7923 static std::vector<vk::VkBufferMemoryBarrier> createBufferBarriers(vk::VkDescriptorType descriptorType,
7924 const std::vector<BufferHandleSp> &buffers,
7925 uint32_t numTexelBuffers);
7926
7927 static vk::Move<vk::VkBuffer> createBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
7928 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
7929 de::MovePtr<vk::Allocation> *outAllocation);
7930
7931 static vk::Move<vk::VkBufferView> createBufferView(const vk::DeviceInterface &vki, vk::VkDevice device,
7932 const tcu::TextureFormat &textureFormat, uint32_t offset,
7933 vk::VkBuffer buffer);
7934
7935 static vk::VkBufferMemoryBarrier createBarrier(vk::VkDescriptorType descriptorType, vk::VkBuffer buffer);
7936
7937 static void populateSourceBuffer(const tcu::PixelBufferAccess &access, uint32_t bufferNdx);
7938
7939 static void uploadData(const vk::DeviceInterface &vki, vk::VkDevice device, const vk::Allocation &memory,
7940 const de::ArrayBuffer<uint8_t> &data);
7941
7942 uint32_t getViewOffset(vkt::Context &context, bool hasViewOffset, vk::VkDescriptorType descriptorType);
7943
7944 public:
7945 static int getFetchPos(int fetchPosNdx);
7946 tcu::Vec4 fetchTexelValue(int fetchPosNdx, int setNdx) const;
7947
getNumTexelBuffers(void) const7948 inline int getNumTexelBuffers(void) const
7949 {
7950 return m_numTexelBuffers;
7951 }
getTextureFormat(void) const7952 const tcu::TextureFormat &getTextureFormat(void) const
7953 {
7954 return m_imageFormat;
7955 }
getBufferView(int ndx) const7956 inline vk::VkBufferView getBufferView(int ndx) const
7957 {
7958 return **m_bufferView[ndx % m_bufferView.size()];
7959 }
getSourceView(int ndx) const7960 inline tcu::ConstPixelBufferAccess getSourceView(int ndx) const
7961 {
7962 return m_sourceView[ndx % m_sourceView.size()];
7963 }
getBufferInitBarriers(void) const7964 inline const vk::VkBufferMemoryBarrier *getBufferInitBarriers(void) const
7965 {
7966 return &m_bufferBarrier.front();
7967 }
7968
7969 private:
7970 enum
7971 {
7972 BUFFER_SIZE = 512,
7973 VIEW_DATA_SIZE = 256, //!< size in bytes
7974 VIEW_WIDTH = 64, //!< size in pixels
7975 };
7976 enum
7977 {
7978 // some arbitrary points
7979 SAMPLE_POINT_0 = 6,
7980 SAMPLE_POINT_1 = 51,
7981 SAMPLE_POINT_2 = 42,
7982 SAMPLE_POINT_3 = 25,
7983 };
7984
7985 const uint32_t m_numTexelBuffers;
7986 const tcu::TextureFormat m_imageFormat;
7987 const ShaderInputInterface m_shaderInterface;
7988 const uint32_t m_viewOffset;
7989
7990 const std::vector<de::ArrayBuffer<uint8_t>> m_sourceBuffer;
7991 const std::vector<tcu::ConstPixelBufferAccess> m_sourceView;
7992
7993 std::vector<AllocationSp> m_bufferMemory;
7994 const std::vector<BufferHandleSp> m_buffer;
7995 const std::vector<BufferViewHandleSp> m_bufferView;
7996 const std::vector<vk::VkBufferMemoryBarrier> m_bufferBarrier;
7997 };
7998
getViewOffset(vkt::Context & context,bool hasViewOffset,vk::VkDescriptorType descriptorType)7999 uint32_t TexelBufferInstanceBuffers::getViewOffset(vkt::Context &context, bool hasViewOffset,
8000 vk::VkDescriptorType descriptorType)
8001 {
8002 if (!hasViewOffset)
8003 return 0u;
8004
8005 if (!context.getTexelBufferAlignmentFeaturesEXT().texelBufferAlignment)
8006 return (uint32_t)context.getDeviceProperties().limits.minTexelBufferOffsetAlignment;
8007
8008 vk::VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT alignmentProperties;
8009 deMemset(&alignmentProperties, 0, sizeof(alignmentProperties));
8010 alignmentProperties.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT;
8011
8012 vk::VkPhysicalDeviceProperties2 properties2;
8013 deMemset(&properties2, 0, sizeof(properties2));
8014 properties2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
8015 properties2.pNext = &alignmentProperties;
8016
8017 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);
8018
8019 vk::VkBool32 singleTexelAlignment = isUniformDescriptorType(descriptorType) ?
8020 alignmentProperties.uniformTexelBufferOffsetSingleTexelAlignment :
8021 alignmentProperties.storageTexelBufferOffsetSingleTexelAlignment;
8022 vk::VkDeviceSize align = isUniformDescriptorType(descriptorType) ?
8023 alignmentProperties.uniformTexelBufferOffsetAlignmentBytes :
8024 alignmentProperties.storageTexelBufferOffsetAlignmentBytes;
8025
8026 // format is rgba8
8027 if (singleTexelAlignment)
8028 return de::min(4u, (uint32_t)align);
8029 else
8030 return (uint32_t)align;
8031 }
8032
TexelBufferInstanceBuffers(vkt::Context & context,const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool hasViewOffset)8033 TexelBufferInstanceBuffers::TexelBufferInstanceBuffers(vkt::Context &context, const vk::DeviceInterface &vki,
8034 vk::VkDevice device, vk::Allocator &allocator,
8035 vk::VkDescriptorType descriptorType,
8036 DescriptorSetCount descriptorSetCount,
8037 ShaderInputInterface shaderInterface, bool hasViewOffset)
8038 : m_numTexelBuffers(getInterfaceNumResources(shaderInterface) * getDescriptorSetCount(descriptorSetCount))
8039 , m_imageFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
8040 , m_shaderInterface(shaderInterface)
8041 , m_viewOffset(getViewOffset(context, hasViewOffset, descriptorType))
8042 , m_sourceBuffer(createSourceBuffers(m_imageFormat, m_numTexelBuffers))
8043 , m_sourceView(createSourceViews(m_sourceBuffer, m_imageFormat, m_numTexelBuffers, m_viewOffset))
8044 , m_bufferMemory()
8045 , m_buffer(createBuffers(vki, device, allocator, descriptorType, m_sourceBuffer, m_bufferMemory, m_imageFormat,
8046 m_numTexelBuffers, m_viewOffset))
8047 , m_bufferView(createBufferViews(vki, device, m_buffer, m_imageFormat, m_numTexelBuffers, m_viewOffset))
8048 , m_bufferBarrier(createBufferBarriers(descriptorType, m_buffer, m_numTexelBuffers))
8049 {
8050 }
8051
createSourceBuffers(tcu::TextureFormat imageFormat,uint32_t numTexelBuffers)8052 std::vector<de::ArrayBuffer<uint8_t>> TexelBufferInstanceBuffers::createSourceBuffers(tcu::TextureFormat imageFormat,
8053 uint32_t numTexelBuffers)
8054 {
8055 DE_ASSERT(BUFFER_SIZE % imageFormat.getPixelSize() == 0);
8056
8057 std::vector<de::ArrayBuffer<uint8_t>> sourceBuffers(numTexelBuffers, BUFFER_SIZE);
8058
8059 for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8060 populateSourceBuffer(tcu::PixelBufferAccess(imageFormat,
8061 tcu::IVec3(BUFFER_SIZE / imageFormat.getPixelSize(), 1, 1),
8062 sourceBuffers[bufferNdx].getPtr()),
8063 bufferNdx);
8064
8065 return sourceBuffers;
8066 }
8067
createSourceViews(const std::vector<de::ArrayBuffer<uint8_t>> & sourceBuffers,tcu::TextureFormat imageFormat,uint32_t numTexelBuffers,uint32_t viewOffset)8068 std::vector<tcu::ConstPixelBufferAccess> TexelBufferInstanceBuffers::createSourceViews(
8069 const std::vector<de::ArrayBuffer<uint8_t>> &sourceBuffers, tcu::TextureFormat imageFormat,
8070 uint32_t numTexelBuffers, uint32_t viewOffset)
8071 {
8072 std::vector<tcu::ConstPixelBufferAccess> sourceViews;
8073
8074 for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8075 sourceViews.push_back(tcu::ConstPixelBufferAccess(imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1),
8076 sourceBuffers[bufferNdx].getElementPtr(viewOffset)));
8077
8078 return sourceViews;
8079 }
8080
createBuffers(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,const std::vector<de::ArrayBuffer<uint8_t>> & sourceBuffers,std::vector<AllocationSp> & bufferMemory,tcu::TextureFormat imageFormat,uint32_t numTexelBuffers,uint32_t viewOffset)8081 std::vector<BufferHandleSp> TexelBufferInstanceBuffers::createBuffers(
8082 const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
8083 const std::vector<de::ArrayBuffer<uint8_t>> &sourceBuffers, std::vector<AllocationSp> &bufferMemory,
8084 tcu::TextureFormat imageFormat, uint32_t numTexelBuffers, uint32_t viewOffset)
8085 {
8086 std::vector<BufferHandleSp> buffers;
8087
8088 for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8089 {
8090 de::MovePtr<vk::Allocation> memory;
8091 vk::Move<vk::VkBuffer> buffer = createBuffer(vki, device, allocator, descriptorType, &memory);
8092 vk::Move<vk::VkBufferView> bufferView = createBufferView(vki, device, imageFormat, viewOffset, *buffer);
8093
8094 uploadData(vki, device, *memory, sourceBuffers[bufferNdx]);
8095
8096 bufferMemory.push_back(AllocationSp(memory.release()));
8097 buffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
8098 }
8099
8100 return buffers;
8101 }
8102
createBufferViews(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<BufferHandleSp> & buffers,tcu::TextureFormat imageFormat,uint32_t numTexelBuffers,uint32_t viewOffset)8103 std::vector<BufferViewHandleSp> TexelBufferInstanceBuffers::createBufferViews(
8104 const vk::DeviceInterface &vki, vk::VkDevice device, const std::vector<BufferHandleSp> &buffers,
8105 tcu::TextureFormat imageFormat, uint32_t numTexelBuffers, uint32_t viewOffset)
8106 {
8107 std::vector<BufferViewHandleSp> bufferViews;
8108
8109 for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8110 {
8111 vk::Move<vk::VkBufferView> bufferView =
8112 createBufferView(vki, device, imageFormat, viewOffset, **buffers[bufferNdx]);
8113 bufferViews.push_back(BufferViewHandleSp(new BufferViewHandleUp(bufferView)));
8114 }
8115
8116 return bufferViews;
8117 }
8118
createBufferBarriers(vk::VkDescriptorType descriptorType,const std::vector<BufferHandleSp> & buffers,uint32_t numTexelBuffers)8119 std::vector<vk::VkBufferMemoryBarrier> TexelBufferInstanceBuffers::createBufferBarriers(
8120 vk::VkDescriptorType descriptorType, const std::vector<BufferHandleSp> &buffers, uint32_t numTexelBuffers)
8121 {
8122 std::vector<vk::VkBufferMemoryBarrier> bufferBarriers;
8123
8124 for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8125 bufferBarriers.push_back(createBarrier(descriptorType, **buffers[bufferNdx]));
8126
8127 return bufferBarriers;
8128 }
8129
createBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,de::MovePtr<vk::Allocation> * outAllocation)8130 vk::Move<vk::VkBuffer> TexelBufferInstanceBuffers::createBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
8131 vk::Allocator &allocator,
8132 vk::VkDescriptorType descriptorType,
8133 de::MovePtr<vk::Allocation> *outAllocation)
8134 {
8135 const vk::VkBufferUsageFlags usage = (isUniformDescriptorType(descriptorType)) ?
8136 (vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) :
8137 (vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
8138 const vk::VkBufferCreateInfo createInfo = {
8139 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
8140 nullptr,
8141 0u, // flags
8142 (vk::VkDeviceSize)BUFFER_SIZE, // size
8143 usage, // usage
8144 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
8145 0u, // queueFamilyCount
8146 nullptr, // pQueueFamilyIndices
8147 };
8148 vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &createInfo));
8149 de::MovePtr<vk::Allocation> allocation(
8150 allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
8151
8152 *outAllocation = allocation;
8153 return buffer;
8154 }
8155
createBufferView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & textureFormat,uint32_t offset,vk::VkBuffer buffer)8156 vk::Move<vk::VkBufferView> TexelBufferInstanceBuffers::createBufferView(const vk::DeviceInterface &vki,
8157 vk::VkDevice device,
8158 const tcu::TextureFormat &textureFormat,
8159 uint32_t offset, vk::VkBuffer buffer)
8160 {
8161 const vk::VkBufferViewCreateInfo createInfo = {
8162 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
8163 nullptr,
8164 (vk::VkBufferViewCreateFlags)0,
8165 buffer, // buffer
8166 vk::mapTextureFormat(textureFormat), // format
8167 (vk::VkDeviceSize)offset, // offset
8168 (vk::VkDeviceSize)VIEW_DATA_SIZE // range
8169 };
8170 return vk::createBufferView(vki, device, &createInfo);
8171 }
8172
createBarrier(vk::VkDescriptorType descriptorType,vk::VkBuffer buffer)8173 vk::VkBufferMemoryBarrier TexelBufferInstanceBuffers::createBarrier(vk::VkDescriptorType descriptorType,
8174 vk::VkBuffer buffer)
8175 {
8176 const vk::VkAccessFlags inputBit =
8177 (isUniformDescriptorType(descriptorType)) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
8178 const vk::VkBufferMemoryBarrier barrier = {
8179 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
8180 nullptr,
8181 vk::VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
8182 inputBit, // dstAccessMask
8183 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
8184 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
8185 buffer, // buffer
8186 0u, // offset
8187 (vk::VkDeviceSize)BUFFER_SIZE // size
8188 };
8189 return barrier;
8190 }
8191
populateSourceBuffer(const tcu::PixelBufferAccess & access,uint32_t bufferNdx)8192 void TexelBufferInstanceBuffers::populateSourceBuffer(const tcu::PixelBufferAccess &access, uint32_t bufferNdx)
8193 {
8194 DE_ASSERT(access.getHeight() == 1);
8195 DE_ASSERT(access.getDepth() == 1);
8196
8197 const int32_t width = access.getWidth();
8198
8199 for (int x = 0; x < width; ++x)
8200 {
8201 int red = 255 * x / width; //!< gradient from 0 -> max (detects large offset errors)
8202 int green = ((x % 2 == 0) ? (127) : (0)) +
8203 ((x % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
8204 int blue = 16 * (x % 16); //!< 16-long triangle wave
8205
8206 DE_ASSERT(de::inRange(red, 0, 255));
8207 DE_ASSERT(de::inRange(green, 0, 255));
8208 DE_ASSERT(de::inRange(blue, 0, 255));
8209
8210 if (bufferNdx % 2 == 0)
8211 red = 255 - red;
8212 if (bufferNdx % 3 == 0)
8213 green = 255 - green;
8214 if (bufferNdx % 4 == 0)
8215 blue = 255 - blue;
8216
8217 access.setPixel(tcu::IVec4(red, green, blue, 255), x, 0, 0);
8218 }
8219 }
8220
uploadData(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::Allocation & memory,const de::ArrayBuffer<uint8_t> & data)8221 void TexelBufferInstanceBuffers::uploadData(const vk::DeviceInterface &vki, vk::VkDevice device,
8222 const vk::Allocation &memory, const de::ArrayBuffer<uint8_t> &data)
8223 {
8224 deMemcpy(memory.getHostPtr(), data.getPtr(), data.size());
8225 flushAlloc(vki, device, memory);
8226 }
8227
getFetchPos(int fetchPosNdx)8228 int TexelBufferInstanceBuffers::getFetchPos(int fetchPosNdx)
8229 {
8230 static const int fetchPositions[4] = {
8231 SAMPLE_POINT_0,
8232 SAMPLE_POINT_1,
8233 SAMPLE_POINT_2,
8234 SAMPLE_POINT_3,
8235 };
8236 return de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
8237 }
8238
fetchTexelValue(int fetchPosNdx,int setNdx) const8239 tcu::Vec4 TexelBufferInstanceBuffers::fetchTexelValue(int fetchPosNdx, int setNdx) const
8240 {
8241 // source order is ABAB
8242 const tcu::ConstPixelBufferAccess &texelSrcA = getSourceView(setNdx * getInterfaceNumResources(m_shaderInterface));
8243 const tcu::ConstPixelBufferAccess &texelSrcB =
8244 getSourceView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
8245 const tcu::ConstPixelBufferAccess &texelSrc = ((fetchPosNdx % 2) == 0) ? (texelSrcA) : (texelSrcB);
8246
8247 return texelSrc.getPixel(getFetchPos(fetchPosNdx), 0, 0);
8248 }
8249
8250 class TexelBufferRenderInstance : public SingleCmdRenderInstance
8251 {
8252 public:
8253 TexelBufferRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
8254 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
8255 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
8256 ShaderInputInterface shaderInterface, bool nonzeroViewOffset, const bool bind2);
8257
8258 private:
8259 static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
8260 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
8261 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
8262 DescriptorUpdateMethod updateMethod);
8263
8264 static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
8265 const vk::DeviceInterface &vki, vk::VkDevice device,
8266 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
8267
8268 static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
8269 vk::VkDescriptorType descriptorType,
8270 DescriptorSetCount descriptorSetCount,
8271 ShaderInputInterface shaderInterface);
8272
8273 static std::vector<DescriptorSetHandleSp> createDescriptorSets(
8274 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
8275 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
8276 ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
8277 vk::VkDescriptorPool pool, const TexelBufferInstanceBuffers &buffers,
8278 vk::DescriptorSetUpdateBuilder &updateBuilder,
8279 #ifndef CTS_USES_VULKANSC
8280 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
8281 #endif
8282 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
8283
8284 static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
8285 vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
8286 vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool, vk::VkBufferView viewA,
8287 vk::VkBufferView viewB, vk::VkDescriptorSet descriptorSet,
8288 vk::DescriptorSetUpdateBuilder &updateBuilder,
8289 std::vector<uint32_t> &descriptorsPerSet,
8290 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
8291
8292 #ifndef CTS_USES_VULKANSC
8293 static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
8294 vk::VkDescriptorType descriptorType,
8295 ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout,
8296 uint32_t setNdx, vk::VkDescriptorPool pool, vk::VkBufferView viewA,
8297 vk::VkBufferView viewB, vk::VkDescriptorSet descriptorSet,
8298 std::vector<UpdateTemplateHandleSp> &updateTemplates,
8299 std::vector<RawUpdateRegistry> ®istry, bool withPush = false,
8300 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
8301 #endif
8302
8303 void logTestPlan(void) const;
8304 vk::VkPipelineLayout getPipelineLayout(void) const;
8305 void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
8306 tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
8307
8308 enum
8309 {
8310 RENDER_SIZE = 128,
8311 };
8312
8313 const DescriptorUpdateMethod m_updateMethod;
8314 const vk::VkDescriptorType m_descriptorType;
8315 const DescriptorSetCount m_descriptorSetCount;
8316 const vk::VkShaderStageFlags m_stageFlags;
8317 const vk::VkShaderStageFlags m_existingStages;
8318 const ShaderInputInterface m_shaderInterface;
8319 const bool m_nonzeroViewOffset;
8320
8321 #ifndef CTS_USES_VULKANSC
8322 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
8323 std::vector<RawUpdateRegistry> m_updateRegistry;
8324 #endif
8325 vk::DescriptorSetUpdateBuilder m_updateBuilder;
8326 const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
8327 const vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
8328 const TexelBufferInstanceBuffers m_texelBuffers;
8329 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
8330 std::vector<uint32_t> m_descriptorsPerSet;
8331 const std::vector<DescriptorSetHandleSp> m_descriptorSets;
8332 };
8333
TexelBufferRenderInstance(vkt::Context & context,DescriptorUpdateMethod updateMethod,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,ShaderInputInterface shaderInterface,bool nonzeroViewOffset,const bool bind2)8334 TexelBufferRenderInstance::TexelBufferRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
8335 bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
8336 DescriptorSetCount descriptorSetCount,
8337 vk::VkShaderStageFlags stageFlags,
8338 vk::VkShaderStageFlags existingStages,
8339 ShaderInputInterface shaderInterface, bool nonzeroViewOffset,
8340 const bool bind2)
8341 : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
8342 , m_updateMethod(updateMethod)
8343 , m_descriptorType(descriptorType)
8344 , m_descriptorSetCount(descriptorSetCount)
8345 , m_stageFlags(stageFlags)
8346 , m_existingStages(existingStages)
8347 , m_shaderInterface(shaderInterface)
8348 , m_nonzeroViewOffset(nonzeroViewOffset)
8349 #ifndef CTS_USES_VULKANSC
8350 , m_updateTemplates()
8351 , m_updateRegistry()
8352 #endif
8353 , m_updateBuilder()
8354 , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
8355 m_shaderInterface, m_stageFlags, m_updateMethod))
8356 , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
8357 , m_texelBuffers(context, m_vki, m_device, m_allocator, m_descriptorType, m_descriptorSetCount, m_shaderInterface,
8358 m_nonzeroViewOffset)
8359 , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
8360 , m_descriptorsPerSet()
8361 , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
8362 m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool,
8363 m_texelBuffers, m_updateBuilder,
8364 #ifndef CTS_USES_VULKANSC
8365 m_updateTemplates, m_updateRegistry,
8366 #endif
8367 m_descriptorsPerSet, *m_pipelineLayout))
8368 {
8369 }
8370
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)8371 std::vector<DescriptorSetLayoutHandleSp> TexelBufferRenderInstance::createDescriptorSetLayouts(
8372 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
8373 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
8374 DescriptorUpdateMethod updateMethod)
8375 {
8376 #ifdef CTS_USES_VULKANSC
8377 DE_UNREF(updateMethod);
8378 #endif
8379 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
8380
8381 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
8382 {
8383 vk::DescriptorSetLayoutBuilder builder;
8384 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
8385
8386 #ifndef CTS_USES_VULKANSC
8387 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
8388 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8389 {
8390 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
8391 }
8392 #endif
8393
8394 switch (shaderInterface)
8395 {
8396 case SHADER_INPUT_SINGLE_DESCRIPTOR:
8397 builder.addSingleBinding(descriptorType, stageFlags);
8398 break;
8399
8400 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
8401 builder.addSingleBinding(descriptorType, stageFlags);
8402 builder.addSingleBinding(descriptorType, stageFlags);
8403 break;
8404
8405 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
8406 builder.addSingleIndexedBinding(descriptorType, stageFlags, 0);
8407 builder.addSingleIndexedBinding(descriptorType, stageFlags, 2);
8408 break;
8409
8410 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
8411 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
8412 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
8413 break;
8414
8415 case SHADER_INPUT_DESCRIPTOR_ARRAY:
8416 builder.addArrayBinding(descriptorType, 2u, stageFlags);
8417 break;
8418
8419 default:
8420 DE_FATAL("Impossible");
8421 }
8422
8423 vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
8424 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
8425
8426 // Add an empty descriptor set layout between sets 0 and 2
8427 if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
8428 {
8429 vk::DescriptorSetLayoutBuilder emptyBuilder;
8430 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
8431 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
8432 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
8433 }
8434 }
8435 return descriptorSetLayouts;
8436 }
8437
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)8438 vk::Move<vk::VkPipelineLayout> TexelBufferRenderInstance::createPipelineLayout(
8439 const vk::DeviceInterface &vki, vk::VkDevice device,
8440 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
8441 {
8442 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
8443 for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
8444 layoutHandles.push_back(**descriptorSetLayout[setNdx]);
8445
8446 const vk::VkPipelineLayoutCreateInfo createInfo = {
8447 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
8448 nullptr,
8449 (vk::VkPipelineLayoutCreateFlags)0,
8450 (uint32_t)layoutHandles.size(), // descriptorSetCount
8451 &layoutHandles.front(), // pSetLayouts
8452 0u, // pushConstantRangeCount
8453 nullptr, // pPushConstantRanges
8454 };
8455 return vk::createPipelineLayout(vki, device, &createInfo);
8456 }
8457
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)8458 vk::Move<vk::VkDescriptorPool> TexelBufferRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
8459 vk::VkDevice device,
8460 vk::VkDescriptorType descriptorType,
8461 DescriptorSetCount descriptorSetCount,
8462 ShaderInputInterface shaderInterface)
8463 {
8464 return vk::DescriptorPoolBuilder()
8465 .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
8466 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
8467 getDescriptorSetCount(descriptorSetCount));
8468 }
8469
createDescriptorSets(const vk::DeviceInterface & vki,DescriptorUpdateMethod updateMethod,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayouts,vk::VkDescriptorPool pool,const TexelBufferInstanceBuffers & buffers,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & updateRegistry,std::vector<uint32_t> & descriptorsPerSet,vk::VkPipelineLayout pipelineLayout)8470 std::vector<DescriptorSetHandleSp> TexelBufferRenderInstance::createDescriptorSets(
8471 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
8472 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
8473 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool,
8474 const TexelBufferInstanceBuffers &buffers, vk::DescriptorSetUpdateBuilder &updateBuilder,
8475 #ifndef CTS_USES_VULKANSC
8476 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
8477 #endif
8478 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
8479 {
8480 #ifdef CTS_USES_VULKANSC
8481 DE_UNREF(pipelineLayout);
8482 #endif
8483 std::vector<DescriptorSetHandleSp> descriptorSets;
8484
8485 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
8486 {
8487 vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
8488
8489 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
8490 pool, 1u, &layout};
8491
8492 vk::VkBufferView viewA = buffers.getBufferView(setNdx * getInterfaceNumResources(shaderInterface));
8493 vk::VkBufferView viewB = buffers.getBufferView(setNdx * getInterfaceNumResources(shaderInterface) + 1);
8494
8495 vk::Move<vk::VkDescriptorSet> descriptorSet;
8496
8497 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
8498 updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
8499 {
8500 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
8501 }
8502 else
8503 {
8504 descriptorSet = vk::Move<vk::VkDescriptorSet>();
8505 }
8506
8507 #ifndef CTS_USES_VULKANSC
8508 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
8509 {
8510 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, setNdx, pool, viewA,
8511 viewB, *descriptorSet, updateTemplates, updateRegistry);
8512 }
8513 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
8514 {
8515 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, setNdx, pool, viewA,
8516 viewB, *descriptorSet, updateTemplates, updateRegistry, true,
8517 pipelineLayout);
8518 }
8519 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8520 {
8521 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
8522 updateBuilder, descriptorsPerSet, updateMethod);
8523 }
8524 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
8525 #endif
8526 {
8527 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
8528 updateBuilder, descriptorsPerSet);
8529 }
8530
8531 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
8532 }
8533
8534 return descriptorSets;
8535 }
8536
writeDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkBufferView viewA,vk::VkBufferView viewB,vk::VkDescriptorSet descriptorSet,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)8537 void TexelBufferRenderInstance::writeDescriptorSet(
8538 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
8539 ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
8540 vk::VkBufferView viewA, vk::VkBufferView viewB, vk::VkDescriptorSet descriptorSet,
8541 vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
8542 DescriptorUpdateMethod updateMethod)
8543 {
8544 DE_UNREF(layout);
8545 DE_UNREF(pool);
8546 const vk::VkBufferView texelBufferInfos[2] = {
8547 viewA,
8548 viewB,
8549 };
8550 uint32_t numDescriptors = 0u;
8551
8552 switch (shaderInterface)
8553 {
8554 case SHADER_INPUT_SINGLE_DESCRIPTOR:
8555 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
8556 &texelBufferInfos[0]);
8557 numDescriptors++;
8558 break;
8559
8560 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
8561 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
8562 &texelBufferInfos[0]);
8563 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
8564 &texelBufferInfos[1]);
8565 numDescriptors += 2;
8566 break;
8567
8568 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
8569 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
8570 &texelBufferInfos[0]);
8571 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
8572 &texelBufferInfos[1]);
8573 numDescriptors += 2;
8574 break;
8575
8576 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
8577 updateBuilder.writeSingle(descriptorSet,
8578 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
8579 descriptorType, &texelBufferInfos[0]);
8580 updateBuilder.writeSingle(descriptorSet,
8581 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
8582 descriptorType, &texelBufferInfos[1]);
8583 numDescriptors += 2;
8584 break;
8585
8586 case SHADER_INPUT_DESCRIPTOR_ARRAY:
8587 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
8588 2u, texelBufferInfos);
8589 numDescriptors++;
8590 break;
8591
8592 default:
8593 DE_FATAL("Impossible");
8594 }
8595
8596 descriptorsPerSet.push_back(numDescriptors);
8597
8598 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
8599 {
8600 updateBuilder.update(vki, device);
8601 updateBuilder.clear();
8602 }
8603 }
8604
8605 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkDescriptorPool pool,vk::VkBufferView viewA,vk::VkBufferView viewB,vk::VkDescriptorSet descriptorSet,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)8606 void TexelBufferRenderInstance::writeDescriptorSetWithTemplate(
8607 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
8608 ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, uint32_t setNdx, vk::VkDescriptorPool pool,
8609 vk::VkBufferView viewA, vk::VkBufferView viewB, vk::VkDescriptorSet descriptorSet,
8610 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry, bool withPush,
8611 vk::VkPipelineLayout pipelineLayout)
8612 {
8613 DE_UNREF(pool);
8614 const vk::VkBufferView texelBufferInfos[2] = {
8615 viewA,
8616 viewB,
8617 };
8618 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
8619 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
8620 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
8621 nullptr,
8622 0,
8623 0, // updateCount
8624 nullptr, // pUpdates
8625 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
8626 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
8627 layout,
8628 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
8629 pipelineLayout,
8630 setNdx};
8631
8632 RawUpdateRegistry updateRegistry;
8633
8634 updateRegistry.addWriteObject(texelBufferInfos[0]);
8635 updateRegistry.addWriteObject(texelBufferInfos[1]);
8636
8637 switch (shaderInterface)
8638 {
8639 case SHADER_INPUT_SINGLE_DESCRIPTOR:
8640 updateEntries.push_back(
8641 createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
8642 break;
8643
8644 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
8645 updateEntries.push_back(
8646 createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
8647 updateEntries.push_back(
8648 createTemplateBinding(1, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
8649 break;
8650
8651 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
8652 updateEntries.push_back(
8653 createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
8654 updateEntries.push_back(
8655 createTemplateBinding(2, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
8656 break;
8657
8658 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
8659 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
8660 updateRegistry.getWriteObjectOffset(0), 0));
8661 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
8662 updateRegistry.getWriteObjectOffset(1), 0));
8663 break;
8664
8665 case SHADER_INPUT_DESCRIPTOR_ARRAY:
8666 updateEntries.push_back(createTemplateBinding(0, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
8667 sizeof(texelBufferInfos[0])));
8668 break;
8669
8670 default:
8671 DE_FATAL("Impossible");
8672 }
8673
8674 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
8675 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
8676
8677 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
8678 vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
8679 updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
8680 registry.push_back(updateRegistry);
8681
8682 if (!withPush)
8683 {
8684 vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
8685 registry.back().getRawPointer());
8686 }
8687 }
8688 #endif
8689
logTestPlan(void) const8690 void TexelBufferRenderInstance::logTestPlan(void) const
8691 {
8692 std::ostringstream msg;
8693
8694 msg << "Rendering 2x2 grid.\n"
8695 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
8696 "Multiple descriptor sets. ")
8697 << "Each descriptor set contains "
8698 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
8699 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
8700 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
8701 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
8702 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
8703 nullptr)
8704 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
8705 << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
8706 << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
8707
8708 if (m_stageFlags == 0u)
8709 {
8710 msg << "Descriptors are not accessed in any shader stage.\n";
8711 }
8712 else
8713 {
8714 msg << "Color in each cell is fetched using the descriptor(s):\n";
8715
8716 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
8717 {
8718 msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
8719
8720 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
8721 {
8722 const int srcResourceNdx = (resultNdx % 2); // ABAB source
8723 msg << " from texelBuffer " << srcResourceNdx;
8724 }
8725
8726 msg << "\n";
8727 }
8728
8729 msg << "Descriptors are accessed in {"
8730 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
8731 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
8732 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
8733 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
8734 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.";
8735 }
8736
8737 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
8738 }
8739
getPipelineLayout(void) const8740 vk::VkPipelineLayout TexelBufferRenderInstance::getPipelineLayout(void) const
8741 {
8742 return *m_pipelineLayout;
8743 }
8744
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const8745 void TexelBufferRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
8746 {
8747 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
8748 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8749 {
8750 std::vector<vk::VkDescriptorSet> sets;
8751 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
8752 sets.push_back(**m_descriptorSets[setNdx]);
8753
8754 switch (m_descriptorSetCount)
8755 {
8756 case DESCRIPTOR_SET_COUNT_SINGLE:
8757 case DESCRIPTOR_SET_COUNT_MULTIPLE:
8758 {
8759 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
8760 getPipelineLayout(), 0, (uint32_t)sets.size(), &sets.front(), 0, nullptr, m_bind2);
8761 break;
8762 }
8763 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
8764 {
8765 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
8766 {
8767 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
8768 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
8769 getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], 0, nullptr, m_bind2);
8770 }
8771 break;
8772 }
8773 default:
8774 DE_FATAL("Impossible");
8775 }
8776 }
8777 #ifndef CTS_USES_VULKANSC
8778 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
8779 {
8780 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
8781 {
8782 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
8783 m_vki.cmdPushDescriptorSetWithTemplate(cmd, **m_updateTemplates[setNdx], getPipelineLayout(),
8784 descriptorSetNdx,
8785 (const void *)m_updateRegistry[setNdx].getRawPointer());
8786 }
8787 }
8788 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8789 {
8790 uint32_t descriptorNdx = 0u;
8791 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
8792 {
8793 const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
8794 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
8795 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout,
8796 descriptorSetNdx, descriptorNdx, numDescriptors);
8797 descriptorNdx += numDescriptors;
8798 }
8799 }
8800 #endif
8801
8802 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
8803 }
8804
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const8805 tcu::TestStatus TexelBufferRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
8806 {
8807 const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
8808 const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
8809 const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
8810 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
8811
8812 tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
8813
8814 tcu::Vec4 sample0 = tcu::Vec4(0.0f);
8815 tcu::Vec4 sample1 = tcu::Vec4(0.0f);
8816 tcu::Vec4 sample2 = tcu::Vec4(0.0f);
8817 tcu::Vec4 sample3 = tcu::Vec4(0.0f);
8818
8819 if (doFetch)
8820 {
8821 for (uint32_t setNdx = 0u; setNdx < numDescriptorSets; setNdx++)
8822 {
8823 sample0 += m_texelBuffers.fetchTexelValue(0, setNdx);
8824 sample1 += m_texelBuffers.fetchTexelValue(1, setNdx);
8825 sample2 += m_texelBuffers.fetchTexelValue(2, setNdx);
8826 sample3 += m_texelBuffers.fetchTexelValue(3, setNdx);
8827 }
8828
8829 if (numDescriptorSets > 1)
8830 {
8831 sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
8832 sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
8833 sample2 = sample2 / tcu::Vec4(float(numDescriptorSets));
8834 sample3 = sample3 / tcu::Vec4(float(numDescriptorSets));
8835 }
8836 }
8837 else
8838 {
8839 sample0 = yellow;
8840 sample1 = green;
8841 sample2 = green;
8842 sample3 = yellow;
8843 }
8844
8845 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
8846
8847 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
8848 result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
8849 return tcu::TestStatus::fail("Image verification failed");
8850 else
8851 return tcu::TestStatus::pass("Pass");
8852 }
8853
8854 class TexelBufferComputeInstance : public vkt::TestInstance
8855 {
8856 public:
8857 TexelBufferComputeInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
8858 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
8859 ShaderInputInterface shaderInterface, bool nonzeroViewOffset, const bool bind2);
8860
8861 private:
8862 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
8863 vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
8864 vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
8865 uint32_t setNdx);
8866 void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
8867 #ifndef CTS_USES_VULKANSC
8868 void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
8869 uint32_t setNdx, bool withPush = false,
8870 vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
8871 #endif
8872
8873 tcu::TestStatus iterate(void);
8874 void logTestPlan(void) const;
8875 tcu::TestStatus testResourceAccess(void);
8876
8877 const DescriptorUpdateMethod m_updateMethod;
8878 const vk::VkDescriptorType m_descriptorType;
8879 const DescriptorSetCount m_descriptorSetCount;
8880 const ShaderInputInterface m_shaderInterface;
8881 const bool m_nonzeroViewOffset;
8882 const bool m_bind2;
8883
8884 const vk::DeviceInterface &m_vki;
8885 const vk::VkDevice m_device;
8886 const vk::VkQueue m_queue;
8887 const uint32_t m_queueFamilyIndex;
8888 vk::Allocator &m_allocator;
8889 #ifndef CTS_USES_VULKANSC
8890 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
8891 #endif
8892
8893 const ComputeInstanceResultBuffer m_result;
8894 const TexelBufferInstanceBuffers m_texelBuffers;
8895
8896 #ifndef CTS_USES_VULKANSC
8897 std::vector<RawUpdateRegistry> m_updateRegistry;
8898 #endif
8899 vk::DescriptorSetUpdateBuilder m_updateBuilder;
8900 std::vector<uint32_t> m_descriptorsPerSet;
8901 };
8902
TexelBufferComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool nonzeroViewOffset,const bool bind2)8903 TexelBufferComputeInstance::TexelBufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
8904 vk::VkDescriptorType descriptorType,
8905 DescriptorSetCount descriptorSetCount,
8906 ShaderInputInterface shaderInterface, bool nonzeroViewOffset,
8907 const bool bind2)
8908 : vkt::TestInstance(context)
8909 , m_updateMethod(updateMethod)
8910 , m_descriptorType(descriptorType)
8911 , m_descriptorSetCount(descriptorSetCount)
8912 , m_shaderInterface(shaderInterface)
8913 , m_nonzeroViewOffset(nonzeroViewOffset)
8914 , m_bind2(bind2)
8915 , m_vki(context.getDeviceInterface())
8916 , m_device(context.getDevice())
8917 , m_queue(context.getUniversalQueue())
8918 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
8919 , m_allocator(context.getDefaultAllocator())
8920 #ifndef CTS_USES_VULKANSC
8921 , m_updateTemplates()
8922 #endif
8923 , m_result(m_vki, m_device, m_allocator)
8924 , m_texelBuffers(context, m_vki, m_device, m_allocator, m_descriptorType, m_descriptorSetCount, m_shaderInterface,
8925 m_nonzeroViewOffset)
8926 #ifndef CTS_USES_VULKANSC
8927 , m_updateRegistry()
8928 #endif
8929 , m_updateBuilder()
8930 , m_descriptorsPerSet()
8931 {
8932 }
8933
createDescriptorSetLayout(uint32_t setNdx) const8934 vk::Move<vk::VkDescriptorSetLayout> TexelBufferComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
8935 {
8936 vk::DescriptorSetLayoutBuilder builder;
8937 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
8938 uint32_t binding = 0;
8939
8940 #ifndef CTS_USES_VULKANSC
8941 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
8942 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8943 {
8944 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
8945 }
8946 #endif
8947
8948 if (setNdx == 0)
8949 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
8950 binding++);
8951
8952 switch (m_shaderInterface)
8953 {
8954 case SHADER_INPUT_SINGLE_DESCRIPTOR:
8955 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
8956 break;
8957
8958 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
8959 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
8960 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
8961 break;
8962
8963 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
8964 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding);
8965 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2);
8966 break;
8967
8968 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
8969 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
8970 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
8971 break;
8972
8973 case SHADER_INPUT_DESCRIPTOR_ARRAY:
8974 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
8975 break;
8976
8977 default:
8978 DE_FATAL("Impossible");
8979 }
8980
8981 return builder.build(m_vki, m_device, extraFlags);
8982 }
8983
createDescriptorPool(void) const8984 vk::Move<vk::VkDescriptorPool> TexelBufferComputeInstance::createDescriptorPool(void) const
8985 {
8986 return vk::DescriptorPoolBuilder()
8987 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
8988 .addType(m_descriptorType,
8989 getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
8990 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
8991 getDescriptorSetCount(m_descriptorSetCount));
8992 }
8993
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx)8994 vk::Move<vk::VkDescriptorSet> TexelBufferComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
8995 vk::VkDescriptorSetLayout layout,
8996 uint32_t setNdx)
8997 {
8998 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
8999 pool, 1u, &layout};
9000
9001 vk::Move<vk::VkDescriptorSet> descriptorSet;
9002 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
9003 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9004 {
9005 descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
9006 }
9007 else
9008 {
9009 descriptorSet = vk::Move<vk::VkDescriptorSet>();
9010 }
9011
9012 #ifndef CTS_USES_VULKANSC
9013 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
9014 {
9015 writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx);
9016 }
9017 else
9018 #endif
9019 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
9020 {
9021 writeDescriptorSet(*descriptorSet, setNdx);
9022 }
9023
9024 return descriptorSet;
9025 }
9026
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)9027 void TexelBufferComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
9028 {
9029 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
9030 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
9031 const vk::VkBufferView texelBufferInfos[2] = {
9032 m_texelBuffers.getBufferView(setNdx * getInterfaceNumResources(m_shaderInterface)),
9033 m_texelBuffers.getBufferView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)};
9034 uint32_t binding = 0u;
9035 uint32_t numDescriptors = 0u;
9036
9037 // result
9038 if (setNdx == 0)
9039 {
9040 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9041 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
9042 numDescriptors++;
9043 }
9044
9045 // texel buffers
9046 switch (m_shaderInterface)
9047 {
9048 case SHADER_INPUT_SINGLE_DESCRIPTOR:
9049 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9050 m_descriptorType, &texelBufferInfos[0]);
9051 numDescriptors++;
9052 break;
9053
9054 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
9055 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9056 m_descriptorType, &texelBufferInfos[0]);
9057 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9058 m_descriptorType, &texelBufferInfos[1]);
9059 numDescriptors += 2;
9060 break;
9061
9062 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
9063 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
9064 m_descriptorType, &texelBufferInfos[0]);
9065 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
9066 m_descriptorType, &texelBufferInfos[1]);
9067 numDescriptors += 2;
9068 break;
9069
9070 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
9071 m_updateBuilder.writeSingle(descriptorSet,
9072 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
9073 m_descriptorType, &texelBufferInfos[0]);
9074 m_updateBuilder.writeSingle(descriptorSet,
9075 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
9076 m_descriptorType, &texelBufferInfos[1]);
9077 numDescriptors += 2;
9078 break;
9079
9080 case SHADER_INPUT_DESCRIPTOR_ARRAY:
9081 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9082 m_descriptorType, 2u, texelBufferInfos);
9083 numDescriptors++;
9084 break;
9085
9086 default:
9087 DE_FATAL("Impossible");
9088 }
9089
9090 m_descriptorsPerSet.push_back(numDescriptors);
9091
9092 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
9093 {
9094 m_updateBuilder.update(m_vki, m_device);
9095 m_updateBuilder.clear();
9096 }
9097 }
9098
9099 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)9100 void TexelBufferComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
9101 vk::VkDescriptorSetLayout layout, uint32_t setNdx,
9102 bool withPush, vk::VkPipelineLayout pipelineLayout)
9103 {
9104 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
9105 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
9106 const vk::VkBufferView texelBufferInfos[2] = {
9107 m_texelBuffers.getBufferView(setNdx * getInterfaceNumResources(m_shaderInterface)),
9108 m_texelBuffers.getBufferView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)};
9109 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
9110 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
9111 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
9112 nullptr,
9113 0,
9114 0, // updateCount
9115 nullptr, // pUpdates
9116 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
9117 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
9118 layout,
9119 vk::VK_PIPELINE_BIND_POINT_COMPUTE,
9120 pipelineLayout,
9121 setNdx};
9122 uint32_t binding = 0u;
9123 uint32_t offset = 0u;
9124 RawUpdateRegistry updateRegistry;
9125
9126 if (setNdx == 0)
9127 updateRegistry.addWriteObject(resultInfo);
9128
9129 updateRegistry.addWriteObject(texelBufferInfos[0]);
9130 updateRegistry.addWriteObject(texelBufferInfos[1]);
9131
9132 // result
9133 if (setNdx == 0)
9134 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
9135 updateRegistry.getWriteObjectOffset(offset++), 0));
9136
9137 // texel buffers
9138 switch (m_shaderInterface)
9139 {
9140 case SHADER_INPUT_SINGLE_DESCRIPTOR:
9141 updateEntries.push_back(
9142 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
9143 break;
9144
9145 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
9146 updateEntries.push_back(
9147 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
9148 updateEntries.push_back(
9149 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
9150 break;
9151
9152 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
9153 updateEntries.push_back(
9154 createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
9155 updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
9156 updateRegistry.getWriteObjectOffset(offset++), 0));
9157 break;
9158
9159 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
9160 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
9161 updateRegistry.getWriteObjectOffset(offset++), 0));
9162 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
9163 updateRegistry.getWriteObjectOffset(offset++), 0));
9164 break;
9165
9166 case SHADER_INPUT_DESCRIPTOR_ARRAY:
9167 updateEntries.push_back(createTemplateBinding(binding++, 0, 2, m_descriptorType,
9168 updateRegistry.getWriteObjectOffset(offset++),
9169 sizeof(texelBufferInfos[0])));
9170 break;
9171
9172 default:
9173 DE_FATAL("Impossible");
9174 }
9175
9176 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
9177 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
9178
9179 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
9180 vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
9181 m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
9182 m_updateRegistry.push_back(updateRegistry);
9183
9184 if (!withPush)
9185 {
9186 m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates[setNdx],
9187 m_updateRegistry.back().getRawPointer());
9188 }
9189 }
9190 #endif
9191
iterate(void)9192 tcu::TestStatus TexelBufferComputeInstance::iterate(void)
9193 {
9194 logTestPlan();
9195 return testResourceAccess();
9196 }
9197
logTestPlan(void) const9198 void TexelBufferComputeInstance::logTestPlan(void) const
9199 {
9200 std::ostringstream msg;
9201
9202 msg << "Fetching 4 values from image in compute shader.\n"
9203 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
9204 "Multiple descriptor sets. ")
9205 << "Each descriptor set contains "
9206 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
9207 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
9208 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
9209 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
9210 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
9211 nullptr)
9212 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
9213 << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
9214 << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
9215
9216 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
9217 {
9218 msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
9219
9220 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
9221 {
9222 const int srcResourceNdx = (resultNdx % 2); // ABAB source
9223 msg << " from texelBuffer " << srcResourceNdx;
9224 }
9225
9226 msg << "\n";
9227 }
9228
9229 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
9230 }
9231
testResourceAccess(void)9232 tcu::TestStatus TexelBufferComputeInstance::testResourceAccess(void)
9233 {
9234 const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
9235 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
9236 std::vector<DescriptorSetHandleSp> descriptorSets;
9237 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
9238 std::vector<vk::VkDescriptorSet> setHandles;
9239
9240 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9241 {
9242 vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
9243 vk::Move<vk::VkDescriptorSet> set = createDescriptorSet(*descriptorPool, *layout, setNdx);
9244
9245 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
9246 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
9247
9248 layoutHandles.push_back(**descriptorSetLayouts.back());
9249 setHandles.push_back(**descriptorSets.back());
9250
9251 // Add an empty descriptor set layout between sets 0 and 2
9252 if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
9253 {
9254 vk::DescriptorSetLayoutBuilder emptyBuilder;
9255 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
9256 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
9257
9258 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
9259 layoutHandles.push_back(**descriptorSetLayouts.back());
9260 }
9261 }
9262
9263 const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
9264 &layoutHandles.front());
9265 const uint32_t *const dynamicOffsets = nullptr;
9266 const int numDynamicOffsets = 0;
9267 const vk::VkBufferMemoryBarrier *const preBarriers = m_texelBuffers.getBufferInitBarriers();
9268 const int numPreBarriers = m_texelBuffers.getNumTexelBuffers();
9269 const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
9270 const int numPostBarriers = 1;
9271
9272 const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
9273 tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
9274 numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
9275 postBarriers, m_bind2);
9276
9277 tcu::Vec4 results[4];
9278 bool anyResultSet = false;
9279 bool allResultsOk = true;
9280
9281 #ifndef CTS_USES_VULKANSC
9282 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9283 {
9284 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9285 writeDescriptorSetWithTemplate(VK_NULL_HANDLE, layoutHandles[setNdx], setNdx, true,
9286 pipeline.getPipelineLayout());
9287
9288 compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
9289 }
9290 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
9291 {
9292 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9293 writeDescriptorSet(VK_NULL_HANDLE, setNdx);
9294
9295 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
9296 }
9297 else
9298 #endif
9299 {
9300 compute.submitAndWait(m_queueFamilyIndex, m_queue);
9301 }
9302 m_result.readResultContentsTo(&results);
9303
9304 // verify
9305 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
9306 {
9307 const tcu::Vec4 result = results[resultNdx];
9308 const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
9309
9310 tcu::Vec4 reference = tcu::Vec4(0.0f);
9311 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9312 reference += m_texelBuffers.fetchTexelValue(resultNdx, setNdx);
9313
9314 reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
9315
9316 if (result != tcu::Vec4(-1.0f))
9317 anyResultSet = true;
9318
9319 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
9320 {
9321 allResultsOk = false;
9322
9323 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test sample " << resultNdx << ": Expected "
9324 << reference << ", got " << result << tcu::TestLog::EndMessage;
9325 }
9326 }
9327
9328 // read back and verify
9329 if (allResultsOk)
9330 return tcu::TestStatus::pass("Pass");
9331 else if (anyResultSet)
9332 return tcu::TestStatus::fail("Invalid result values");
9333 else
9334 {
9335 m_context.getTestContext().getLog()
9336 << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
9337 return tcu::TestStatus::fail("Result buffer was not written to");
9338 }
9339 }
9340
9341 class TexelBufferDescriptorCase : public QuadrantRendederCase
9342 {
9343 public:
9344 enum
9345 {
9346 FLAG_VIEW_OFFSET = (1u << 1u),
9347 };
9348 // enum continues where resource flags ends
9349 DE_STATIC_ASSERT((uint32_t)FLAG_VIEW_OFFSET == (uint32_t)RESOURCE_FLAG_LAST);
9350
9351 TexelBufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name,
9352 bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
9353 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9354 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
9355 uint32_t flags, const bool m_bind2);
9356
9357 void checkSupport(Context &context) const;
9358
9359 private:
9360 std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
9361 std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
9362 std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
9363 std::string genNoAccessSource(void) const;
9364
9365 vkt::TestInstance *createInstance(vkt::Context &context) const;
9366
9367 const DescriptorUpdateMethod m_updateMethod;
9368 const bool m_isPrimaryCmdBuf;
9369 const vk::VkDescriptorType m_descriptorType;
9370 const DescriptorSetCount m_descriptorSetCount;
9371 const ShaderInputInterface m_shaderInterface;
9372 const bool m_nonzeroViewOffset;
9373 const bool m_bind2;
9374 };
9375
TexelBufferDescriptorCase(tcu::TestContext & testCtx,DescriptorUpdateMethod updateMethod,const char * name,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,uint32_t flags,const bool bind2)9376 TexelBufferDescriptorCase::TexelBufferDescriptorCase(
9377 tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name, bool isPrimaryCmdBuf,
9378 vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9379 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, uint32_t flags, const bool bind2)
9380 : QuadrantRendederCase(testCtx, name, glu::GLSL_VERSION_310_ES, exitingStages, activeStages, descriptorSetCount)
9381 , m_updateMethod(updateMethod)
9382 , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
9383 , m_descriptorType(descriptorType)
9384 , m_descriptorSetCount(descriptorSetCount)
9385 , m_shaderInterface(shaderInterface)
9386 , m_nonzeroViewOffset(((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u))
9387 , m_bind2(bind2)
9388 {
9389 }
9390
checkSupport(Context & context) const9391 void TexelBufferDescriptorCase::checkSupport(Context &context) const
9392 {
9393 if (m_bind2)
9394 context.requireDeviceFunctionality("VK_KHR_maintenance6");
9395 }
9396
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const9397 std::string TexelBufferDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
9398 {
9399 DE_UNREF(stage);
9400 return "#extension GL_EXT_texture_buffer : require\n";
9401 }
9402
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const9403 std::string TexelBufferDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage,
9404 int numUsedBindings) const
9405 {
9406 DE_UNREF(stage);
9407
9408 const bool isUniform = isUniformDescriptorType(m_descriptorType);
9409 const char *const storageType = (isUniform) ? ("textureBuffer ") : ("readonly imageBuffer ");
9410 const char *const formatQualifier = (isUniform) ? ("") : (", rgba8");
9411 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
9412
9413 std::ostringstream buf;
9414
9415 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
9416 {
9417 // Result buffer is bound only to the first descriptor set in compute shader cases
9418 const int descBinding =
9419 numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
9420 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
9421 const uint32_t descriptorSet = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
9422
9423 switch (m_shaderInterface)
9424 {
9425 case SHADER_INPUT_SINGLE_DESCRIPTOR:
9426 buf << "layout(set = " << descriptorSet
9427 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9428 "u_texelBuffer"
9429 << setNdxPostfix << ";\n";
9430 break;
9431 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
9432 buf << "layout(set = " << descriptorSet
9433 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9434 "u_texelBuffer"
9435 << setNdxPostfix
9436 << "A;\n"
9437 "layout(set = "
9438 << descriptorSet
9439 << ", binding = " + de::toString(descBinding + 1) + formatQualifier + ") uniform highp " + storageType +
9440 "u_texelBuffer"
9441 << setNdxPostfix << "B;\n";
9442 break;
9443 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
9444 buf << "layout(set = " << descriptorSet
9445 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9446 "u_texelBuffer"
9447 << setNdxPostfix
9448 << "A;\n"
9449 "layout(set = "
9450 << descriptorSet
9451 << ", binding = " + de::toString(descBinding + 2) + formatQualifier + ") uniform highp " + storageType +
9452 "u_texelBuffer"
9453 << setNdxPostfix << "B;\n";
9454 break;
9455 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
9456 buf << "layout(set = " << descriptorSet
9457 << ", binding = " + de::toString(getArbitraryBindingIndex(0)) + formatQualifier + ") uniform highp " +
9458 storageType + "u_texelBuffer"
9459 << setNdxPostfix
9460 << "A;\n"
9461 "layout(set = "
9462 << descriptorSet
9463 << ", binding = " + de::toString(getArbitraryBindingIndex(1)) + formatQualifier + ") uniform highp " +
9464 storageType + "u_texelBuffer"
9465 << setNdxPostfix << "B;\n";
9466 break;
9467 case SHADER_INPUT_DESCRIPTOR_ARRAY:
9468 buf << "layout(set = " << descriptorSet
9469 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9470 "u_texelBuffer"
9471 << setNdxPostfix << "[2];\n";
9472 break;
9473 default:
9474 DE_FATAL("Impossible");
9475 return "";
9476 }
9477 }
9478 return buf.str();
9479 }
9480
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const9481 std::string TexelBufferDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
9482 {
9483 DE_UNREF(stage);
9484
9485 const char *const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") :
9486 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("A") :
9487 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("A") :
9488 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? ("A") :
9489 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]") :
9490 (nullptr);
9491 const char *const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") :
9492 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("B") :
9493 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("B") :
9494 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? ("B") :
9495 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]") :
9496 (nullptr);
9497 const char *const fetchFunc = (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad");
9498 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
9499
9500 std::ostringstream buf;
9501
9502 buf << " result_color = vec4(0.0);\n";
9503
9504 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
9505 {
9506 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
9507
9508 buf << " if (quadrant_id == 0)\n"
9509 << " result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixA << ", "
9510 << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n"
9511 << " else if (quadrant_id == 1)\n"
9512 << " result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixB << ", "
9513 << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n"
9514 << " else if (quadrant_id == 2)\n"
9515 << " result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixA << ", "
9516 << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n"
9517 << " else\n"
9518 << " result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixB << ", "
9519 << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n";
9520 }
9521
9522 if (getDescriptorSetCount(m_descriptorSetCount) > 1)
9523 buf << " result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
9524
9525 return buf.str();
9526 }
9527
genNoAccessSource(void) const9528 std::string TexelBufferDescriptorCase::genNoAccessSource(void) const
9529 {
9530 return " if (quadrant_id == 1 || quadrant_id == 2)\n"
9531 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
9532 " else\n"
9533 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
9534 }
9535
createInstance(vkt::Context & context) const9536 vkt::TestInstance *TexelBufferDescriptorCase::createInstance(vkt::Context &context) const
9537 {
9538 verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
9539 m_updateMethod, m_descriptorType, m_activeStages);
9540
9541 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
9542 {
9543 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
9544 return new TexelBufferComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
9545 m_shaderInterface, m_nonzeroViewOffset, m_bind2);
9546 }
9547 else
9548 return new TexelBufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
9549 m_descriptorSetCount, m_activeStages, m_exitingStages, m_shaderInterface,
9550 m_nonzeroViewOffset, m_bind2);
9551 }
9552
createShaderAccessImageTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface dimension,uint32_t resourceFlags,const bool bind2)9553 void createShaderAccessImageTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf, DescriptorUpdateMethod updateMethod,
9554 vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages,
9555 vk::VkShaderStageFlags activeStages, DescriptorSetCount descriptorSetCount,
9556 ShaderInputInterface dimension, uint32_t resourceFlags, const bool bind2)
9557 {
9558 static const struct
9559 {
9560 vk::VkImageViewType viewType;
9561 const char *name;
9562 uint32_t flags;
9563 } s_imageTypes[] = {
9564 {vk::VK_IMAGE_VIEW_TYPE_1D, "1d", 0u},
9565 {vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9566 {vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9567
9568 {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array", 0u},
9569 {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9570 {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9571
9572 {vk::VK_IMAGE_VIEW_TYPE_2D, "2d", 0u},
9573 {vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9574 {vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9575
9576 {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array", 0u},
9577 {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9578 {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9579
9580 {vk::VK_IMAGE_VIEW_TYPE_3D, "3d", 0u},
9581 {vk::VK_IMAGE_VIEW_TYPE_3D, "3d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9582 // no 3d array textures
9583
9584 {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube", 0u},
9585 {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9586 {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9587
9588 {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array", 0u},
9589 {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9590 {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE}};
9591
9592 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx)
9593 {
9594 // never overlap
9595 DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u);
9596
9597 // skip some image view variations to avoid unnecessary bloating
9598 if ((descriptorType != vk::VK_DESCRIPTOR_TYPE_SAMPLER) &&
9599 (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) &&
9600 (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9601 continue;
9602
9603 if ((dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) &&
9604 (activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) &&
9605 (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9606 continue;
9607
9608 if ((dimension == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) &&
9609 (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9610 continue;
9611
9612 if ((descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS) &&
9613 (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9614 continue;
9615
9616 group->addChild(new ImageDescriptorCase(group->getTestContext(), s_imageTypes[ndx].name, isPrimaryCmdBuf,
9617 updateMethod, descriptorType, exitingStages, activeStages,
9618 descriptorSetCount, dimension, s_imageTypes[ndx].viewType,
9619 s_imageTypes[ndx].flags | resourceFlags, bind2));
9620 }
9621 }
9622
createShaderAccessTexelBufferTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface dimension,uint32_t resourceFlags,const bool bind2)9623 void createShaderAccessTexelBufferTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf,
9624 DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
9625 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9626 DescriptorSetCount descriptorSetCount, ShaderInputInterface dimension,
9627 uint32_t resourceFlags, const bool bind2)
9628 {
9629 DE_ASSERT(resourceFlags == 0);
9630 DE_UNREF(resourceFlags);
9631
9632 static const struct
9633 {
9634 const char *name;
9635 uint32_t flags;
9636 } s_texelBufferTypes[] = {
9637 // View offset is zero
9638 {"offset_zero", 0u},
9639 // View offset is non-zero
9640 {"offset_nonzero", TexelBufferDescriptorCase::FLAG_VIEW_OFFSET},
9641 };
9642
9643 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx)
9644 {
9645 group->addChild(new TexelBufferDescriptorCase(
9646 group->getTestContext(), updateMethod, s_texelBufferTypes[ndx].name, isPrimaryCmdBuf, descriptorType,
9647 exitingStages, activeStages, descriptorSetCount, dimension, s_texelBufferTypes[ndx].flags, bind2));
9648 }
9649 }
9650
createShaderAccessBufferTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface dimension,uint32_t resourceFlags,const bool bind2)9651 void createShaderAccessBufferTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf, DescriptorUpdateMethod updateMethod,
9652 vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages,
9653 vk::VkShaderStageFlags activeStages, DescriptorSetCount descriptorSetCount,
9654 ShaderInputInterface dimension, uint32_t resourceFlags, const bool bind2)
9655 {
9656 DE_ASSERT(resourceFlags == 0u);
9657 DE_UNREF(resourceFlags);
9658
9659 static const struct
9660 {
9661 const char *name;
9662 bool isForDynamicCases;
9663 uint32_t flags;
9664 } s_bufferTypes[] = {
9665 {"offset_view_zero", false, 0u},
9666 {"offset_view_nonzero", false, BufferDescriptorCase::FLAG_VIEW_OFFSET},
9667
9668 {"offset_view_zero_dynamic_zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO},
9669 {"offset_view_zero_dynamic_nonzero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO},
9670 {"offset_view_nonzero_dynamic_zero", true,
9671 BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO},
9672 {"offset_view_nonzero_dynamic_nonzero", true,
9673 BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO},
9674 };
9675
9676 const bool isDynamicCase = isDynamicDescriptorType(descriptorType);
9677
9678 if (isDynamicCase)
9679 {
9680 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH ||
9681 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9682 {
9683 // Can't support push descriptor sets with dynamic UBOs or SSBOs
9684 return;
9685 }
9686 }
9687
9688 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx)
9689 {
9690 if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases)
9691 group->addChild(new BufferDescriptorCase(group->getTestContext(), updateMethod, s_bufferTypes[ndx].name,
9692 isPrimaryCmdBuf, descriptorType, exitingStages, activeStages,
9693 descriptorSetCount, dimension, s_bufferTypes[ndx].flags, bind2));
9694 }
9695 }
9696
9697 } // namespace
9698
createShaderAccessTests(tcu::TestContext & testCtx)9699 tcu::TestCaseGroup *createShaderAccessTests(tcu::TestContext &testCtx)
9700 {
9701 static const struct
9702 {
9703 const bool isPrimary;
9704 const char *name;
9705 } s_bindTypes[] = {
9706 // Bind in primary command buffer
9707 {true, "primary_cmd_buf"},
9708 // Bind in secondary command buffer
9709 {false, "secondary_cmd_buf"},
9710 };
9711 static const struct
9712 {
9713 const DescriptorUpdateMethod method;
9714 const char *name;
9715 } s_updateMethods[] = {
9716 {DESCRIPTOR_UPDATE_METHOD_NORMAL, ""},
9717 #ifndef CTS_USES_VULKANSC
9718 // Use descriptor update templates
9719 {DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE, "with_template"},
9720 // Use push descriptor updates
9721 {DESCRIPTOR_UPDATE_METHOD_WITH_PUSH, "with_push"},
9722 // Use push descriptor update templates
9723 {DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE, "with_push_template"},
9724 #endif
9725 };
9726 static const struct
9727 {
9728 const vk::VkDescriptorType descriptorType;
9729 const char *name;
9730 const char *description;
9731 uint32_t flags;
9732 } s_descriptorTypes[] = {
9733 {vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_mutable", "VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler", 0u},
9734 {vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_immutable", "VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler",
9735 RESOURCE_FLAG_IMMUTABLE_SAMPLER},
9736 {vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_mutable",
9737 "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler", 0u},
9738 {vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_immutable",
9739 "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER},
9740 // \note No way to access SAMPLED_IMAGE without a sampler
9741 //{ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image", "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE", 0u },
9742 {vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image", "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE", 0u},
9743 {vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, "uniform_texel_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER",
9744 0u},
9745 {vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "storage_texel_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER",
9746 0u},
9747 {vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER", 0u},
9748 {vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER", 0u},
9749 {vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic",
9750 "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC", 0u},
9751 {vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic",
9752 "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC", 0u},
9753 };
9754 static const struct
9755 {
9756 const char *name;
9757 vk::VkShaderStageFlags existingStages; //!< stages that exists
9758 vk::VkShaderStageFlags activeStages; //!< stages that access resource
9759 bool supportsSecondaryCmdBufs;
9760 } s_shaderStages[] = {
9761 // No accessing stages
9762 {
9763 "no_access",
9764 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9765 0u,
9766 true,
9767 },
9768 // Vertex stage
9769 {
9770 "vertex",
9771 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9772 vk::VK_SHADER_STAGE_VERTEX_BIT,
9773 true,
9774 },
9775 // Tessellation control stage
9776 {
9777 "tess_ctrl",
9778 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
9779 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9780 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
9781 true,
9782 },
9783 // Tessellation evaluation stage
9784 {
9785 "tess_eval",
9786 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
9787 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9788 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
9789 true,
9790 },
9791 // Geometry stage
9792 {
9793 "geometry",
9794 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9795 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
9796 true,
9797 },
9798 // Fragment stage
9799 {
9800 "fragment",
9801 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9802 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9803 true,
9804 },
9805 // Compute stage
9806 {
9807 "compute",
9808 vk::VK_SHADER_STAGE_COMPUTE_BIT,
9809 vk::VK_SHADER_STAGE_COMPUTE_BIT,
9810 false,
9811 },
9812 // Vertex and fragment stages
9813 {
9814 "vertex_fragment",
9815 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9816 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9817 true,
9818 }};
9819 static const struct
9820 {
9821 ShaderInputInterface dimension;
9822 const char *name;
9823 } s_variableDimensions[] = {
9824 {SHADER_INPUT_SINGLE_DESCRIPTOR, "single_descriptor"},
9825 {SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, "multiple_contiguous_descriptors"},
9826 {SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, "multiple_discontiguous_descriptors"},
9827 {SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS, "multiple_arbitrary_descriptors"},
9828 {SHADER_INPUT_DESCRIPTOR_ARRAY, "descriptor_array"},
9829 };
9830 static const struct
9831 {
9832 const bool bind2;
9833 const char *name;
9834 const char *description;
9835 } s_bindCommand[] = {
9836 {false, "bind", "use_vkCmdBindDescriptors"},
9837 {true, "bind2", "use vkCmdBindDescriptors2"},
9838 };
9839
9840 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access"));
9841
9842 // .primary_cmd_buf...
9843 for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx)
9844 {
9845 de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name));
9846
9847 for (int bindCommandNdx = 0; bindCommandNdx < DE_LENGTH_OF_ARRAY(s_bindCommand); ++bindCommandNdx)
9848 {
9849 de::MovePtr<tcu::TestCaseGroup> bindCommandGroup(
9850 new tcu::TestCaseGroup(testCtx, s_bindCommand[bindCommandNdx].name));
9851
9852 for (int updateMethodNdx = 0; updateMethodNdx < DE_LENGTH_OF_ARRAY(s_updateMethods); ++updateMethodNdx)
9853 {
9854 de::MovePtr<tcu::TestCaseGroup> updateMethodGroup(
9855 new tcu::TestCaseGroup(testCtx, s_updateMethods[updateMethodNdx].name));
9856
9857 // .sampler, .combined_image_sampler, other resource types ...
9858 for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx)
9859 {
9860 de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(
9861 testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description));
9862
9863 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx)
9864 {
9865 if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs)
9866 {
9867 de::MovePtr<tcu::TestCaseGroup> stageGroup(
9868 new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name));
9869 de::MovePtr<tcu::TestCaseGroup> multipleGroup(new tcu::TestCaseGroup(
9870 testCtx, "multiple_descriptor_sets", "Multiple descriptor sets"));
9871 de::MovePtr<tcu::TestCaseGroup> multipleDiscontiguousGroup(
9872 new tcu::TestCaseGroup(testCtx, "multiple_discontiguous_descriptor_sets",
9873 "Multiple discontiguous descriptor sets"));
9874
9875 for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions);
9876 ++dimensionNdx)
9877 {
9878 de::MovePtr<tcu::TestCaseGroup> dimensionSingleDescriptorSetGroup(
9879 new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9880 de::MovePtr<tcu::TestCaseGroup> dimensionMultipleDescriptorSetsGroup(
9881 new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9882 de::MovePtr<tcu::TestCaseGroup> dimensionMultipleDiscontiguousDescriptorSetsGroup(
9883 new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9884 void (*createTestsFunc)(
9885 tcu::TestCaseGroup *group, bool isPrimaryCmdBuf,
9886 DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
9887 vk::VkShaderStageFlags existingStages, vk::VkShaderStageFlags activeStages,
9888 DescriptorSetCount descriptorSetCount, ShaderInputInterface dimension,
9889 uint32_t resourceFlags, const bool bind2);
9890
9891 switch (s_descriptorTypes[descriptorNdx].descriptorType)
9892 {
9893 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
9894 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
9895 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
9896 createTestsFunc = createShaderAccessImageTests;
9897 break;
9898
9899 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
9900 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
9901 createTestsFunc = createShaderAccessTexelBufferTests;
9902 break;
9903
9904 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
9905 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
9906 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
9907 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
9908 createTestsFunc = createShaderAccessBufferTests;
9909 break;
9910
9911 default:
9912 createTestsFunc = nullptr;
9913 DE_FATAL("Impossible");
9914 }
9915
9916 if (createTestsFunc)
9917 {
9918 createTestsFunc(
9919 dimensionSingleDescriptorSetGroup.get(), s_bindTypes[bindTypeNdx].isPrimary,
9920 s_updateMethods[updateMethodNdx].method,
9921 s_descriptorTypes[descriptorNdx].descriptorType,
9922 s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9923 DESCRIPTOR_SET_COUNT_SINGLE, s_variableDimensions[dimensionNdx].dimension,
9924 s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9925
9926 createTestsFunc(
9927 dimensionMultipleDescriptorSetsGroup.get(), s_bindTypes[bindTypeNdx].isPrimary,
9928 s_updateMethods[updateMethodNdx].method,
9929 s_descriptorTypes[descriptorNdx].descriptorType,
9930 s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9931 DESCRIPTOR_SET_COUNT_MULTIPLE, s_variableDimensions[dimensionNdx].dimension,
9932 s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9933
9934 createTestsFunc(
9935 dimensionMultipleDiscontiguousDescriptorSetsGroup.get(),
9936 s_bindTypes[bindTypeNdx].isPrimary, s_updateMethods[updateMethodNdx].method,
9937 s_descriptorTypes[descriptorNdx].descriptorType,
9938 s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9939 DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS,
9940 s_variableDimensions[dimensionNdx].dimension,
9941 s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9942 }
9943 else
9944 DE_FATAL("Impossible");
9945
9946 stageGroup->addChild(dimensionSingleDescriptorSetGroup.release());
9947
9948 // Only one descriptor set layout can be created with VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR set
9949 if (s_updateMethods[updateMethodNdx].method == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH ||
9950 s_updateMethods[updateMethodNdx].method ==
9951 DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9952 continue;
9953
9954 multipleGroup->addChild(dimensionMultipleDescriptorSetsGroup.release());
9955 multipleDiscontiguousGroup->addChild(
9956 dimensionMultipleDiscontiguousDescriptorSetsGroup.release());
9957 }
9958
9959 stageGroup->addChild(multipleGroup.release());
9960 stageGroup->addChild(multipleDiscontiguousGroup.release());
9961 typeGroup->addChild(stageGroup.release());
9962 }
9963 }
9964
9965 if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL)
9966 {
9967 updateMethodGroup->addChild(typeGroup.release());
9968 }
9969 else
9970 {
9971 bindCommandGroup->addChild(typeGroup.release());
9972 }
9973 }
9974
9975 if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL)
9976 {
9977 bindCommandGroup->addChild(updateMethodGroup.release());
9978 }
9979 }
9980 bindGroup->addChild(bindCommandGroup.release());
9981 }
9982
9983 group->addChild(bindGroup.release());
9984 }
9985
9986 return group.release();
9987 }
9988
9989 } // namespace BindingModel
9990 } // namespace vkt
9991