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 extensionNames.push_back("VK_KHR_push_descriptor");
175 break;
176
177 case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE:
178 extensionNames.push_back("VK_KHR_push_descriptor");
179 // Fallthrough
180 case DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE:
181 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_descriptor_update_template"))
182 extensionNames.push_back("VK_KHR_descriptor_update_template");
183 break;
184
185 case DESCRIPTOR_UPDATE_METHOD_NORMAL:
186 // no extensions needed
187 break;
188
189 default:
190 DE_FATAL("Impossible");
191 }
192
193 numExtensionsNeeded = extensionNames.size();
194
195 if (numExtensionsNeeded > 0)
196 {
197 for (size_t deviceExtNdx = 0; deviceExtNdx < deviceExtensions.size(); deviceExtNdx++)
198 {
199 for (size_t requiredExtNdx = 0; requiredExtNdx < extensionNames.size(); requiredExtNdx++)
200 {
201 if (deStringEqual(deviceExtensions[deviceExtNdx].c_str(), extensionNames[requiredExtNdx].c_str()))
202 {
203 --numExtensionsNeeded;
204 break;
205 }
206 }
207
208 if (numExtensionsNeeded == 0)
209 break;
210 }
211
212 if (numExtensionsNeeded > 0)
213 {
214 TCU_THROW(NotSupportedError,
215 (stringifyDescriptorUpdateMethod(updateMethod) + " tests are not supported").c_str());
216 }
217 }
218
219 switch (descType)
220 {
221 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
222 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
223 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
224 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
225 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
226 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
227 // These are supported in all stages
228 break;
229
230 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
231 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
232 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
233 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
234 if (activeStages & (vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
235 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT))
236 {
237 if (!deviceFeatures.vertexPipelineStoresAndAtomics)
238 TCU_THROW(NotSupportedError,
239 (de::toString(descType) + " is not supported in the vertex pipeline").c_str());
240 }
241
242 if (activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT)
243 {
244 if (!deviceFeatures.fragmentStoresAndAtomics)
245 TCU_THROW(NotSupportedError,
246 (de::toString(descType) + " is not supported in fragment shaders").c_str());
247 }
248 break;
249
250 default:
251 DE_FATAL("Impossible");
252 }
253
254 if (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !deviceFeatures.imageCubeArray)
255 TCU_THROW(NotSupportedError, "imageCubeArray feature not supported");
256 }
257
viewTypeToImageType(vk::VkImageViewType type)258 vk::VkImageType viewTypeToImageType(vk::VkImageViewType type)
259 {
260 switch (type)
261 {
262 case vk::VK_IMAGE_VIEW_TYPE_1D:
263 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
264 return vk::VK_IMAGE_TYPE_1D;
265 case vk::VK_IMAGE_VIEW_TYPE_2D:
266 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
267 return vk::VK_IMAGE_TYPE_2D;
268 case vk::VK_IMAGE_VIEW_TYPE_3D:
269 return vk::VK_IMAGE_TYPE_3D;
270 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
271 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
272 return vk::VK_IMAGE_TYPE_2D;
273
274 default:
275 DE_FATAL("Impossible");
276 return (vk::VkImageType)0;
277 }
278 }
279
getImageLayoutForDescriptorType(vk::VkDescriptorType descType)280 vk::VkImageLayout getImageLayoutForDescriptorType(vk::VkDescriptorType descType)
281 {
282 if (descType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
283 return vk::VK_IMAGE_LAYOUT_GENERAL;
284 else
285 return vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
286 }
287
getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid & srcImage)288 uint32_t getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid &srcImage)
289 {
290 uint32_t dataSize = 0;
291 for (int level = 0; level < srcImage.getNumLevels(); ++level)
292 {
293 const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
294
295 // tightly packed
296 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
297
298 dataSize +=
299 srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
300 }
301 return dataSize;
302 }
303
writeTextureLevelPyramidData(void * dst,uint32_t dstLen,const tcu::TextureLevelPyramid & srcImage,vk::VkImageViewType viewType,std::vector<vk::VkBufferImageCopy> * copySlices)304 void writeTextureLevelPyramidData(void *dst, uint32_t dstLen, const tcu::TextureLevelPyramid &srcImage,
305 vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy> *copySlices)
306 {
307 // \note cube is copied face-by-face
308 const uint32_t arraySize =
309 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
310 (srcImage.getLevel(0).getHeight()) :
311 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ?
312 (srcImage.getLevel(0).getDepth()) :
313 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
314 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
315 (srcImage.getLevel(0).getDepth()) :
316 ((uint32_t)0);
317 uint32_t levelOffset = 0;
318
319 DE_ASSERT(arraySize != 0);
320
321 for (int level = 0; level < srcImage.getNumLevels(); ++level)
322 {
323 const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
324 const tcu::PixelBufferAccess dstAccess(srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(),
325 (uint8_t *)dst + levelOffset);
326 const uint32_t dataSize =
327 srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
328 const uint32_t sliceDataSize = dataSize / arraySize;
329 const int32_t sliceHeight =
330 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
331 (1) :
332 (srcAccess.getHeight());
333 const int32_t sliceDepth = (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1);
334 const tcu::IVec3 sliceSize(srcAccess.getWidth(), sliceHeight, sliceDepth);
335
336 // tightly packed
337 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
338
339 for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx)
340 {
341 const vk::VkBufferImageCopy copySlice = {
342 (vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize, // bufferOffset
343 (uint32_t)sliceSize.x(), // bufferRowLength
344 (uint32_t)sliceSize.y(), // bufferImageHeight
345 {
346 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
347 (uint32_t)level, // mipLevel
348 (uint32_t)sliceNdx, // arrayLayer
349 1u, // arraySize
350 }, // imageSubresource
351 {
352 0,
353 0,
354 0,
355 }, // imageOffset
356 {
357 (uint32_t)sliceSize.x(),
358 (uint32_t)sliceSize.y(),
359 (uint32_t)sliceSize.z(),
360 } // imageExtent
361 };
362 copySlices->push_back(copySlice);
363 }
364
365 DE_ASSERT(arraySize * sliceDataSize == dataSize);
366
367 tcu::copy(dstAccess, srcAccess);
368 levelOffset += dataSize;
369 }
370
371 DE_ASSERT(dstLen == levelOffset);
372 DE_UNREF(dstLen);
373 }
374
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkBuffer buffer,vk::MemoryRequirement requirement)375 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory(const vk::DeviceInterface &vki, vk::VkDevice device,
376 vk::Allocator &allocator, vk::VkBuffer buffer,
377 vk::MemoryRequirement requirement)
378 {
379 const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vki, device, buffer);
380 de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement);
381
382 VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
383 return allocation;
384 }
385
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkImage image,vk::MemoryRequirement requirement)386 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory(const vk::DeviceInterface &vki, vk::VkDevice device,
387 vk::Allocator &allocator, vk::VkImage image,
388 vk::MemoryRequirement requirement)
389 {
390 const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vki, device, image);
391 de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement);
392
393 VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
394 return allocation;
395 }
396
makeDescriptorImageInfo(vk::VkSampler sampler)397 vk::VkDescriptorImageInfo makeDescriptorImageInfo(vk::VkSampler sampler)
398 {
399 return vk::makeDescriptorImageInfo(sampler, (vk::VkImageView)0, (vk::VkImageLayout)0);
400 }
401
makeDescriptorImageInfo(vk::VkImageView imageView,vk::VkImageLayout layout)402 vk::VkDescriptorImageInfo makeDescriptorImageInfo(vk::VkImageView imageView, vk::VkImageLayout layout)
403 {
404 return vk::makeDescriptorImageInfo((vk::VkSampler)0, imageView, layout);
405 }
406
drawQuadrantReferenceResult(const tcu::PixelBufferAccess & dst,const tcu::Vec4 & c1,const tcu::Vec4 & c2,const tcu::Vec4 & c3,const tcu::Vec4 & c4)407 void drawQuadrantReferenceResult(const tcu::PixelBufferAccess &dst, const tcu::Vec4 &c1, const tcu::Vec4 &c2,
408 const tcu::Vec4 &c3, const tcu::Vec4 &c4)
409 {
410 tcu::clear(tcu::getSubregion(dst, 0, 0, dst.getWidth() / 2, dst.getHeight() / 2), c1);
411 tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, 0, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() / 2),
412 c2);
413 tcu::clear(
414 tcu::getSubregion(dst, 0, dst.getHeight() / 2, dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c3);
415 tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, dst.getHeight() / 2, dst.getWidth() - dst.getWidth() / 2,
416 dst.getHeight() - dst.getHeight() / 2),
417 c4);
418 }
419
420 #ifndef CTS_USES_VULKANSC
createTemplateBinding(uint32_t binding,uint32_t arrayElement,uint32_t descriptorCount,vk::VkDescriptorType descriptorType,size_t offset,size_t stride)421 static const vk::VkDescriptorUpdateTemplateEntry createTemplateBinding(uint32_t binding, uint32_t arrayElement,
422 uint32_t descriptorCount,
423 vk::VkDescriptorType descriptorType,
424 size_t offset, size_t stride)
425 {
426 const vk::VkDescriptorUpdateTemplateEntry updateBinding = {binding, arrayElement, descriptorCount,
427 descriptorType, offset, stride};
428
429 return updateBinding;
430 }
431
432 class RawUpdateRegistry
433 {
434 public:
435 RawUpdateRegistry(void);
436
437 template <typename Type>
438 void addWriteObject(const Type &updateObject);
439 size_t getWriteObjectOffset(const uint32_t objectId);
440 const uint8_t *getRawPointer() const;
441
442 private:
443 std::vector<uint8_t> m_updateEntries;
444 std::vector<size_t> m_updateEntryOffsets;
445 size_t m_nextOffset;
446 };
447
RawUpdateRegistry(void)448 RawUpdateRegistry::RawUpdateRegistry(void) : m_updateEntries(), m_updateEntryOffsets(), m_nextOffset(0)
449 {
450 }
451
452 template <typename Type>
addWriteObject(const Type & updateObject)453 void RawUpdateRegistry::addWriteObject(const Type &updateObject)
454 {
455 m_updateEntryOffsets.push_back(m_nextOffset);
456
457 // in this case, elements <=> bytes
458 m_updateEntries.resize(m_nextOffset + sizeof(updateObject));
459 Type *t = reinterpret_cast<Type *>(m_updateEntries.data() + m_nextOffset);
460 *t = updateObject;
461 m_nextOffset += sizeof(updateObject);
462 }
463
getWriteObjectOffset(const uint32_t objectId)464 size_t RawUpdateRegistry::getWriteObjectOffset(const uint32_t objectId)
465 {
466 return m_updateEntryOffsets[objectId];
467 }
468
getRawPointer() const469 const uint8_t *RawUpdateRegistry::getRawPointer() const
470 {
471 return m_updateEntries.data();
472 }
473 #endif
474
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)475 void bindDescriptorSets(const vk::DeviceInterface &m_vki, vk::VkCommandBuffer cmdBuffer,
476 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
477 vk::VkPipelineBindPoint bindPoint, vk::VkPipelineLayout layout, uint32_t first, uint32_t count,
478 const vk::VkDescriptorSet *descriptorSets, uint32_t dynamicOffsetCount,
479 const uint32_t *dynamicOffsets, bool bind2)
480 {
481 DE_UNREF(stageFlags);
482 DE_UNREF(existingStages);
483 if (bind2)
484 {
485 #ifndef CTS_USES_VULKANSC
486 vk::VkBindDescriptorSetsInfoKHR bindDescriptorSetsInfo = {
487 vk::VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO_KHR, // VkStructureType sType;
488 DE_NULL, // const void* pNext;
489 existingStages, // VkShaderStageFlags stageFlags;
490 layout, // VkPipelineLayout layout;
491 first, // uint32_t firstSet;
492 count, // uint32_t descriptorSetCount;
493 descriptorSets, // const VkDescriptorSet* pDescriptorSets;
494 dynamicOffsetCount, // uint32_t dynamicOffsetCount;
495 dynamicOffsets // const uint32_t* pDynamicOffsets;
496 };
497 m_vki.cmdBindDescriptorSets2KHR(cmdBuffer, &bindDescriptorSetsInfo);
498 #endif
499 }
500 else
501 {
502 m_vki.cmdBindDescriptorSets(cmdBuffer, bindPoint, layout, first, count, descriptorSets, dynamicOffsetCount,
503 dynamicOffsets);
504 }
505 }
506
507 class SingleTargetRenderInstance : public vkt::TestInstance
508 {
509 public:
510 SingleTargetRenderInstance(Context &context, const tcu::UVec2 &size, const bool bind2);
511
512 private:
513 static vk::Move<vk::VkImage> createColorAttachment(const vk::DeviceInterface &vki, vk::VkDevice device,
514 vk::Allocator &allocator, const tcu::TextureFormat &format,
515 const tcu::UVec2 &size,
516 de::MovePtr<vk::Allocation> *outAllocation);
517
518 static vk::Move<vk::VkImageView> createColorAttachmentView(const vk::DeviceInterface &vki, vk::VkDevice device,
519 const tcu::TextureFormat &format, vk::VkImage image);
520
521 static vk::Move<vk::VkFramebuffer> createFramebuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
522 vk::VkRenderPass renderpass,
523 vk::VkImageView colorAttachmentView, const tcu::UVec2 &size);
524
525 static vk::Move<vk::VkCommandPool> createCommandPool(const vk::DeviceInterface &vki, vk::VkDevice device,
526 uint32_t queueFamilyIndex);
527
528 virtual void logTestPlan(void) const = 0;
529 virtual void renderToTarget(void) = 0;
530 virtual tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const = 0;
531
532 void readRenderTarget(tcu::TextureLevel &dst);
533 tcu::TestStatus iterate(void);
534
535 protected:
536 const tcu::TextureFormat m_targetFormat;
537 const tcu::UVec2 m_targetSize;
538 const bool m_bind2;
539
540 const vk::DeviceInterface &m_vki;
541 const vk::VkDevice m_device;
542 const vk::VkQueue m_queue;
543 const uint32_t m_queueFamilyIndex;
544 vk::Allocator &m_allocator;
545 de::MovePtr<vk::Allocation> m_colorAttachmentMemory;
546 const vk::Unique<vk::VkImage> m_colorAttachmentImage;
547 const vk::Unique<vk::VkImageView> m_colorAttachmentView;
548 const vk::Unique<vk::VkRenderPass> m_renderPass;
549 const vk::Unique<vk::VkFramebuffer> m_framebuffer;
550 const vk::Unique<vk::VkCommandPool> m_cmdPool;
551
552 bool m_firstIteration;
553 };
554
SingleTargetRenderInstance(Context & context,const tcu::UVec2 & size,const bool bind2)555 SingleTargetRenderInstance::SingleTargetRenderInstance(Context &context, const tcu::UVec2 &size, const bool bind2)
556 : vkt::TestInstance(context)
557 , m_targetFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
558 , m_targetSize(size)
559 , m_bind2(bind2)
560 , m_vki(context.getDeviceInterface())
561 , m_device(context.getDevice())
562 , m_queue(context.getUniversalQueue())
563 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
564 , m_allocator(context.getDefaultAllocator())
565 , m_colorAttachmentMemory(DE_NULL)
566 , m_colorAttachmentImage(
567 createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory))
568 , m_colorAttachmentView(createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage))
569 , m_renderPass(makeRenderPass(m_vki, m_device, vk::mapTextureFormat(m_targetFormat)))
570 , m_framebuffer(createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize))
571 , m_cmdPool(createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex()))
572 , m_firstIteration(true)
573 {
574 }
575
createColorAttachment(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,const tcu::TextureFormat & format,const tcu::UVec2 & size,de::MovePtr<vk::Allocation> * outAllocation)576 vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment(const vk::DeviceInterface &vki,
577 vk::VkDevice device, vk::Allocator &allocator,
578 const tcu::TextureFormat &format,
579 const tcu::UVec2 &size,
580 de::MovePtr<vk::Allocation> *outAllocation)
581 {
582 const vk::VkImageCreateInfo imageInfo = {
583 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
584 DE_NULL,
585 (vk::VkImageCreateFlags)0,
586 vk::VK_IMAGE_TYPE_2D, // imageType
587 vk::mapTextureFormat(format), // format
588 {size.x(), size.y(), 1u}, // extent
589 1, // mipLevels
590 1, // arraySize
591 vk::VK_SAMPLE_COUNT_1_BIT, // samples
592 vk::VK_IMAGE_TILING_OPTIMAL, // tiling
593 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
594 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
595 0u, // queueFamilyCount
596 DE_NULL, // pQueueFamilyIndices
597 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
598 };
599
600 vk::Move<vk::VkImage> image(vk::createImage(vki, device, &imageInfo));
601 de::MovePtr<vk::Allocation> allocation(
602 allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any));
603
604 *outAllocation = allocation;
605 return image;
606 }
607
createColorAttachmentView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & format,vk::VkImage image)608 vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView(const vk::DeviceInterface &vki,
609 vk::VkDevice device,
610 const tcu::TextureFormat &format,
611 vk::VkImage image)
612 {
613 const vk::VkImageViewCreateInfo createInfo = {
614 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
615 DE_NULL,
616 (vk::VkImageViewCreateFlags)0,
617 image, // image
618 vk::VK_IMAGE_VIEW_TYPE_2D, // viewType
619 vk::mapTextureFormat(format), // format
620 vk::makeComponentMappingRGBA(),
621 {
622 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
623 0u, // baseMipLevel
624 1u, // mipLevels
625 0u, // baseArrayLayer
626 1u, // arraySize
627 },
628 };
629
630 return vk::createImageView(vki, device, &createInfo);
631 }
632
createFramebuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkRenderPass renderpass,vk::VkImageView colorAttachmentView,const tcu::UVec2 & size)633 vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer(const vk::DeviceInterface &vki,
634 vk::VkDevice device,
635 vk::VkRenderPass renderpass,
636 vk::VkImageView colorAttachmentView,
637 const tcu::UVec2 &size)
638 {
639 const vk::VkFramebufferCreateInfo framebufferCreateInfo = {
640 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
641 DE_NULL,
642 (vk::VkFramebufferCreateFlags)0,
643 renderpass, // renderPass
644 1u, // attachmentCount
645 &colorAttachmentView, // pAttachments
646 size.x(), // width
647 size.y(), // height
648 1, // layers
649 };
650
651 return vk::createFramebuffer(vki, device, &framebufferCreateInfo);
652 }
653
createCommandPool(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex)654 vk::Move<vk::VkCommandPool> SingleTargetRenderInstance::createCommandPool(const vk::DeviceInterface &vki,
655 vk::VkDevice device,
656 uint32_t queueFamilyIndex)
657 {
658 return vk::createCommandPool(vki, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
659 }
660
readRenderTarget(tcu::TextureLevel & dst)661 void SingleTargetRenderInstance::readRenderTarget(tcu::TextureLevel &dst)
662 {
663 const uint64_t pixelDataSize = (uint64_t)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize());
664 const vk::VkBufferCreateInfo bufferCreateInfo = {
665 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
666 DE_NULL,
667 0u, // flags
668 pixelDataSize, // size
669 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
670 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
671 0u, // queueFamilyCount
672 DE_NULL, // pQueueFamilyIndices
673 };
674 const vk::Unique<vk::VkBuffer> buffer(vk::createBuffer(m_vki, m_device, &bufferCreateInfo));
675
676 const de::MovePtr<vk::Allocation> bufferMemory =
677 allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible);
678
679 const vk::Unique<vk::VkCommandBuffer> cmd(
680 vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
681
682 // copy content to buffer
683 beginCommandBuffer(m_vki, *cmd);
684 copyImageToBuffer(m_vki, *cmd, *m_colorAttachmentImage, *buffer, tcu::IVec2(m_targetSize.x(), m_targetSize.y()));
685 endCommandBuffer(m_vki, *cmd);
686
687 submitCommandsAndWait(m_vki, m_device, m_queue, cmd.get());
688
689 dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y());
690
691 // copy data
692 invalidateAlloc(m_vki, m_device, *bufferMemory);
693 tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr()));
694 }
695
iterate(void)696 tcu::TestStatus SingleTargetRenderInstance::iterate(void)
697 {
698 tcu::TextureLevel resultImage;
699
700 // log
701 if (m_firstIteration)
702 {
703 logTestPlan();
704 m_firstIteration = false;
705 }
706
707 // render
708 {
709 // transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
710 const vk::VkImageSubresourceRange fullSubrange = {
711 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
712 0u, // baseMipLevel
713 1u, // mipLevels
714 0u, // baseArraySlice
715 1u, // arraySize
716 };
717 const vk::VkImageMemoryBarrier imageBarrier = {
718 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
719 DE_NULL,
720 0u, // srcAccessMask
721 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
722 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
723 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
724 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
725 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
726 *m_colorAttachmentImage, // image
727 fullSubrange, // subresourceRange
728 };
729
730 const vk::Unique<vk::VkCommandBuffer> cmd(
731 vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
732
733 beginCommandBuffer(m_vki, *cmd);
734 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
735 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0, 0,
736 (const vk::VkMemoryBarrier *)DE_NULL, 0, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1,
737 &imageBarrier);
738 endCommandBuffer(m_vki, *cmd);
739
740 submitCommandsAndWait(m_vki, m_device, m_queue, cmd.get());
741
742 renderToTarget();
743 }
744
745 // read and verify
746 readRenderTarget(resultImage);
747 #ifdef CTS_USES_VULKANSC
748 // skip costly verification in main process
749 if (!m_context.getTestContext().getCommandLine().isSubProcess())
750 return tcu::TestStatus::pass("Success");
751 #endif // CTS_USES_VULKANSC
752 return verifyResultImage(resultImage.getAccess());
753 }
754
755 class RenderInstanceShaders
756 {
757 public:
758 RenderInstanceShaders(const vk::DeviceInterface &vki, vk::VkDevice device,
759 const vk::VkPhysicalDeviceFeatures &deviceFeatures,
760 const vk::BinaryCollection &programCollection);
761
hasTessellationStage(void) const762 inline bool hasTessellationStage(void) const
763 {
764 return *m_tessCtrlShaderModule != 0 || *m_tessEvalShaderModule != 0;
765 }
getNumStages(void) const766 inline uint32_t getNumStages(void) const
767 {
768 return (uint32_t)m_stageInfos.size();
769 }
getStages(void) const770 inline const vk::VkPipelineShaderStageCreateInfo *getStages(void) const
771 {
772 return &m_stageInfos[0];
773 }
774
775 private:
776 void addStage(const vk::DeviceInterface &vki, vk::VkDevice device,
777 const vk::VkPhysicalDeviceFeatures &deviceFeatures, const vk::BinaryCollection &programCollection,
778 const char *name, vk::VkShaderStageFlagBits stage, vk::Move<vk::VkShaderModule> *outModule);
779
780 vk::VkPipelineShaderStageCreateInfo getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,
781 vk::VkShaderModule shader) const;
782
783 vk::Move<vk::VkShaderModule> m_vertexShaderModule;
784 vk::Move<vk::VkShaderModule> m_tessCtrlShaderModule;
785 vk::Move<vk::VkShaderModule> m_tessEvalShaderModule;
786 vk::Move<vk::VkShaderModule> m_geometryShaderModule;
787 vk::Move<vk::VkShaderModule> m_fragmentShaderModule;
788 std::vector<vk::VkPipelineShaderStageCreateInfo> m_stageInfos;
789 };
790
RenderInstanceShaders(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const vk::BinaryCollection & programCollection)791 RenderInstanceShaders::RenderInstanceShaders(const vk::DeviceInterface &vki, vk::VkDevice device,
792 const vk::VkPhysicalDeviceFeatures &deviceFeatures,
793 const vk::BinaryCollection &programCollection)
794 {
795 addStage(vki, device, deviceFeatures, programCollection, "vertex", vk::VK_SHADER_STAGE_VERTEX_BIT,
796 &m_vertexShaderModule);
797 addStage(vki, device, deviceFeatures, programCollection, "tess_ctrl", vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
798 &m_tessCtrlShaderModule);
799 addStage(vki, device, deviceFeatures, programCollection, "tess_eval",
800 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvalShaderModule);
801 addStage(vki, device, deviceFeatures, programCollection, "geometry", vk::VK_SHADER_STAGE_GEOMETRY_BIT,
802 &m_geometryShaderModule);
803 addStage(vki, device, deviceFeatures, programCollection, "fragment", vk::VK_SHADER_STAGE_FRAGMENT_BIT,
804 &m_fragmentShaderModule);
805
806 DE_ASSERT(!m_stageInfos.empty());
807 }
808
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)809 void RenderInstanceShaders::addStage(const vk::DeviceInterface &vki, vk::VkDevice device,
810 const vk::VkPhysicalDeviceFeatures &deviceFeatures,
811 const vk::BinaryCollection &programCollection, const char *name,
812 vk::VkShaderStageFlagBits stage, vk::Move<vk::VkShaderModule> *outModule)
813 {
814 if (programCollection.contains(name))
815 {
816 if (vk::isShaderStageSupported(deviceFeatures, stage))
817 {
818 vk::Move<vk::VkShaderModule> module =
819 createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0);
820
821 m_stageInfos.push_back(getShaderStageCreateInfo(stage, *module));
822 *outModule = module;
823 }
824 else
825 {
826 // Wait for the GPU to idle so that throwing the exception
827 // below doesn't free in-use GPU resource.
828 vki.deviceWaitIdle(device);
829 TCU_THROW(NotSupportedError, (de::toString(stage) + " is not supported").c_str());
830 }
831 }
832 }
833
getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,vk::VkShaderModule shader) const834 vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,
835 vk::VkShaderModule shader) const
836 {
837 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo = {
838 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
839 DE_NULL,
840 (vk::VkPipelineShaderStageCreateFlags)0,
841 stage, // stage
842 shader, // shader
843 "main",
844 DE_NULL, // pSpecializationInfo
845 };
846 return stageCreateInfo;
847 }
848
849 class SingleCmdRenderInstance : public SingleTargetRenderInstance
850 {
851 public:
852 SingleCmdRenderInstance(Context &context, bool isPrimaryCmdBuf, const tcu::UVec2 &renderSize, const bool bind2);
853
854 private:
855 vk::Move<vk::VkPipeline> createPipeline(vk::VkPipelineLayout pipelineLayout);
856
857 virtual vk::VkPipelineLayout getPipelineLayout(void) const = 0;
858 virtual void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const = 0;
859
860 void renderToTarget(void);
861
862 const bool m_isPrimaryCmdBuf;
863 };
864
SingleCmdRenderInstance(Context & context,bool isPrimaryCmdBuf,const tcu::UVec2 & renderSize,const bool bind2)865 SingleCmdRenderInstance::SingleCmdRenderInstance(Context &context, bool isPrimaryCmdBuf, const tcu::UVec2 &renderSize,
866 const bool bind2)
867 : SingleTargetRenderInstance(context, renderSize, bind2)
868 , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
869 {
870 }
871
createPipeline(vk::VkPipelineLayout pipelineLayout)872 vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline(vk::VkPipelineLayout pipelineLayout)
873 {
874 const RenderInstanceShaders shaderStages(m_vki, m_device, m_context.getDeviceFeatures(),
875 m_context.getBinaryCollection());
876 const vk::VkPrimitiveTopology topology = shaderStages.hasTessellationStage() ?
877 vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
878 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
879 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = {
880 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
881 DE_NULL,
882 (vk::VkPipelineVertexInputStateCreateFlags)0,
883 0u, // bindingCount
884 DE_NULL, // pVertexBindingDescriptions
885 0u, // attributeCount
886 DE_NULL, // pVertexAttributeDescriptions
887 };
888 const vk::VkPipelineInputAssemblyStateCreateInfo iaState = {
889 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
890 DE_NULL,
891 (vk::VkPipelineInputAssemblyStateCreateFlags)0,
892 topology, // topology
893 VK_FALSE, // primitiveRestartEnable
894 };
895 const vk::VkPipelineTessellationStateCreateInfo tessState = {
896 vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, DE_NULL,
897 (vk::VkPipelineTessellationStateCreateFlags)0,
898 3u, // patchControlPoints
899 };
900 const vk::VkViewport viewport = vk::makeViewport(m_targetSize);
901 const vk::VkRect2D renderArea = vk::makeRect2D(m_targetSize);
902 const vk::VkPipelineViewportStateCreateInfo vpState = {
903 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
904 DE_NULL,
905 (vk::VkPipelineViewportStateCreateFlags)0,
906 1u, // viewportCount
907 &viewport,
908 1u,
909 &renderArea,
910 };
911 const vk::VkPipelineRasterizationStateCreateInfo rsState = {
912 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
913 DE_NULL,
914 (vk::VkPipelineRasterizationStateCreateFlags)0,
915 VK_FALSE, // depthClipEnable
916 VK_FALSE, // rasterizerDiscardEnable
917 vk::VK_POLYGON_MODE_FILL, // fillMode
918 vk::VK_CULL_MODE_NONE, // cullMode
919 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
920 VK_FALSE, // depthBiasEnable
921 0.0f, // depthBias
922 0.0f, // depthBiasClamp
923 0.0f, // slopeScaledDepthBias
924 1.0f, // lineWidth
925 };
926 const vk::VkSampleMask sampleMask = 0x01u;
927 const vk::VkPipelineMultisampleStateCreateInfo msState = {
928 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
929 DE_NULL,
930 (vk::VkPipelineMultisampleStateCreateFlags)0,
931 vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples
932 VK_FALSE, // sampleShadingEnable
933 0.0f, // minSampleShading
934 &sampleMask, // sampleMask
935 VK_FALSE, // alphaToCoverageEnable
936 VK_FALSE, // alphaToOneEnable
937 };
938 const vk::VkPipelineDepthStencilStateCreateInfo dsState = {
939 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
940 DE_NULL,
941 (vk::VkPipelineDepthStencilStateCreateFlags)0,
942 VK_FALSE, // depthTestEnable
943 VK_FALSE, // depthWriteEnable
944 vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp
945 VK_FALSE, // depthBoundsTestEnable
946 VK_FALSE, // stencilTestEnable
947 {vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u,
948 0u}, // front
949 {vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u,
950 0u}, // back
951 -1.0f, // minDepthBounds
952 +1.0f, // maxDepthBounds
953 };
954 const vk::VkPipelineColorBlendAttachmentState cbAttachment = {
955 VK_FALSE, // blendEnable
956 vk::VK_BLEND_FACTOR_ZERO, // srcBlendColor
957 vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
958 vk::VK_BLEND_OP_ADD, // blendOpColor
959 vk::VK_BLEND_FACTOR_ZERO, // srcBlendAlpha
960 vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
961 vk::VK_BLEND_OP_ADD, // blendOpAlpha
962 (vk::VK_COLOR_COMPONENT_R_BIT | vk::VK_COLOR_COMPONENT_G_BIT | vk::VK_COLOR_COMPONENT_B_BIT |
963 vk::VK_COLOR_COMPONENT_A_BIT), // channelWriteMask
964 };
965 const vk::VkPipelineColorBlendStateCreateInfo cbState = {
966 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
967 DE_NULL,
968 (vk::VkPipelineColorBlendStateCreateFlags)0,
969 VK_FALSE, // logicOpEnable
970 vk::VK_LOGIC_OP_CLEAR, // logicOp
971 1u, // attachmentCount
972 &cbAttachment, // pAttachments
973 {0.0f, 0.0f, 0.0f, 0.0f}, // blendConst
974 };
975 const vk::VkGraphicsPipelineCreateInfo createInfo = {
976 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
977 DE_NULL,
978 (vk::VkPipelineCreateFlags)0,
979 shaderStages.getNumStages(), // stageCount
980 shaderStages.getStages(), // pStages
981 &vertexInputState, // pVertexInputState
982 &iaState, // pInputAssemblyState
983 (shaderStages.hasTessellationStage() ? &tessState : DE_NULL), // pTessellationState
984 &vpState, // pViewportState
985 &rsState, // pRasterState
986 &msState, // pMultisampleState
987 &dsState, // pDepthStencilState
988 &cbState, // pColorBlendState
989 (const vk::VkPipelineDynamicStateCreateInfo *)DE_NULL, // pDynamicState
990 pipelineLayout, // layout
991 *m_renderPass, // renderPass
992 0u, // subpass
993 (vk::VkPipeline)0, // basePipelineHandle
994 0u, // basePipelineIndex
995 };
996 return createGraphicsPipeline(m_vki, m_device, (vk::VkPipelineCache)0u, &createInfo);
997 }
998
renderToTarget(void)999 void SingleCmdRenderInstance::renderToTarget(void)
1000 {
1001 const vk::VkRect2D renderArea = {
1002 {0, 0}, // offset
1003 {m_targetSize.x(), m_targetSize.y()}, // extent
1004 };
1005 const vk::VkCommandBufferInheritanceInfo passCmdBufInheritInfo = {
1006 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1007 DE_NULL,
1008 (vk::VkRenderPass)*m_renderPass, // renderPass
1009 0u, // subpass
1010 (vk::VkFramebuffer)*m_framebuffer, // framebuffer
1011 VK_FALSE, // occlusionQueryEnable
1012 (vk::VkQueryControlFlags)0,
1013 (vk::VkQueryPipelineStatisticFlags)0,
1014 };
1015 const vk::VkCommandBufferBeginInfo passCmdBufBeginInfo = {
1016 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1017 DE_NULL,
1018 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // flags
1019 &passCmdBufInheritInfo,
1020 };
1021
1022 const vk::VkPipelineLayout pipelineLayout(getPipelineLayout());
1023 const vk::Unique<vk::VkPipeline> pipeline(createPipeline(pipelineLayout));
1024 const vk::Unique<vk::VkCommandBuffer> mainCmd(
1025 vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1026 const vk::Unique<vk::VkCommandBuffer> passCmd(
1027 (m_isPrimaryCmdBuf) ?
1028 (vk::Move<vk::VkCommandBuffer>()) :
1029 (vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY)));
1030 const vk::Unique<vk::VkFence> fence(vk::createFence(m_vki, m_device));
1031 const vk::VkSubpassContents passContents =
1032 (m_isPrimaryCmdBuf) ? (vk::VK_SUBPASS_CONTENTS_INLINE) : (vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1033
1034 if (!m_isPrimaryCmdBuf)
1035 {
1036 VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo));
1037 m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1038 writeDrawCmdBuffer(*passCmd);
1039 endCommandBuffer(m_vki, *passCmd);
1040 }
1041
1042 beginCommandBuffer(m_vki, *mainCmd);
1043 beginRenderPass(m_vki, *mainCmd, *m_renderPass, *m_framebuffer, renderArea, tcu::Vec4(0.0f), passContents);
1044
1045 if (m_isPrimaryCmdBuf)
1046 {
1047 m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1048 writeDrawCmdBuffer(*mainCmd);
1049 }
1050 else
1051 {
1052 m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get());
1053 }
1054
1055 endRenderPass(m_vki, *mainCmd);
1056 endCommandBuffer(m_vki, *mainCmd);
1057
1058 // submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no).
1059 submitCommandsAndWait(m_vki, m_device, m_queue, mainCmd.get());
1060 }
1061
1062 enum DescriptorSetCount
1063 {
1064 DESCRIPTOR_SET_COUNT_SINGLE = 0, //!< single descriptor set
1065 DESCRIPTOR_SET_COUNT_MULTIPLE, //!< multiple descriptor sets
1066 DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS, //!< multiple discontiguous descriptor sets
1067
1068 DESCRIPTOR_SET_COUNT_LAST
1069 };
1070
getDescriptorSetCount(DescriptorSetCount count)1071 uint32_t getDescriptorSetCount(DescriptorSetCount count)
1072 {
1073 switch (count)
1074 {
1075 case DESCRIPTOR_SET_COUNT_SINGLE:
1076 return 1u;
1077 case DESCRIPTOR_SET_COUNT_MULTIPLE:
1078 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1079 return 2u;
1080 default:
1081 DE_FATAL("Impossible");
1082 return 0u;
1083 }
1084 }
1085
getDescriptorSetNdx(DescriptorSetCount count,uint32_t setNdx)1086 uint32_t getDescriptorSetNdx(DescriptorSetCount count, uint32_t setNdx)
1087 {
1088 DE_ASSERT(setNdx < getDescriptorSetCount(count));
1089
1090 const uint32_t contiguousNdx[] = {0, 1};
1091 const uint32_t discontiguousNdx[] = {0, 2};
1092
1093 switch (count)
1094 {
1095 case DESCRIPTOR_SET_COUNT_SINGLE:
1096 return 0u;
1097 case DESCRIPTOR_SET_COUNT_MULTIPLE:
1098 return contiguousNdx[setNdx];
1099 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1100 return discontiguousNdx[setNdx];
1101 default:
1102 DE_FATAL("Impossible");
1103 return 0u;
1104 }
1105 }
1106
1107 enum ShaderInputInterface
1108 {
1109 SHADER_INPUT_SINGLE_DESCRIPTOR = 0, //!< one descriptor
1110 SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with contiguous binding id's
1111 SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with discontiguous binding id's
1112 SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS, //!< multiple descriptors with large gaps between binding id's
1113 SHADER_INPUT_DESCRIPTOR_ARRAY, //!< descriptor array
1114
1115 SHADER_INPUT_LAST
1116 };
1117
getInterfaceNumResources(ShaderInputInterface shaderInterface)1118 uint32_t getInterfaceNumResources(ShaderInputInterface shaderInterface)
1119 {
1120 switch (shaderInterface)
1121 {
1122 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1123 return 1u;
1124 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1125 return 2u;
1126 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1127 return 2u;
1128 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1129 return 2u;
1130 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1131 return 2u;
1132
1133 default:
1134 DE_FATAL("Impossible");
1135 return 0u;
1136 }
1137 }
1138
getArbitraryBindingIndex(uint32_t ndx)1139 uint32_t getArbitraryBindingIndex(uint32_t ndx)
1140 {
1141 DE_ASSERT(ndx < 2);
1142
1143 // Binding decoration value can be any 32-bit unsigned integer value.
1144 // 0xFFFE is the largest binding value accepted by glslang
1145
1146 const uint32_t bufferIndices[] = {
1147 #ifndef CTS_USES_VULKANSC
1148 0x7FFEu, 0xFFFEu
1149 #else
1150 // Use smaller values for VulkanSC since these can produce huge static memory allocations
1151 0x1FFu, 0x3FFu
1152 #endif
1153 };
1154
1155 return bufferIndices[ndx];
1156 }
1157
1158 typedef de::MovePtr<vk::Allocation> AllocationMp;
1159 typedef de::SharedPtr<vk::Allocation> AllocationSp;
1160 typedef vk::Unique<vk::VkBuffer> BufferHandleUp;
1161 typedef de::SharedPtr<BufferHandleUp> BufferHandleSp;
1162 typedef vk::Unique<vk::VkBufferView> BufferViewHandleUp;
1163 typedef de::SharedPtr<BufferViewHandleUp> BufferViewHandleSp;
1164 typedef vk::Unique<vk::VkSampler> SamplerHandleUp;
1165 typedef de::SharedPtr<SamplerHandleUp> SamplerHandleSp;
1166 typedef vk::Unique<vk::VkImage> ImageHandleUp;
1167 typedef de::SharedPtr<ImageHandleUp> ImageHandleSp;
1168 typedef vk::Unique<vk::VkImageView> ImageViewHandleUp;
1169 typedef de::SharedPtr<ImageViewHandleUp> ImageViewHandleSp;
1170 typedef vk::Unique<vk::VkDescriptorSet> DescriptorSetHandleUp;
1171 typedef de::SharedPtr<DescriptorSetHandleUp> DescriptorSetHandleSp;
1172 typedef vk::Unique<vk::VkDescriptorSetLayout> DescriptorSetLayoutHandleUp;
1173 typedef de::SharedPtr<DescriptorSetLayoutHandleUp> DescriptorSetLayoutHandleSp;
1174 #ifndef CTS_USES_VULKANSC
1175 typedef vk::Unique<vk::VkDescriptorUpdateTemplate> UpdateTemplateHandleUp;
1176 typedef de::SharedPtr<UpdateTemplateHandleUp> UpdateTemplateHandleSp;
1177 #endif
1178
1179 class BufferRenderInstance : public SingleCmdRenderInstance
1180 {
1181 public:
1182 BufferRenderInstance(Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
1183 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1184 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
1185 ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
1186 bool dynamicOffsetNonZero, bool bind2);
1187
1188 static std::vector<uint32_t> getViewOffsets(DescriptorSetCount descriptorSetCount,
1189 ShaderInputInterface shaderInterface, bool setViewOffset);
1190
1191 static std::vector<uint32_t> getDynamicOffsets(DescriptorSetCount descriptorSetCount,
1192 ShaderInputInterface shaderInterface, bool dynamicOffsetNonZero);
1193
1194 static std::vector<BufferHandleSp> createSourceBuffers(
1195 const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator,
1196 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1197 ShaderInputInterface shaderInterface, const std::vector<uint32_t> &viewOffset,
1198 const std::vector<uint32_t> &dynamicOffset, std::vector<AllocationSp> &bufferMemory);
1199
1200 static vk::Move<vk::VkBuffer> createSourceBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1201 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
1202 uint32_t setNdx, uint32_t offset, uint32_t bufferSize,
1203 de::MovePtr<vk::Allocation> *outMemory);
1204
1205 static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
1206 vk::VkDescriptorType descriptorType,
1207 DescriptorSetCount descriptorSetCount,
1208 ShaderInputInterface shaderInterface);
1209
1210 static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
1211 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
1212 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
1213 DescriptorUpdateMethod updateMethod);
1214
1215 static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
1216 const vk::DeviceInterface &vki, vk::VkDevice device,
1217 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
1218
1219 static std::vector<DescriptorSetHandleSp> createDescriptorSets(
1220 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
1221 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool descriptorPool,
1222 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1223 ShaderInputInterface shaderInterface, const std::vector<BufferHandleSp> &buffers,
1224 const std::vector<uint32_t> &offsets, vk::DescriptorSetUpdateBuilder &updateBuilder,
1225 std::vector<uint32_t> &descriptorsPerSet,
1226 #ifndef CTS_USES_VULKANSC
1227 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
1228 #endif
1229 vk::VkPipelineLayout pipelineLayout = DE_NULL);
1230
1231 static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
1232 vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1233 vk::VkBuffer sourceBufferA, const uint32_t viewOffsetA, vk::VkBuffer sourceBufferB,
1234 const uint32_t viewOffsetB, vk::VkDescriptorSet descriptorSet,
1235 vk::DescriptorSetUpdateBuilder &updateBuilder,
1236 std::vector<uint32_t> &descriptorsPerSet,
1237 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
1238
1239 #ifndef CTS_USES_VULKANSC
1240 static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
1241 vk::VkDescriptorSetLayout descriptorSetLayout, uint32_t setNdx,
1242 vk::VkDescriptorPool descriptorPool, vk::VkDescriptorType descriptorType,
1243 ShaderInputInterface shaderInterface, vk::VkBuffer sourceBufferA,
1244 const uint32_t viewOffsetA, vk::VkBuffer sourceBufferB,
1245 const uint32_t viewOffsetB, vk::VkDescriptorSet descriptorSet,
1246 std::vector<UpdateTemplateHandleSp> &updateTemplates,
1247 std::vector<RawUpdateRegistry> ®istry, bool withPush = false,
1248 vk::VkPipelineLayout pipelineLayout = 0);
1249 #endif
1250
1251 void logTestPlan(void) const;
1252 vk::VkPipelineLayout getPipelineLayout(void) const;
1253 void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
1254 tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
1255
1256 enum
1257 {
1258 RENDER_SIZE = 128,
1259 BUFFER_DATA_SIZE = 8 * sizeof(float),
1260 BUFFER_SIZE_A = 2048, //!< a lot more than required
1261 BUFFER_SIZE_B = 2560, //!< a lot more than required
1262 BUFFER_SIZE_C = 2128, //!< a lot more than required
1263 BUFFER_SIZE_D = 2136, //!< a lot more than required
1264
1265 STATIC_OFFSET_VALUE_A = 256,
1266 DYNAMIC_OFFSET_VALUE_A = 512,
1267 STATIC_OFFSET_VALUE_B = 1024,
1268 DYNAMIC_OFFSET_VALUE_B = 768,
1269 STATIC_OFFSET_VALUE_C = 512,
1270 DYNAMIC_OFFSET_VALUE_C = 512,
1271 STATIC_OFFSET_VALUE_D = 768,
1272 DYNAMIC_OFFSET_VALUE_D = 1024,
1273 };
1274
1275 const DescriptorUpdateMethod m_updateMethod;
1276 const vk::VkDescriptorType m_descriptorType;
1277 const DescriptorSetCount m_descriptorSetCount;
1278 const ShaderInputInterface m_shaderInterface;
1279 const bool m_setViewOffset;
1280 const bool m_setDynamicOffset;
1281 const bool m_dynamicOffsetNonZero;
1282 const vk::VkShaderStageFlags m_stageFlags;
1283 const vk::VkShaderStageFlags m_existingStages;
1284
1285 const std::vector<uint32_t> m_viewOffset;
1286 const std::vector<uint32_t> m_dynamicOffset;
1287
1288 std::vector<AllocationSp> m_bufferMemory;
1289 const std::vector<BufferHandleSp> m_sourceBuffer;
1290 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
1291 #ifndef CTS_USES_VULKANSC
1292 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
1293 std::vector<RawUpdateRegistry> m_updateRegistry;
1294 #endif
1295 vk::DescriptorSetUpdateBuilder m_updateBuilder;
1296 const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
1297 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
1298 std::vector<uint32_t> m_descriptorsPerSet;
1299 const std::vector<DescriptorSetHandleSp> m_descriptorSets;
1300 };
1301
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)1302 BufferRenderInstance::BufferRenderInstance(Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
1303 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1304 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
1305 ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
1306 bool dynamicOffsetNonZero, bool bind2)
1307 : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
1308 , m_updateMethod(updateMethod)
1309 , m_descriptorType(descriptorType)
1310 , m_descriptorSetCount(descriptorSetCount)
1311 , m_shaderInterface(shaderInterface)
1312 , m_setViewOffset(viewOffset)
1313 , m_setDynamicOffset(dynamicOffset)
1314 , m_dynamicOffsetNonZero(dynamicOffsetNonZero)
1315 , m_stageFlags(stageFlags)
1316 , m_existingStages(existingStages)
1317 , m_viewOffset(getViewOffsets(m_descriptorSetCount, m_shaderInterface, m_setViewOffset))
1318 , m_dynamicOffset(getDynamicOffsets(m_descriptorSetCount, m_shaderInterface, m_dynamicOffsetNonZero))
1319 , m_bufferMemory()
1320 , m_sourceBuffer(createSourceBuffers(m_vki, m_device, m_allocator, m_descriptorType, m_descriptorSetCount,
1321 m_shaderInterface, m_viewOffset, m_dynamicOffset, m_bufferMemory))
1322 , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
1323 #ifndef CTS_USES_VULKANSC
1324 , m_updateTemplates()
1325 , m_updateRegistry()
1326 #endif
1327 , m_updateBuilder()
1328 , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
1329 m_shaderInterface, m_stageFlags, m_updateMethod))
1330 , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
1331 , m_descriptorsPerSet()
1332 , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorSetLayouts, *m_descriptorPool,
1333 m_descriptorType, m_descriptorSetCount, m_shaderInterface, m_sourceBuffer,
1334 m_viewOffset, m_updateBuilder, m_descriptorsPerSet,
1335 #ifndef CTS_USES_VULKANSC
1336 m_updateTemplates, m_updateRegistry,
1337 #endif
1338 *m_pipelineLayout))
1339 {
1340 if (m_setDynamicOffset)
1341 DE_ASSERT(isDynamicDescriptorType(m_descriptorType));
1342 if (m_dynamicOffsetNonZero)
1343 DE_ASSERT(m_setDynamicOffset);
1344 }
1345
getViewOffsets(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool setViewOffset)1346 std::vector<uint32_t> BufferRenderInstance::getViewOffsets(DescriptorSetCount descriptorSetCount,
1347 ShaderInputInterface shaderInterface, bool setViewOffset)
1348 {
1349 const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1350 std::vector<uint32_t> viewOffset;
1351
1352 for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1353 {
1354 const uint32_t staticOffsetValues[] = {STATIC_OFFSET_VALUE_A, STATIC_OFFSET_VALUE_B, STATIC_OFFSET_VALUE_C,
1355 STATIC_OFFSET_VALUE_D};
1356
1357 viewOffset.push_back(
1358 setViewOffset ? (staticOffsetValues[bufferNdx % getInterfaceNumResources(shaderInterface)]) : (0u));
1359 }
1360
1361 return viewOffset;
1362 }
1363
getDynamicOffsets(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool dynamicOffsetNonZero)1364 std::vector<uint32_t> BufferRenderInstance::getDynamicOffsets(DescriptorSetCount descriptorSetCount,
1365 ShaderInputInterface shaderInterface,
1366 bool dynamicOffsetNonZero)
1367 {
1368 const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1369 std::vector<uint32_t> dynamicOffset;
1370
1371 for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1372 {
1373 const uint32_t dynamicOffsetValues[] = {DYNAMIC_OFFSET_VALUE_A, DYNAMIC_OFFSET_VALUE_B, DYNAMIC_OFFSET_VALUE_C,
1374 DYNAMIC_OFFSET_VALUE_D};
1375
1376 dynamicOffset.push_back(
1377 dynamicOffsetNonZero ? (dynamicOffsetValues[bufferNdx % getInterfaceNumResources(shaderInterface)]) : (0u));
1378 }
1379
1380 return dynamicOffset;
1381 }
1382
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)1383 std::vector<BufferHandleSp> BufferRenderInstance::createSourceBuffers(
1384 const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
1385 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
1386 const std::vector<uint32_t> &viewOffset, const std::vector<uint32_t> &dynamicOffset,
1387 std::vector<AllocationSp> &bufferMemory)
1388 {
1389 const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1390 std::vector<uint32_t> effectiveOffset;
1391 std::vector<uint32_t> bufferSize;
1392 std::vector<BufferHandleSp> sourceBuffers;
1393
1394 for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1395 {
1396 const uint32_t bufferSizeValues[] = {BUFFER_SIZE_A, BUFFER_SIZE_B, BUFFER_SIZE_C, BUFFER_SIZE_D};
1397
1398 effectiveOffset.push_back(isDynamicDescriptorType(descriptorType) ?
1399 (viewOffset[bufferNdx] + dynamicOffset[bufferNdx]) :
1400 (viewOffset[bufferNdx]));
1401 bufferSize.push_back(bufferSizeValues[bufferNdx % getInterfaceNumResources(shaderInterface)]);
1402 }
1403
1404 // Create source buffers
1405 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1406 {
1407 for (uint32_t bufferNdx = 0; bufferNdx < getInterfaceNumResources(shaderInterface); bufferNdx++)
1408 {
1409 de::MovePtr<vk::Allocation> memory;
1410 vk::Move<vk::VkBuffer> buffer =
1411 createSourceBuffer(vki, device, allocator, descriptorType, setNdx, effectiveOffset[bufferNdx],
1412 bufferSize[bufferNdx], &memory);
1413
1414 bufferMemory.push_back(AllocationSp(memory.release()));
1415 sourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
1416 }
1417 }
1418
1419 return sourceBuffers;
1420 }
1421
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)1422 vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1423 vk::Allocator &allocator,
1424 vk::VkDescriptorType descriptorType, uint32_t setNdx,
1425 uint32_t offset, uint32_t bufferSize,
1426 de::MovePtr<vk::Allocation> *outMemory)
1427 {
1428 static const float s_colors[] = {
1429 0.0f, 1.0f, 0.0f, 1.0f, // green
1430 1.0f, 1.0f, 0.0f, 1.0f, // yellow
1431 0.0f, 0.0f, 1.0f, 1.0f, // blue
1432 1.0f, 0.0f, 0.0f, 1.0f // red
1433 };
1434 DE_STATIC_ASSERT(sizeof(s_colors) / 2 == BUFFER_DATA_SIZE);
1435 DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize);
1436 DE_ASSERT(offset % sizeof(float) == 0);
1437 DE_ASSERT(bufferSize % sizeof(float) == 0);
1438
1439 const bool isUniformBuffer = isUniformDescriptorType(descriptorType);
1440 const vk::VkBufferUsageFlags usageFlags =
1441 (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1442 const float preGuardValue = 0.5f;
1443 const float postGuardValue = 0.75f;
1444 const vk::VkBufferCreateInfo bufferCreateInfo = {
1445 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1446 DE_NULL,
1447 0u, // flags
1448 bufferSize, // size
1449 usageFlags, // usage
1450 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1451 0u, // queueFamilyCount
1452 DE_NULL, // pQueueFamilyIndices
1453 };
1454 vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &bufferCreateInfo));
1455 de::MovePtr<vk::Allocation> bufferMemory =
1456 allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible);
1457 void *const mapPtr = bufferMemory->getHostPtr();
1458
1459 // guard with interesting values
1460 for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float))
1461 deMemcpy((uint8_t *)mapPtr + preGuardOffset, &preGuardValue, sizeof(float));
1462
1463 deMemcpy((uint8_t *)mapPtr + offset, &s_colors[8 * (setNdx % 2)], sizeof(s_colors) / 2);
1464 for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors) / 2;
1465 postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float))
1466 deMemcpy((uint8_t *)mapPtr + postGuardOffset, &postGuardValue, sizeof(float));
1467 deMemset((uint8_t *)mapPtr + offset + sizeof(s_colors) / 2, 0x5A,
1468 (size_t)bufferSize - (size_t)offset -
1469 sizeof(s_colors) / 2); // fill with interesting pattern that produces valid floats
1470
1471 flushAlloc(vki, device, *bufferMemory);
1472
1473 // Flushed host-visible memory is automatically made available to the GPU, no barrier is needed.
1474
1475 *outMemory = bufferMemory;
1476 return buffer;
1477 }
1478
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)1479 vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
1480 vk::VkDevice device,
1481 vk::VkDescriptorType descriptorType,
1482 DescriptorSetCount descriptorSetCount,
1483 ShaderInputInterface shaderInterface)
1484 {
1485 return vk::DescriptorPoolBuilder()
1486 .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
1487 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1488 getDescriptorSetCount(descriptorSetCount));
1489 }
1490
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)1491 std::vector<DescriptorSetLayoutHandleSp> BufferRenderInstance::createDescriptorSetLayouts(
1492 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
1493 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
1494 DescriptorUpdateMethod updateMethod)
1495 {
1496 #ifdef CTS_USES_VULKANSC
1497 DE_UNREF(updateMethod);
1498 #endif
1499 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
1500
1501 #ifndef CTS_USES_VULKANSC
1502 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
1503 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1504 {
1505 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
1506 }
1507 #endif
1508
1509 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
1510
1511 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1512 {
1513 vk::DescriptorSetLayoutBuilder builder;
1514 switch (shaderInterface)
1515 {
1516 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1517 builder.addSingleBinding(descriptorType, stageFlags);
1518 break;
1519
1520 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1521 builder.addSingleBinding(descriptorType, stageFlags);
1522 builder.addSingleBinding(descriptorType, stageFlags);
1523 break;
1524
1525 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1526 builder.addSingleIndexedBinding(descriptorType, stageFlags, 0u);
1527 builder.addSingleIndexedBinding(descriptorType, stageFlags, 2u);
1528 break;
1529
1530 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1531 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
1532 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
1533 break;
1534
1535 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1536 builder.addArrayBinding(descriptorType, 2u, stageFlags);
1537 break;
1538
1539 default:
1540 DE_FATAL("Impossible");
1541 }
1542
1543 vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
1544 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
1545
1546 // Add an empty descriptor set layout between sets 0 and 2
1547 if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
1548 {
1549 vk::DescriptorSetLayoutBuilder emptyBuilder;
1550 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
1551 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
1552 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
1553 }
1554 }
1555 return descriptorSetLayouts;
1556 }
1557
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)1558 vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout(
1559 const vk::DeviceInterface &vki, vk::VkDevice device,
1560 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
1561 {
1562 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
1563 for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
1564 layoutHandles.push_back(**descriptorSetLayout[setNdx]);
1565
1566 const vk::VkPipelineLayoutCreateInfo createInfo = {
1567 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1568 DE_NULL,
1569 (vk::VkPipelineLayoutCreateFlags)0,
1570 (uint32_t)layoutHandles.size(), // descriptorSetCount
1571 &layoutHandles.front(), // pSetLayouts
1572 0u, // pushConstantRangeCount
1573 DE_NULL, // pPushConstantRanges
1574 };
1575 return vk::createPipelineLayout(vki, device, &createInfo);
1576 }
1577
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)1578 std::vector<DescriptorSetHandleSp> BufferRenderInstance::createDescriptorSets(
1579 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
1580 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool descriptorPool,
1581 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
1582 const std::vector<BufferHandleSp> &buffers, const std::vector<uint32_t> &offsets,
1583 vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
1584 #ifndef CTS_USES_VULKANSC
1585 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
1586 #endif
1587 vk::VkPipelineLayout pipelineLayout)
1588 {
1589 #ifdef CTS_USES_VULKANSC
1590 DE_UNREF(pipelineLayout);
1591 #endif
1592 std::vector<DescriptorSetHandleSp> descriptorSets;
1593
1594 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1595 {
1596 vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
1597 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
1598 descriptorPool, 1u, &layout};
1599
1600 vk::VkBuffer bufferA = **buffers[(setNdx * getInterfaceNumResources(shaderInterface)) % buffers.size()];
1601 vk::VkBuffer bufferB = **buffers[(setNdx * getInterfaceNumResources(shaderInterface) + 1) % buffers.size()];
1602 uint32_t offsetA = offsets[(setNdx * getInterfaceNumResources(shaderInterface)) % offsets.size()];
1603 uint32_t offsetB = offsets[(setNdx * getInterfaceNumResources(shaderInterface) + 1) % offsets.size()];
1604
1605 vk::Move<vk::VkDescriptorSet> descriptorSet;
1606
1607 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
1608 updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1609 {
1610 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
1611 }
1612 else
1613 {
1614 descriptorSet = vk::Move<vk::VkDescriptorSet>();
1615 }
1616
1617 #ifndef CTS_USES_VULKANSC
1618 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
1619 {
1620 writeDescriptorSetWithTemplate(vki, device, layout, setNdx, descriptorPool, descriptorType, shaderInterface,
1621 bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplates,
1622 updateRegistry);
1623 }
1624 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1625 {
1626 writeDescriptorSetWithTemplate(vki, device, layout, setNdx, descriptorPool, descriptorType, shaderInterface,
1627 bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplates,
1628 updateRegistry, true, pipelineLayout);
1629 }
1630 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1631 {
1632 writeDescriptorSet(vki, device, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB,
1633 *descriptorSet, updateBuilder, descriptorsPerSet, updateMethod);
1634 }
1635 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
1636 #endif
1637 {
1638 writeDescriptorSet(vki, device, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB,
1639 *descriptorSet, updateBuilder, descriptorsPerSet);
1640 }
1641
1642 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
1643 }
1644 return descriptorSets;
1645 }
1646
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)1647 void BufferRenderInstance::writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
1648 vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1649 vk::VkBuffer bufferA, const uint32_t offsetA, vk::VkBuffer bufferB,
1650 const uint32_t offsetB, vk::VkDescriptorSet descriptorSet,
1651 vk::DescriptorSetUpdateBuilder &updateBuilder,
1652 std::vector<uint32_t> &descriptorsPerSet,
1653 DescriptorUpdateMethod updateMethod)
1654 {
1655 const vk::VkDescriptorBufferInfo bufferInfos[2] = {
1656 vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1657 vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1658 };
1659 uint32_t numDescriptors = 0u;
1660
1661 switch (shaderInterface)
1662 {
1663 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1664 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1665 &bufferInfos[0]);
1666 numDescriptors++;
1667 break;
1668
1669 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1670 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1671 &bufferInfos[0]);
1672 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
1673 &bufferInfos[1]);
1674 numDescriptors += 2;
1675 break;
1676
1677 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1678 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1679 &bufferInfos[0]);
1680 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
1681 &bufferInfos[1]);
1682 numDescriptors += 2;
1683 break;
1684
1685 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1686 updateBuilder.writeSingle(descriptorSet,
1687 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
1688 descriptorType, &bufferInfos[0]);
1689 updateBuilder.writeSingle(descriptorSet,
1690 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
1691 descriptorType, &bufferInfos[1]);
1692 numDescriptors += 2;
1693 break;
1694
1695 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1696 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1697 2u, bufferInfos);
1698 numDescriptors++;
1699 break;
1700
1701 default:
1702 DE_FATAL("Impossible");
1703 }
1704
1705 descriptorsPerSet.push_back(numDescriptors);
1706
1707 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
1708 {
1709 updateBuilder.update(vki, device);
1710 updateBuilder.clear();
1711 }
1712 }
1713
1714 #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)1715 void BufferRenderInstance::writeDescriptorSetWithTemplate(
1716 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorSetLayout layout, uint32_t setNdx,
1717 vk::VkDescriptorPool descriptorPool, vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1718 vk::VkBuffer bufferA, const uint32_t offsetA, vk::VkBuffer bufferB, const uint32_t offsetB,
1719 vk::VkDescriptorSet descriptorSet, std::vector<UpdateTemplateHandleSp> &updateTemplates,
1720 std::vector<RawUpdateRegistry> ®istry, bool withPush, vk::VkPipelineLayout pipelineLayout)
1721 {
1722 DE_UNREF(descriptorPool);
1723 const vk::VkDescriptorBufferInfo bufferInfos[2] = {
1724 vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1725 vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1726 };
1727 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
1728 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
1729 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
1730 DE_NULL,
1731 0,
1732 0, // descriptorUpdateEntryCount
1733 DE_NULL, // pDescriptorUpdateEntries
1734 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
1735 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
1736 layout,
1737 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1738 pipelineLayout,
1739 setNdx};
1740
1741 RawUpdateRegistry updateRegistry;
1742
1743 updateRegistry.addWriteObject(bufferInfos[0]);
1744 updateRegistry.addWriteObject(bufferInfos[1]);
1745
1746 switch (shaderInterface)
1747 {
1748 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1749 updateEntries.push_back(
1750 createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1751 break;
1752
1753 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1754 updateEntries.push_back(
1755 createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1756 updateEntries.push_back(
1757 createTemplateBinding(1u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
1758 break;
1759
1760 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1761 updateEntries.push_back(
1762 createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1763 updateEntries.push_back(
1764 createTemplateBinding(2u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
1765 break;
1766
1767 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1768 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
1769 updateRegistry.getWriteObjectOffset(0), 0));
1770 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
1771 updateRegistry.getWriteObjectOffset(1), 0));
1772 break;
1773
1774 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1775 updateEntries.push_back(createTemplateBinding(0u, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
1776 sizeof(bufferInfos[0])));
1777 break;
1778
1779 default:
1780 DE_FATAL("Impossible");
1781 }
1782
1783 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
1784 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
1785
1786 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
1787 vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
1788 updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
1789 registry.push_back(updateRegistry);
1790
1791 if (!withPush)
1792 {
1793 vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
1794 registry.back().getRawPointer());
1795 }
1796 }
1797 #endif
1798
logTestPlan(void) const1799 void BufferRenderInstance::logTestPlan(void) const
1800 {
1801 std::ostringstream msg;
1802
1803 msg << "Rendering 2x2 yellow-green grid.\n"
1804 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
1805 "Multiple descriptor sets. ")
1806 << "Each descriptor set contains "
1807 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
1808 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
1809 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
1810 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
1811 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
1812 (const char *)DE_NULL)
1813 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
1814 << "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
1815
1816 if (isDynamicDescriptorType(m_descriptorType))
1817 {
1818 if (m_setDynamicOffset)
1819 {
1820 msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
1821 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
1822 }
1823 else
1824 {
1825 msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
1826 }
1827 }
1828
1829 if (m_stageFlags == 0u)
1830 {
1831 msg << "Descriptors are not accessed in any shader stage.\n";
1832 }
1833 else
1834 {
1835 msg << "Descriptors are accessed in {"
1836 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
1837 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
1838 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
1839 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
1840 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.\n";
1841 }
1842
1843 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
1844 }
1845
getPipelineLayout(void) const1846 vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout(void) const
1847 {
1848 return *m_pipelineLayout;
1849 }
1850
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const1851 void BufferRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
1852 {
1853 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
1854 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1855 {
1856 std::vector<vk::VkDescriptorSet> sets;
1857 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1858 sets.push_back(**m_descriptorSets[setNdx]);
1859
1860 switch (m_descriptorSetCount)
1861 {
1862 case DESCRIPTOR_SET_COUNT_SINGLE:
1863 case DESCRIPTOR_SET_COUNT_MULTIPLE:
1864 {
1865 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1866 const uint32_t numOffsets = (!m_setDynamicOffset) ? (0u) : ((uint32_t)m_dynamicOffset.size());
1867 const uint32_t *const dynamicOffsetPtr = (!m_setDynamicOffset) ? (DE_NULL) : (&m_dynamicOffset.front());
1868
1869 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1870 getPipelineLayout(), 0, (int)sets.size(), &sets.front(), numOffsets, dynamicOffsetPtr,
1871 m_bind2);
1872 break;
1873 }
1874 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1875 {
1876 uint32_t dynamicOffsetNdx = 0u;
1877
1878 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1879 {
1880 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1881 const uint32_t numOffsets =
1882 (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
1883 const uint32_t *const dynamicOffsetPtr =
1884 (!m_setDynamicOffset) ? (DE_NULL) : (&m_dynamicOffset[dynamicOffsetNdx]);
1885 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
1886
1887 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1888 getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], numOffsets,
1889 dynamicOffsetPtr, m_bind2);
1890
1891 dynamicOffsetNdx += getInterfaceNumResources(m_shaderInterface);
1892 }
1893 break;
1894 }
1895 default:
1896 DE_FATAL("Impossible");
1897 }
1898 }
1899 #ifndef CTS_USES_VULKANSC
1900 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1901 {
1902 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1903 m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, **m_updateTemplates[setNdx], getPipelineLayout(), setNdx,
1904 (const void *)m_updateRegistry[setNdx].getRawPointer());
1905 }
1906 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1907 {
1908 uint32_t descriptorNdx = 0u;
1909 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1910 {
1911 const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
1912 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, setNdx,
1913 descriptorNdx, numDescriptors);
1914 descriptorNdx += numDescriptors;
1915 }
1916 }
1917 #endif
1918
1919 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
1920 }
1921
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const1922 tcu::TestStatus BufferRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
1923 {
1924 const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
1925 const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
1926 const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
1927 tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
1928
1929 tcu::Vec4 sample0 = tcu::Vec4(0.0f);
1930 tcu::Vec4 sample1 = tcu::Vec4(0.0f);
1931
1932 if (m_stageFlags)
1933 {
1934 const tcu::Vec4 colors[] = {
1935 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), // green
1936 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), // yellow
1937 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), // blue
1938 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), // red
1939 };
1940
1941 for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
1942 {
1943 sample0 += colors[2 * (setNdx % 2)];
1944 sample1 += colors[2 * (setNdx % 2) + 1];
1945 }
1946
1947 if (numDescriptorSets > 1)
1948 {
1949 sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
1950 sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
1951 }
1952 }
1953 else
1954 {
1955 sample0 = green;
1956 sample1 = yellow;
1957 }
1958
1959 drawQuadrantReferenceResult(reference.getAccess(), sample1, sample0, sample0, sample1);
1960
1961 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
1962 result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
1963 return tcu::TestStatus::fail("Image verification failed");
1964 else
1965 return tcu::TestStatus::pass("Pass");
1966 }
1967
1968 class ComputeInstanceResultBuffer
1969 {
1970 public:
1971 enum
1972 {
1973 DATA_SIZE = sizeof(tcu::Vec4[4])
1974 };
1975
1976 ComputeInstanceResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator);
1977
1978 void readResultContentsTo(tcu::Vec4 (*results)[4]) const;
1979
getBuffer(void) const1980 inline vk::VkBuffer getBuffer(void) const
1981 {
1982 return *m_buffer;
1983 }
getResultReadBarrier(void) const1984 inline const vk::VkBufferMemoryBarrier *getResultReadBarrier(void) const
1985 {
1986 return &m_bufferBarrier;
1987 }
1988
1989 private:
1990 static vk::Move<vk::VkBuffer> createResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1991 vk::Allocator &allocator,
1992 de::MovePtr<vk::Allocation> *outAllocation);
1993
1994 static vk::VkBufferMemoryBarrier createResultBufferBarrier(vk::VkBuffer buffer);
1995
1996 const vk::DeviceInterface &m_vki;
1997 const vk::VkDevice m_device;
1998
1999 de::MovePtr<vk::Allocation> m_bufferMem;
2000 const vk::Unique<vk::VkBuffer> m_buffer;
2001 const vk::VkBufferMemoryBarrier m_bufferBarrier;
2002 };
2003
ComputeInstanceResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator)2004 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
2005 vk::Allocator &allocator)
2006 : m_vki(vki)
2007 , m_device(device)
2008 , m_bufferMem(DE_NULL)
2009 , m_buffer(createResultBuffer(m_vki, m_device, allocator, &m_bufferMem))
2010 , m_bufferBarrier(createResultBufferBarrier(*m_buffer))
2011 {
2012 }
2013
readResultContentsTo(tcu::Vec4 (* results)[4]) const2014 void ComputeInstanceResultBuffer::readResultContentsTo(tcu::Vec4 (*results)[4]) const
2015 {
2016 invalidateAlloc(m_vki, m_device, *m_bufferMem);
2017 deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
2018 }
2019
createResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,de::MovePtr<vk::Allocation> * outAllocation)2020 vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer(const vk::DeviceInterface &vki,
2021 vk::VkDevice device, vk::Allocator &allocator,
2022 de::MovePtr<vk::Allocation> *outAllocation)
2023 {
2024 const vk::VkBufferCreateInfo createInfo = {
2025 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
2026 DE_NULL,
2027 0u, // flags
2028 (vk::VkDeviceSize)DATA_SIZE, // size
2029 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage
2030 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
2031 0u, // queueFamilyCount
2032 DE_NULL, // pQueueFamilyIndices
2033 };
2034 vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &createInfo));
2035 de::MovePtr<vk::Allocation> allocation(
2036 allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
2037 const float clearValue = -1.0f;
2038 void *mapPtr = allocation->getHostPtr();
2039
2040 for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
2041 deMemcpy(((uint8_t *)mapPtr) + offset, &clearValue, sizeof(float));
2042
2043 flushAlloc(vki, device, *allocation);
2044
2045 *outAllocation = allocation;
2046 return buffer;
2047 }
2048
createResultBufferBarrier(vk::VkBuffer buffer)2049 vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier(vk::VkBuffer buffer)
2050 {
2051 const vk::VkBufferMemoryBarrier bufferBarrier = {
2052 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2053 DE_NULL,
2054 vk::VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask
2055 vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask
2056 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
2057 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
2058 buffer, // buffer
2059 (vk::VkDeviceSize)0u, // offset
2060 DATA_SIZE, // size
2061 };
2062 return bufferBarrier;
2063 }
2064
2065 class ComputePipeline
2066 {
2067 public:
2068 ComputePipeline(const vk::DeviceInterface &vki, vk::VkDevice device, const vk::BinaryCollection &programCollection,
2069 uint32_t numDescriptorSets, const vk::VkDescriptorSetLayout *descriptorSetLayouts);
2070
getPipeline(void) const2071 inline vk::VkPipeline getPipeline(void) const
2072 {
2073 return *m_pipeline;
2074 }
getPipelineLayout(void) const2075 inline vk::VkPipelineLayout getPipelineLayout(void) const
2076 {
2077 return *m_pipelineLayout;
2078 }
2079
2080 private:
2081 static vk::Move<vk::VkPipelineLayout> createPipelineLayout(const vk::DeviceInterface &vki, vk::VkDevice device,
2082 uint32_t numDescriptorSets,
2083 const vk::VkDescriptorSetLayout *descriptorSetLayouts);
2084
2085 static vk::Move<vk::VkPipeline> createPipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2086 const vk::BinaryCollection &programCollection,
2087 vk::VkPipelineLayout layout);
2088
2089 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
2090 const vk::Unique<vk::VkPipeline> m_pipeline;
2091 };
2092
ComputePipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,uint32_t numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)2093 ComputePipeline::ComputePipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2094 const vk::BinaryCollection &programCollection, uint32_t numDescriptorSets,
2095 const vk::VkDescriptorSetLayout *descriptorSetLayouts)
2096 : m_pipelineLayout(createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts))
2097 , m_pipeline(createPipeline(vki, device, programCollection, *m_pipelineLayout))
2098 {
2099 }
2100
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)2101 vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout(
2102 const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t numDescriptorSets,
2103 const vk::VkDescriptorSetLayout *descriptorSetLayouts)
2104 {
2105 const vk::VkPipelineLayoutCreateInfo createInfo = {
2106 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2107 DE_NULL,
2108 (vk::VkPipelineLayoutCreateFlags)0,
2109 numDescriptorSets, // descriptorSetCount
2110 descriptorSetLayouts, // pSetLayouts
2111 0u, // pushConstantRangeCount
2112 DE_NULL, // pPushConstantRanges
2113 };
2114 return vk::createPipelineLayout(vki, device, &createInfo);
2115 }
2116
createPipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,vk::VkPipelineLayout layout)2117 vk::Move<vk::VkPipeline> ComputePipeline::createPipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2118 const vk::BinaryCollection &programCollection,
2119 vk::VkPipelineLayout layout)
2120 {
2121 const vk::Unique<vk::VkShaderModule> computeModule(
2122 vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u));
2123 const vk::VkPipelineShaderStageCreateInfo cs = {
2124 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2125 DE_NULL,
2126 (vk::VkPipelineShaderStageCreateFlags)0,
2127 vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage
2128 *computeModule, // shader
2129 "main",
2130 DE_NULL, // pSpecializationInfo
2131 };
2132 const vk::VkComputePipelineCreateInfo createInfo = {
2133 vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2134 DE_NULL,
2135 0u, // flags
2136 cs, // cs
2137 layout, // layout
2138 (vk::VkPipeline)0, // basePipelineHandle
2139 0u, // basePipelineIndex
2140 };
2141 return createComputePipeline(vki, device, (vk::VkPipelineCache)0u, &createInfo);
2142 }
2143
2144 class ComputeCommand
2145 {
2146 public:
2147 ComputeCommand(const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkPipeline pipeline,
2148 vk::VkPipelineLayout pipelineLayout, const tcu::UVec3 &numWorkGroups,
2149 ShaderInputInterface shaderInterface, DescriptorSetCount descriptorSetCount,
2150 const vk::VkDescriptorSet *descriptorSets, int numDynamicOffsets, const uint32_t *dynamicOffsets,
2151 int numPreBarriers, const vk::VkBufferMemoryBarrier *preBarriers, int numPostBarriers,
2152 const vk::VkBufferMemoryBarrier *postBarriers, const bool bind2);
2153
2154 void submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue
2155 #ifndef CTS_USES_VULKANSC
2156 ,
2157 std::vector<UpdateTemplateHandleSp> *updateTemplates = DE_NULL,
2158 std::vector<RawUpdateRegistry> *updateRegistry = DE_NULL
2159 #endif
2160 ) const;
2161 #ifndef CTS_USES_VULKANSC
2162 void submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue, vk::DescriptorSetUpdateBuilder &updateBuilder,
2163 std::vector<uint32_t> &descriptorsPerSet) const;
2164 #endif
2165
2166 private:
2167 const bool m_bind2;
2168 const vk::DeviceInterface &m_vki;
2169 const vk::VkDevice m_device;
2170 const vk::VkPipeline m_pipeline;
2171 const vk::VkPipelineLayout m_pipelineLayout;
2172 const tcu::UVec3 m_numWorkGroups;
2173 const ShaderInputInterface m_shaderInterface;
2174 const DescriptorSetCount m_descriptorSetCount;
2175 const vk::VkDescriptorSet *const m_descriptorSets;
2176 const int m_numDynamicOffsets;
2177 const uint32_t *const m_dynamicOffsets;
2178 const int m_numPreBarriers;
2179 const vk::VkBufferMemoryBarrier *const m_preBarriers;
2180 const int m_numPostBarriers;
2181 const vk::VkBufferMemoryBarrier *const m_postBarriers;
2182 };
2183
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)2184 ComputeCommand::ComputeCommand(const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkPipeline pipeline,
2185 vk::VkPipelineLayout pipelineLayout, const tcu::UVec3 &numWorkGroups,
2186 ShaderInputInterface shaderInterface, DescriptorSetCount descriptorSetCount,
2187 const vk::VkDescriptorSet *descriptorSets, int numDynamicOffsets,
2188 const uint32_t *dynamicOffsets, int numPreBarriers,
2189 const vk::VkBufferMemoryBarrier *preBarriers, int numPostBarriers,
2190 const vk::VkBufferMemoryBarrier *postBarriers, const bool bind2)
2191 : m_bind2(bind2)
2192 , m_vki(vki)
2193 , m_device(device)
2194 , m_pipeline(pipeline)
2195 , m_pipelineLayout(pipelineLayout)
2196 , m_numWorkGroups(numWorkGroups)
2197 , m_shaderInterface(shaderInterface)
2198 , m_descriptorSetCount(descriptorSetCount)
2199 , m_descriptorSets(descriptorSets)
2200 , m_numDynamicOffsets(numDynamicOffsets)
2201 , m_dynamicOffsets(dynamicOffsets)
2202 , m_numPreBarriers(numPreBarriers)
2203 , m_preBarriers(preBarriers)
2204 , m_numPostBarriers(numPostBarriers)
2205 , m_postBarriers(postBarriers)
2206 {
2207 }
2208
submitAndWait(uint32_t queueFamilyIndex,vk::VkQueue queue,std::vector<UpdateTemplateHandleSp> * updateTemplates,std::vector<RawUpdateRegistry> * updateRegistry) const2209 void ComputeCommand::submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue
2210 #ifndef CTS_USES_VULKANSC
2211 ,
2212 std::vector<UpdateTemplateHandleSp> *updateTemplates,
2213 std::vector<RawUpdateRegistry> *updateRegistry
2214 #endif
2215 ) const
2216 {
2217 const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = {
2218 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, DE_NULL,
2219 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
2220 queueFamilyIndex, // queueFamilyIndex
2221 };
2222 const vk::Unique<vk::VkCommandPool> cmdPool(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
2223
2224 const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo = {
2225 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
2226 DE_NULL,
2227 *cmdPool, // cmdPool
2228 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
2229 1u, // count
2230 };
2231
2232 const vk::Unique<vk::VkCommandBuffer> cmd(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
2233
2234 beginCommandBuffer(m_vki, *cmd);
2235
2236 m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
2237
2238 // normal update
2239 #ifndef CTS_USES_VULKANSC
2240 if (updateTemplates == DE_NULL)
2241 #endif
2242 {
2243 switch (m_descriptorSetCount)
2244 {
2245 case DESCRIPTOR_SET_COUNT_SINGLE:
2246 case DESCRIPTOR_SET_COUNT_MULTIPLE:
2247 {
2248 bindDescriptorSets(m_vki, *cmd, vk::VK_SHADER_STAGE_COMPUTE_BIT, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2249 vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0,
2250 getDescriptorSetCount(m_descriptorSetCount), m_descriptorSets, m_numDynamicOffsets,
2251 m_dynamicOffsets, m_bind2);
2252 break;
2253 }
2254 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
2255 {
2256 uint32_t dynamicOffsetNdx = 0u;
2257
2258 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2259 {
2260 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
2261 const uint32_t numOffsets =
2262 (!m_numDynamicOffsets) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
2263 const uint32_t *const dynamicOffsetPtr =
2264 (!m_numDynamicOffsets) ? (DE_NULL) : (&m_dynamicOffsets[dynamicOffsetNdx]);
2265 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
2266
2267 bindDescriptorSets(m_vki, *cmd, vk::VK_SHADER_STAGE_COMPUTE_BIT, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2268 vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, descriptorSetNdx, 1u,
2269 &m_descriptorSets[setNdx], numOffsets, dynamicOffsetPtr, m_bind2);
2270
2271 dynamicOffsetNdx += getInterfaceNumResources(m_shaderInterface);
2272 }
2273 break;
2274 }
2275 default:
2276 DE_FATAL("Impossible");
2277 }
2278 }
2279 #ifndef CTS_USES_VULKANSC
2280 // update with push template
2281 else
2282 {
2283 for (uint32_t setNdx = 0; setNdx < (uint32_t)(*updateTemplates).size(); setNdx++)
2284 m_vki.cmdPushDescriptorSetWithTemplateKHR(*cmd, **(*updateTemplates)[setNdx], m_pipelineLayout,
2285 getDescriptorSetNdx(m_descriptorSetCount, setNdx),
2286 (const void *)(*updateRegistry)[setNdx].getRawPointer());
2287 }
2288 #endif
2289
2290 if (m_numPreBarriers)
2291 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2292 (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, m_numPreBarriers,
2293 m_preBarriers, 0, (const vk::VkImageMemoryBarrier *)DE_NULL);
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, (const vk::VkMemoryBarrier *)DE_NULL, m_numPostBarriers,
2298 m_postBarriers, 0, (const vk::VkImageMemoryBarrier *)DE_NULL);
2299 endCommandBuffer(m_vki, *cmd);
2300
2301 submitCommandsAndWait(m_vki, m_device, queue, cmd.get());
2302 }
2303
2304 #ifndef CTS_USES_VULKANSC
2305 //cmdPushDescriptorSet variant
submitAndWait(uint32_t queueFamilyIndex,vk::VkQueue queue,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet) const2306 void ComputeCommand::submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue,
2307 vk::DescriptorSetUpdateBuilder &updateBuilder,
2308 std::vector<uint32_t> &descriptorsPerSet) const
2309 {
2310 const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = {
2311 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, DE_NULL,
2312 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
2313 queueFamilyIndex, // queueFamilyIndex
2314 };
2315 const vk::Unique<vk::VkCommandPool> cmdPool(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
2316
2317 const vk::Unique<vk::VkCommandBuffer> cmd(
2318 vk::allocateCommandBuffer(m_vki, m_device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2319
2320 beginCommandBuffer(m_vki, *cmd);
2321
2322 m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
2323
2324 {
2325 uint32_t descriptorNdx = 0u;
2326 for (uint32_t setNdx = 0; setNdx < (uint32_t)descriptorsPerSet.size(); setNdx++)
2327 {
2328 const uint32_t numDescriptors = descriptorsPerSet[setNdx];
2329 updateBuilder.updateWithPush(m_vki, *cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout,
2330 getDescriptorSetNdx(m_descriptorSetCount, setNdx), descriptorNdx,
2331 numDescriptors);
2332 descriptorNdx += numDescriptors;
2333 }
2334 }
2335
2336 if (m_numPreBarriers)
2337 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2338 (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, m_numPreBarriers,
2339 m_preBarriers, 0, (const vk::VkImageMemoryBarrier *)DE_NULL);
2340
2341 m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
2342 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
2343 (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, m_numPostBarriers,
2344 m_postBarriers, 0, (const vk::VkImageMemoryBarrier *)DE_NULL);
2345 endCommandBuffer(m_vki, *cmd);
2346
2347 submitCommandsAndWait(m_vki, m_device, queue, cmd.get());
2348 }
2349 #endif
2350
2351 class BufferComputeInstance : public vkt::TestInstance
2352 {
2353 public:
2354 BufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
2355 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, bool viewOffset,
2356 bool dynamicOffset, bool dynamicOffsetNonZero, bool bind2);
2357
2358 private:
2359 vk::Move<vk::VkBuffer> createColorDataBuffer(uint32_t offset, uint32_t bufferSize, const tcu::Vec4 &value1,
2360 const tcu::Vec4 &value2, de::MovePtr<vk::Allocation> *outAllocation);
2361 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
2362 vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
2363 vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
2364 uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA,
2365 vk::VkBuffer viewB, uint32_t offsetB, vk::VkBuffer resBuf);
2366 void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA,
2367 vk::VkBuffer viewB, uint32_t offsetB, vk::VkBuffer resBuf);
2368 #ifndef CTS_USES_VULKANSC
2369 void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
2370 uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA, vk::VkBuffer viewB,
2371 uint32_t offsetB, vk::VkBuffer resBuf, bool withPush = false,
2372 vk::VkPipelineLayout pipelineLayout = DE_NULL);
2373 #endif
2374
2375 tcu::TestStatus iterate(void);
2376 void logTestPlan(void) const;
2377 tcu::TestStatus testResourceAccess(void);
2378
2379 enum
2380 {
2381 STATIC_OFFSET_VALUE_A = 256,
2382 DYNAMIC_OFFSET_VALUE_A = 512,
2383 STATIC_OFFSET_VALUE_B = 1024,
2384 DYNAMIC_OFFSET_VALUE_B = 768,
2385 };
2386
2387 const DescriptorUpdateMethod m_updateMethod;
2388 const vk::VkDescriptorType m_descriptorType;
2389 const DescriptorSetCount m_descriptorSetCount;
2390 const ShaderInputInterface m_shaderInterface;
2391 const bool m_setViewOffset;
2392 const bool m_setDynamicOffset;
2393 const bool m_dynamicOffsetNonZero;
2394 const bool m_bind2;
2395
2396 #ifndef CTS_USES_VULKANSC
2397 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
2398 #endif
2399 const vk::DeviceInterface &m_vki;
2400 const vk::VkDevice m_device;
2401 const vk::VkQueue m_queue;
2402 const uint32_t m_queueFamilyIndex;
2403 vk::Allocator &m_allocator;
2404
2405 const ComputeInstanceResultBuffer m_result;
2406
2407 #ifndef CTS_USES_VULKANSC
2408 std::vector<RawUpdateRegistry> m_updateRegistry;
2409 #endif
2410 vk::DescriptorSetUpdateBuilder m_updateBuilder;
2411 std::vector<uint32_t> m_descriptorsPerSet;
2412 };
2413
BufferComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero,bool bind2)2414 BufferComputeInstance::BufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
2415 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
2416 ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
2417 bool dynamicOffsetNonZero, bool bind2)
2418 : vkt::TestInstance(context)
2419 , m_updateMethod(updateMethod)
2420 , m_descriptorType(descriptorType)
2421 , m_descriptorSetCount(descriptorSetCount)
2422 , m_shaderInterface(shaderInterface)
2423 , m_setViewOffset(viewOffset)
2424 , m_setDynamicOffset(dynamicOffset)
2425 , m_dynamicOffsetNonZero(dynamicOffsetNonZero)
2426 , m_bind2(bind2)
2427 #ifndef CTS_USES_VULKANSC
2428 , m_updateTemplates()
2429 #endif
2430 , m_vki(context.getDeviceInterface())
2431 , m_device(context.getDevice())
2432 , m_queue(context.getUniversalQueue())
2433 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
2434 , m_allocator(context.getDefaultAllocator())
2435 , m_result(m_vki, m_device, m_allocator)
2436 #ifndef CTS_USES_VULKANSC
2437 , m_updateRegistry()
2438 #endif
2439 , m_updateBuilder()
2440 , m_descriptorsPerSet()
2441 {
2442 if (m_dynamicOffsetNonZero)
2443 DE_ASSERT(m_setDynamicOffset);
2444 }
2445
createColorDataBuffer(uint32_t offset,uint32_t bufferSize,const tcu::Vec4 & value1,const tcu::Vec4 & value2,de::MovePtr<vk::Allocation> * outAllocation)2446 vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer(uint32_t offset, uint32_t bufferSize,
2447 const tcu::Vec4 &value1, const tcu::Vec4 &value2,
2448 de::MovePtr<vk::Allocation> *outAllocation)
2449 {
2450 DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
2451
2452 const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
2453 const vk::VkBufferUsageFlags usageFlags =
2454 (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2455 const vk::VkBufferCreateInfo createInfo = {
2456 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
2457 DE_NULL,
2458 0u, // flags
2459 (vk::VkDeviceSize)bufferSize, // size
2460 usageFlags, // usage
2461 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
2462 0u, // queueFamilyCount
2463 DE_NULL, // pQueueFamilyIndices
2464 };
2465 vk::Move<vk::VkBuffer> buffer(vk::createBuffer(m_vki, m_device, &createInfo));
2466 de::MovePtr<vk::Allocation> allocation(
2467 allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
2468 void *mapPtr = allocation->getHostPtr();
2469
2470 if (offset)
2471 deMemset(mapPtr, 0x5A, (size_t)offset);
2472 deMemcpy((uint8_t *)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
2473 deMemcpy((uint8_t *)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
2474 deMemset((uint8_t *)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A,
2475 (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
2476
2477 flushAlloc(m_vki, m_device, *allocation);
2478
2479 *outAllocation = allocation;
2480 return buffer;
2481 }
2482
createDescriptorSetLayout(uint32_t setNdx) const2483 vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
2484 {
2485 vk::DescriptorSetLayoutBuilder builder;
2486 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
2487 uint32_t binding = 0;
2488
2489 #ifndef CTS_USES_VULKANSC
2490 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
2491 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
2492 {
2493 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
2494 }
2495 #endif
2496
2497 if (setNdx == 0)
2498 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2499 binding++);
2500
2501 switch (m_shaderInterface)
2502 {
2503 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2504 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2505 break;
2506
2507 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2508 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2509 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2510 break;
2511
2512 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2513 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 0u);
2514 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2u);
2515 break;
2516
2517 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2518 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
2519 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
2520 break;
2521
2522 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2523 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2524 break;
2525
2526 default:
2527 DE_FATAL("Impossible");
2528 }
2529
2530 return builder.build(m_vki, m_device, extraFlags);
2531 }
2532
createDescriptorPool(void) const2533 vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool(void) const
2534 {
2535 return vk::DescriptorPoolBuilder()
2536 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2537 .addType(m_descriptorType,
2538 getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
2539 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
2540 getDescriptorSetCount(m_descriptorSetCount));
2541 }
2542
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)2543 vk::Move<vk::VkDescriptorSet> BufferComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
2544 vk::VkDescriptorSetLayout layout,
2545 uint32_t setNdx, vk::VkBuffer viewA,
2546 uint32_t offsetA, vk::VkBuffer viewB,
2547 uint32_t offsetB, vk::VkBuffer resBuf)
2548 {
2549 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
2550 pool, 1u, &layout};
2551
2552 vk::Move<vk::VkDescriptorSet> descriptorSet;
2553 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
2554 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
2555 {
2556 descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
2557 }
2558 else
2559 {
2560 descriptorSet = vk::Move<vk::VkDescriptorSet>();
2561 }
2562
2563 #ifndef CTS_USES_VULKANSC
2564 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
2565 {
2566 writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx, viewA, offsetA, viewB, offsetB, resBuf);
2567 }
2568 else
2569 #endif
2570 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
2571 {
2572 writeDescriptorSet(*descriptorSet, setNdx, viewA, offsetA, viewB, offsetB, resBuf);
2573 }
2574
2575 return descriptorSet;
2576 }
2577
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::VkBuffer viewA,uint32_t offsetA,vk::VkBuffer viewB,uint32_t offsetB,vk::VkBuffer resBuf)2578 void BufferComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkBuffer viewA,
2579 uint32_t offsetA, vk::VkBuffer viewB, uint32_t offsetB,
2580 vk::VkBuffer resBuf)
2581 {
2582 const vk::VkDescriptorBufferInfo resultInfo =
2583 vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
2584 const vk::VkDescriptorBufferInfo bufferInfos[2] = {
2585 vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2586 vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2587 };
2588
2589 uint32_t numDescriptors = 0u;
2590 uint32_t binding = 0u;
2591
2592 // result
2593 if (setNdx == 0)
2594 {
2595 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2596 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
2597 numDescriptors++;
2598 }
2599
2600 // buffers
2601 switch (m_shaderInterface)
2602 {
2603 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2604 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2605 m_descriptorType, &bufferInfos[0]);
2606 numDescriptors++;
2607 break;
2608
2609 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2610 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2611 m_descriptorType, &bufferInfos[0]);
2612 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2613 m_descriptorType, &bufferInfos[1]);
2614 numDescriptors += 2;
2615 break;
2616
2617 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2618 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
2619 m_descriptorType, &bufferInfos[0]);
2620 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
2621 m_descriptorType, &bufferInfos[1]);
2622 numDescriptors += 2;
2623 break;
2624
2625 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2626 m_updateBuilder.writeSingle(descriptorSet,
2627 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
2628 m_descriptorType, &bufferInfos[0]);
2629 m_updateBuilder.writeSingle(descriptorSet,
2630 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
2631 m_descriptorType, &bufferInfos[1]);
2632 numDescriptors += 2;
2633 break;
2634
2635 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2636 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2637 m_descriptorType, 2u, bufferInfos);
2638 numDescriptors++;
2639 break;
2640
2641 default:
2642 DE_FATAL("Impossible");
2643 }
2644
2645 m_descriptorsPerSet.push_back(numDescriptors);
2646
2647 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
2648 {
2649 m_updateBuilder.update(m_vki, m_device);
2650 m_updateBuilder.clear();
2651 }
2652 }
2653
2654 #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)2655 void BufferComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
2656 vk::VkDescriptorSetLayout layout, uint32_t setNdx,
2657 vk::VkBuffer viewA, uint32_t offsetA, vk::VkBuffer viewB,
2658 uint32_t offsetB, vk::VkBuffer resBuf, bool withPush,
2659 vk::VkPipelineLayout pipelineLayout)
2660 {
2661 const vk::VkDescriptorBufferInfo resultInfo =
2662 vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
2663 const vk::VkDescriptorBufferInfo bufferInfos[2] = {
2664 vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2665 vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2666 };
2667 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
2668 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
2669 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
2670 DE_NULL,
2671 0,
2672 0, // descriptorUpdateEntryCount
2673 DE_NULL, // pDescriptorUpdateEntries
2674 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
2675 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
2676 layout,
2677 vk::VK_PIPELINE_BIND_POINT_COMPUTE,
2678 pipelineLayout,
2679 setNdx};
2680 uint32_t binding = 0u;
2681 uint32_t offset = 0u;
2682 RawUpdateRegistry updateRegistry;
2683
2684 if (setNdx == 0)
2685 updateRegistry.addWriteObject(resultInfo);
2686
2687 updateRegistry.addWriteObject(bufferInfos[0]);
2688 updateRegistry.addWriteObject(bufferInfos[1]);
2689
2690 // result
2691 if (setNdx == 0)
2692 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2693 updateRegistry.getWriteObjectOffset(offset++), 0));
2694
2695 // buffers
2696 switch (m_shaderInterface)
2697 {
2698 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2699 updateEntries.push_back(
2700 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2701 break;
2702
2703 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2704 updateEntries.push_back(
2705 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2706 updateEntries.push_back(
2707 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2708 break;
2709
2710 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2711 updateEntries.push_back(
2712 createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2713 updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
2714 updateRegistry.getWriteObjectOffset(offset++), 0));
2715 break;
2716
2717 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2718 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
2719 updateRegistry.getWriteObjectOffset(offset++), 0));
2720 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
2721 updateRegistry.getWriteObjectOffset(offset++), 0));
2722 break;
2723
2724 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2725 updateEntries.push_back(createTemplateBinding(
2726 binding++, 0, 2, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), sizeof(bufferInfos[0])));
2727 break;
2728
2729 default:
2730 DE_FATAL("Impossible");
2731 }
2732
2733 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
2734 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
2735
2736 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
2737 vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
2738 m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
2739 m_updateRegistry.push_back(updateRegistry);
2740
2741 if (!withPush)
2742 {
2743 m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
2744 m_updateRegistry.back().getRawPointer());
2745 }
2746 }
2747 #endif
2748
iterate(void)2749 tcu::TestStatus BufferComputeInstance::iterate(void)
2750 {
2751 logTestPlan();
2752 return testResourceAccess();
2753 }
2754
logTestPlan(void) const2755 void BufferComputeInstance::logTestPlan(void) const
2756 {
2757 std::ostringstream msg;
2758
2759 msg << "Accessing resource in a compute program.\n"
2760 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
2761 "Multiple descriptor sets. ")
2762 << "Each descriptor set contains "
2763 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
2764 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
2765 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
2766 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
2767 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
2768 (const char *)DE_NULL)
2769 << " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType)
2770 << " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n"
2771 << "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
2772
2773 if (isDynamicDescriptorType(m_descriptorType))
2774 {
2775 if (m_setDynamicOffset)
2776 {
2777 msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
2778 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
2779 }
2780 else
2781 {
2782 msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
2783 }
2784 }
2785
2786 msg << "Destination buffer is pre-initialized to -1.\n";
2787
2788 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
2789 }
2790
testResourceAccess(void)2791 tcu::TestStatus BufferComputeInstance::testResourceAccess(void)
2792 {
2793 enum
2794 {
2795 ADDRESSABLE_SIZE = 256, // allocate a lot more than required
2796 };
2797
2798 const bool isDynamicCase = isDynamicDescriptorType(m_descriptorType);
2799 const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
2800
2801 const tcu::Vec4 color[] = {
2802 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), // green
2803 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), // yellow
2804 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), // blue
2805 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), // red
2806 };
2807
2808 std::vector<uint32_t> bindTimeOffsets;
2809 std::vector<tcu::Vec4> colors;
2810 std::vector<uint32_t> dataOffsets;
2811 std::vector<uint32_t> viewOffsets;
2812 std::vector<uint32_t> bufferSizes;
2813 std::vector<AllocationSp> bufferMems;
2814 std::vector<BufferHandleSp> buffers;
2815
2816 for (uint32_t bufferNdx = 0;
2817 bufferNdx < getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface);
2818 bufferNdx++)
2819 {
2820 const uint32_t staticOffsets[] = {STATIC_OFFSET_VALUE_A, STATIC_OFFSET_VALUE_B};
2821
2822 const uint32_t dynamicOffset[] = {DYNAMIC_OFFSET_VALUE_A, DYNAMIC_OFFSET_VALUE_B};
2823
2824 const uint32_t parity = bufferNdx % 2;
2825 bindTimeOffsets.push_back((m_dynamicOffsetNonZero) ? (dynamicOffset[parity]) : (0u));
2826
2827 const uint32_t dataOffset =
2828 ((isDynamicCase) ? (bindTimeOffsets.back()) : 0) + ((m_setViewOffset) ? (staticOffsets[parity]) : (0u));
2829 const uint32_t viewOffset = ((m_setViewOffset) ? (staticOffsets[parity]) : (0u));
2830
2831 colors.push_back(color[bufferNdx % DE_LENGTH_OF_ARRAY(color)]);
2832 dataOffsets.push_back(dataOffset);
2833 viewOffsets.push_back(viewOffset);
2834 bufferSizes.push_back(dataOffsets.back() + ADDRESSABLE_SIZE);
2835
2836 de::MovePtr<vk::Allocation> bufferMem;
2837 vk::Move<vk::VkBuffer> buffer(createColorDataBuffer(
2838 dataOffsets.back(), bufferSizes.back(), color[(bufferNdx * 2) % DE_LENGTH_OF_ARRAY(color)],
2839 color[(bufferNdx * 2 + 1) % DE_LENGTH_OF_ARRAY(color)], &bufferMem));
2840
2841 bufferMems.push_back(AllocationSp(bufferMem.release()));
2842 buffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
2843 }
2844
2845 const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
2846 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
2847 std::vector<DescriptorSetHandleSp> descriptorSets;
2848 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
2849 std::vector<vk::VkDescriptorSet> setHandles;
2850
2851 const uint32_t numSrcBuffers =
2852 getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface);
2853
2854 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2855 {
2856 const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2857 const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2858
2859 vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
2860 vk::Move<vk::VkDescriptorSet> set =
2861 createDescriptorSet(*descriptorPool, *layout, setNdx, **buffers[ndx0], viewOffsets[ndx0], **buffers[ndx1],
2862 viewOffsets[ndx1], m_result.getBuffer());
2863
2864 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
2865 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
2866
2867 layoutHandles.push_back(**descriptorSetLayouts.back());
2868 setHandles.push_back(**descriptorSets.back());
2869
2870 // Add an empty descriptor set layout between sets 0 and 2
2871 if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
2872 {
2873 vk::DescriptorSetLayoutBuilder emptyBuilder;
2874 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
2875 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
2876
2877 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
2878 layoutHandles.push_back(**descriptorSetLayouts.back());
2879 }
2880 }
2881
2882 const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
2883 &layoutHandles.front());
2884 const vk::VkAccessFlags inputBit =
2885 (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
2886
2887 std::vector<vk::VkBufferMemoryBarrier> bufferBarriers;
2888
2889 for (uint32_t bufferNdx = 0; bufferNdx < numSrcBuffers; bufferNdx++)
2890 {
2891 const vk::VkBufferMemoryBarrier barrier = {
2892 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2893 DE_NULL,
2894 vk::VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
2895 inputBit, // dstAccessMask
2896 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
2897 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
2898 **buffers[bufferNdx], // buffer
2899 (vk::VkDeviceSize)0u, // offset
2900 (vk::VkDeviceSize)bufferSizes[bufferNdx], // size
2901 };
2902
2903 bufferBarriers.push_back(barrier);
2904 }
2905
2906 const uint32_t *const dynamicOffsets = (m_setDynamicOffset) ? (&bindTimeOffsets.front()) : (DE_NULL);
2907 const uint32_t numDynamicOffsets = (m_setDynamicOffset) ? (numSrcBuffers) : (0);
2908 const vk::VkBufferMemoryBarrier *const preBarriers = &bufferBarriers.front();
2909 const int numPreBarriers = numSrcBuffers;
2910 const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
2911 const int numPostBarriers = 1;
2912
2913 const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
2914 tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
2915 numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
2916 postBarriers, m_bind2);
2917
2918 tcu::Vec4 refQuadrantValue14 = tcu::Vec4(0.0f);
2919 tcu::Vec4 refQuadrantValue23 = tcu::Vec4(0.0f);
2920
2921 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2922 {
2923 uint32_t offset = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? 1 : 3;
2924 refQuadrantValue14 +=
2925 color[(2 * setNdx * getInterfaceNumResources(m_shaderInterface) + offset) % DE_LENGTH_OF_ARRAY(color)];
2926 refQuadrantValue23 +=
2927 color[(2 * setNdx * getInterfaceNumResources(m_shaderInterface)) % DE_LENGTH_OF_ARRAY(color)];
2928 }
2929
2930 refQuadrantValue14 = refQuadrantValue14 / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
2931 refQuadrantValue23 = refQuadrantValue23 / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
2932
2933 const tcu::Vec4 references[4] = {
2934 refQuadrantValue14,
2935 refQuadrantValue23,
2936 refQuadrantValue23,
2937 refQuadrantValue14,
2938 };
2939 tcu::Vec4 results[4];
2940
2941 #ifndef CTS_USES_VULKANSC
2942 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
2943 {
2944 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2945 {
2946 const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2947 const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2948
2949 writeDescriptorSetWithTemplate(DE_NULL, layoutHandles[setNdx], setNdx, **buffers[ndx0], viewOffsets[ndx0],
2950 **buffers[ndx1], viewOffsets[ndx1], m_result.getBuffer(), true,
2951 pipeline.getPipelineLayout());
2952 }
2953 compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
2954 }
2955 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
2956 {
2957 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2958 {
2959 const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2960 const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2961
2962 writeDescriptorSet(DE_NULL, setNdx, **buffers[ndx0], viewOffsets[ndx0], **buffers[ndx1], viewOffsets[ndx1],
2963 m_result.getBuffer());
2964 }
2965
2966 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
2967 }
2968 else
2969 #endif
2970 {
2971 compute.submitAndWait(m_queueFamilyIndex, m_queue);
2972 }
2973 m_result.readResultContentsTo(&results);
2974
2975 // verify
2976 if (results[0] == references[0] && results[1] == references[1] && results[2] == references[2] &&
2977 results[3] == references[3])
2978 {
2979 return tcu::TestStatus::pass("Pass");
2980 }
2981 else if (results[0] == tcu::Vec4(-1.0f) && results[1] == tcu::Vec4(-1.0f) && results[2] == tcu::Vec4(-1.0f) &&
2982 results[3] == tcu::Vec4(-1.0f))
2983 {
2984 m_context.getTestContext().getLog()
2985 << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
2986 return tcu::TestStatus::fail("Result buffer was not written to");
2987 }
2988 else
2989 {
2990 m_context.getTestContext().getLog()
2991 << tcu::TestLog::Message << "Error expected [" << references[0] << ", " << references[1] << ", "
2992 << references[2] << ", " << references[3] << "], got [" << results[0] << ", " << results[1] << ", "
2993 << results[2] << ", " << results[3] << "]" << tcu::TestLog::EndMessage;
2994 return tcu::TestStatus::fail("Invalid result values");
2995 }
2996 }
2997
2998 class QuadrantRendederCase : public vkt::TestCase
2999 {
3000 public:
3001 QuadrantRendederCase(tcu::TestContext &testCtx, const char *name, glu::GLSLVersion glslVersion,
3002 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3003 DescriptorSetCount descriptorSetCount);
3004
3005 private:
3006 virtual std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const = 0;
3007 virtual std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const = 0;
3008 virtual std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const = 0;
3009 virtual std::string genNoAccessSource(void) const = 0;
3010
3011 std::string genVertexSource(void) const;
3012 std::string genTessCtrlSource(void) const;
3013 std::string genTessEvalSource(void) const;
3014 std::string genGeometrySource(void) const;
3015 std::string genFragmentSource(void) const;
3016 std::string genComputeSource(void) const;
3017
3018 void initPrograms(vk::SourceCollections &programCollection) const;
3019
3020 protected:
3021 const glu::GLSLVersion m_glslVersion;
3022 const vk::VkShaderStageFlags m_exitingStages;
3023 const vk::VkShaderStageFlags m_activeStages;
3024 const DescriptorSetCount m_descriptorSetCount;
3025 };
3026
QuadrantRendederCase(tcu::TestContext & testCtx,const char * name,glu::GLSLVersion glslVersion,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount)3027 QuadrantRendederCase::QuadrantRendederCase(tcu::TestContext &testCtx, const char *name, glu::GLSLVersion glslVersion,
3028 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3029 DescriptorSetCount descriptorSetCount)
3030 : vkt::TestCase(testCtx, name)
3031 , m_glslVersion(glslVersion)
3032 , m_exitingStages(exitingStages)
3033 , m_activeStages(activeStages)
3034 , m_descriptorSetCount(descriptorSetCount)
3035 {
3036 DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages);
3037 }
3038
genVertexSource(void) const3039 std::string QuadrantRendederCase::genVertexSource(void) const
3040 {
3041 const char *const nextStageName = ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) ?
3042 ("tsc") :
3043 ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u) ? ("geo") :
3044 ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u) ? ("frag") :
3045 (DE_NULL);
3046 const char *const fragColorPrec =
3047 ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? "highp" : "mediump";
3048 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3049 std::ostringstream buf;
3050
3051 if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
3052 {
3053 const bool onlyVS = (m_activeStages == vk::VK_SHADER_STAGE_VERTEX_BIT);
3054
3055 // active vertex shader
3056 buf << versionDecl << "\n" << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT);
3057 buf << genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT, 0);
3058 buf << "layout(location = 0) out " << fragColorPrec << " vec4 " << nextStageName << "_color;\n"
3059 << (onlyVS ? "" :
3060 "layout(location = 1) flat out highp int " + de::toString(nextStageName) + "_quadrant_id;\n")
3061 << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) << "void main (void)\n"
3062 << "{\n"
3063 << " highp vec4 result_position;\n"
3064 << " highp int quadrant_id;\n"
3065 << s_quadrantGenVertexPosSource << " gl_Position = result_position;\n"
3066 << (onlyVS ? "" : "\t" + de::toString(nextStageName) + "_quadrant_id = quadrant_id;\n") << "\n"
3067 << " highp vec4 result_color;\n"
3068 << genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX_BIT) << " " << nextStageName
3069 << "_color = result_color;\n"
3070 << "}\n";
3071 }
3072 else
3073 {
3074 // do nothing
3075 buf << versionDecl << "\n"
3076 << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT) << "layout(location = 1) flat out highp int "
3077 << nextStageName << "_quadrant_id;\n"
3078 << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) << "void main (void)\n"
3079 << "{\n"
3080 << " highp vec4 result_position;\n"
3081 << " highp int quadrant_id;\n"
3082 << s_quadrantGenVertexPosSource << " gl_Position = result_position;\n"
3083 << " " << nextStageName << "_quadrant_id = quadrant_id;\n"
3084 << "}\n";
3085 }
3086
3087 return buf.str();
3088 }
3089
genTessCtrlSource(void) const3090 std::string QuadrantRendederCase::genTessCtrlSource(void) const
3091 {
3092 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3093 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3094 const char *const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
3095 std::ostringstream buf;
3096
3097 if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3098 {
3099 // contributing not implemented
3100 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3101
3102 // active tc shader
3103 buf << versionDecl << "\n"
3104 << tessExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
3105 << "layout(vertices=3) out;\n"
3106 << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0)
3107 << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
3108 << "layout(location = 0) out highp vec4 tes_color[];\n"
3109 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) << "void main (void)\n"
3110 << "{\n"
3111 << " highp vec4 result_color;\n"
3112 << " highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n"
3113 << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) << "\n"
3114 << " tes_color[gl_InvocationID] = result_color;\n"
3115 << "\n"
3116 << " // no dynamic input block indexing\n"
3117 << " highp vec4 position;\n"
3118 << " if (gl_InvocationID == 0)\n"
3119 << " position = gl_in[0].gl_Position;\n"
3120 << " else if (gl_InvocationID == 1)\n"
3121 << " position = gl_in[1].gl_Position;\n"
3122 << " else\n"
3123 << " position = gl_in[2].gl_Position;\n"
3124 << " gl_out[gl_InvocationID].gl_Position = position;\n"
3125 << " gl_TessLevelInner[0] = 2.8;\n"
3126 << " gl_TessLevelInner[1] = 2.8;\n"
3127 << " gl_TessLevelOuter[0] = 2.8;\n"
3128 << " gl_TessLevelOuter[1] = 2.8;\n"
3129 << " gl_TessLevelOuter[2] = 2.8;\n"
3130 << " gl_TessLevelOuter[3] = 2.8;\n"
3131 << "}\n";
3132 }
3133 else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3134 {
3135 // active te shader, tc passthru
3136 buf << versionDecl << "\n"
3137 << tessExtDecl << "layout(vertices=3) out;\n"
3138 << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
3139 << "layout(location = 1) flat out highp int tes_quadrant_id[];\n"
3140 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) << "void main (void)\n"
3141 << "{\n"
3142 << " tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n"
3143 << "\n"
3144 << " // no dynamic input block indexing\n"
3145 << " highp vec4 position;\n"
3146 << " if (gl_InvocationID == 0)\n"
3147 << " position = gl_in[0].gl_Position;\n"
3148 << " else if (gl_InvocationID == 1)\n"
3149 << " position = gl_in[1].gl_Position;\n"
3150 << " else\n"
3151 << " position = gl_in[2].gl_Position;\n"
3152 << " gl_out[gl_InvocationID].gl_Position = position;\n"
3153 << " gl_TessLevelInner[0] = 2.8;\n"
3154 << " gl_TessLevelInner[1] = 2.8;\n"
3155 << " gl_TessLevelOuter[0] = 2.8;\n"
3156 << " gl_TessLevelOuter[1] = 2.8;\n"
3157 << " gl_TessLevelOuter[2] = 2.8;\n"
3158 << " gl_TessLevelOuter[3] = 2.8;\n"
3159 << "}\n";
3160 }
3161 else
3162 {
3163 // passthrough not implemented
3164 DE_FATAL("not implemented");
3165 }
3166
3167 return buf.str();
3168 }
3169
genTessEvalSource(void) const3170 std::string QuadrantRendederCase::genTessEvalSource(void) const
3171 {
3172 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3173 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3174 const char *const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
3175 std::ostringstream buf;
3176
3177 if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3178 {
3179 // contributing not implemented
3180 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
3181
3182 // active te shader
3183 buf << versionDecl << "\n"
3184 << tessExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
3185 << "layout(triangles) in;\n"
3186 << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0)
3187 << "layout(location = 1) flat in highp int tes_quadrant_id[];\n"
3188 << "layout(location = 0) out mediump vec4 frag_color;\n"
3189 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) << "void main (void)\n"
3190 << "{\n"
3191 << " highp vec4 result_color;\n"
3192 << " highp int quadrant_id = tes_quadrant_id[0];\n"
3193 << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) << "\n"
3194 << " frag_color = result_color;\n"
3195 << " gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + "
3196 "gl_TessCoord.z * gl_in[2].gl_Position;\n"
3197 << "}\n";
3198 }
3199 else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3200 {
3201 // contributing not implemented
3202 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3203
3204 // active tc shader, te is passthru
3205 buf << versionDecl << "\n"
3206 << tessExtDecl << "layout(triangles) in;\n"
3207 << "layout(location = 0) in highp vec4 tes_color[];\n"
3208 << "layout(location = 0) out mediump vec4 frag_color;\n"
3209 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) << "void main (void)\n"
3210 << "{\n"
3211 << " frag_color = tes_color[0];\n"
3212 << " gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + "
3213 "gl_TessCoord.z * gl_in[2].gl_Position;\n"
3214 << "}\n";
3215 }
3216 else
3217 {
3218 // passthrough not implemented
3219 DE_FATAL("not implemented");
3220 }
3221
3222 return buf.str();
3223 }
3224
genGeometrySource(void) const3225 std::string QuadrantRendederCase::genGeometrySource(void) const
3226 {
3227 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3228 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3229 const char *const geomExtDecl = extRequired ? "#extension GL_EXT_geometry_shader : require\n" : "";
3230 std::ostringstream buf;
3231
3232 if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
3233 {
3234 // contributing not implemented
3235 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT);
3236
3237 // active geometry shader
3238 buf << versionDecl << "\n"
3239 << geomExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "layout(triangles) in;\n"
3240 << "layout(triangle_strip, max_vertices=4) out;\n"
3241 << genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0)
3242 << "layout(location = 1) flat in highp int geo_quadrant_id[];\n"
3243 << "layout(location = 0) out mediump vec4 frag_color;\n"
3244 << genPerVertexBlock(vk::VK_SHADER_STAGE_GEOMETRY_BIT, m_glslVersion) << "void main (void)\n"
3245 << "{\n"
3246 << " highp int quadrant_id;\n"
3247 << " highp vec4 result_color;\n"
3248 << "\n"
3249 << " quadrant_id = geo_quadrant_id[0];\n"
3250 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << " frag_color = result_color;\n"
3251 << " gl_Position = gl_in[0].gl_Position;\n"
3252 << " EmitVertex();\n"
3253 << "\n"
3254 << " quadrant_id = geo_quadrant_id[1];\n"
3255 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << " frag_color = result_color;\n"
3256 << " gl_Position = gl_in[1].gl_Position;\n"
3257 << " EmitVertex();\n"
3258 << "\n"
3259 << " quadrant_id = geo_quadrant_id[2];\n"
3260 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << " frag_color = result_color;\n"
3261 << " gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n"
3262 << " EmitVertex();\n"
3263 << "\n"
3264 << " quadrant_id = geo_quadrant_id[0];\n"
3265 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << " frag_color = result_color;\n"
3266 << " gl_Position = gl_in[2].gl_Position;\n"
3267 << " EmitVertex();\n"
3268 << "}\n";
3269 }
3270 else
3271 {
3272 // passthrough not implemented
3273 DE_FATAL("not implemented");
3274 }
3275
3276 return buf.str();
3277 }
3278
genFragmentSource(void) const3279 std::string QuadrantRendederCase::genFragmentSource(void) const
3280 {
3281 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3282 std::ostringstream buf;
3283
3284 if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
3285 {
3286 buf << versionDecl << "\n"
3287 << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
3288 << genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0);
3289
3290 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
3291 {
3292 // there are other stages, this is just a contributor
3293 buf << "layout(location = 0) in mediump vec4 frag_color;\n";
3294 }
3295
3296 buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
3297 << "layout(location = 0) out mediump vec4 o_color;\n"
3298 << "void main (void)\n"
3299 << "{\n"
3300 << " highp int quadrant_id = frag_quadrant_id;\n"
3301 << " highp vec4 result_color;\n"
3302 << genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
3303
3304 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
3305 {
3306 // just contributor
3307 buf << " if (frag_quadrant_id < 2)\n"
3308 << " o_color = result_color;\n"
3309 << " else\n"
3310 << " o_color = frag_color;\n";
3311 }
3312 else
3313 buf << " o_color = result_color;\n";
3314
3315 buf << "}\n";
3316 }
3317 else if (m_activeStages == 0u)
3318 {
3319 // special case, no active stages
3320 buf << versionDecl << "\n"
3321 << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
3322 << "layout(location = 0) out mediump vec4 o_color;\n"
3323 << "void main (void)\n"
3324 << "{\n"
3325 << " highp int quadrant_id = frag_quadrant_id;\n"
3326 << " highp vec4 result_color;\n"
3327 << genNoAccessSource() << " o_color = result_color;\n"
3328 << "}\n";
3329 }
3330 else
3331 {
3332 // passthrough
3333 buf << versionDecl << "\n"
3334 << "layout(location = 0) in mediump vec4 frag_color;\n"
3335 "layout(location = 0) out mediump vec4 o_color;\n"
3336 "void main (void)\n"
3337 "{\n"
3338 " o_color = frag_color;\n"
3339 "}\n";
3340 }
3341
3342 return buf.str();
3343 }
3344
genComputeSource(void) const3345 std::string QuadrantRendederCase::genComputeSource(void) const
3346 {
3347 const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3348 std::ostringstream buf;
3349
3350 buf << versionDecl << "\n"
3351 << genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT)
3352 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3353 << genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT, 1)
3354 << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
3355 << "{\n"
3356 << " highp vec4 read_colors[4];\n"
3357 << "} b_out;\n"
3358 << "void main (void)\n"
3359 << "{\n"
3360 << " highp int quadrant_id = int(gl_WorkGroupID.x);\n"
3361 << " highp vec4 result_color;\n"
3362 << genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE_BIT)
3363 << " b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
3364 << "}\n";
3365
3366 return buf.str();
3367 }
3368
initPrograms(vk::SourceCollections & programCollection) const3369 void QuadrantRendederCase::initPrograms(vk::SourceCollections &programCollection) const
3370 {
3371 if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
3372 programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource());
3373
3374 if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3375 programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource());
3376
3377 if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3378 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource());
3379
3380 if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
3381 programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource());
3382
3383 if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
3384 programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource());
3385
3386 if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u)
3387 programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource());
3388 }
3389
3390 class BufferDescriptorCase : public QuadrantRendederCase
3391 {
3392 public:
3393 enum
3394 {
3395 FLAG_VIEW_OFFSET = (1u << 1u),
3396 FLAG_DYNAMIC_OFFSET_ZERO = (1u << 2u),
3397 FLAG_DYNAMIC_OFFSET_NONZERO = (1u << 3u),
3398 };
3399 // enum continues where resource flags ends
3400 DE_STATIC_ASSERT((uint32_t)FLAG_VIEW_OFFSET == (uint32_t)RESOURCE_FLAG_LAST);
3401
3402 BufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name,
3403 bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
3404 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3405 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, uint32_t flags,
3406 const bool bind2);
3407
3408 private:
3409 std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
3410 std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
3411 std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
3412 std::string genNoAccessSource(void) const;
3413
3414 vkt::TestInstance *createInstance(vkt::Context &context) const;
3415
3416 void checkSupport(Context &context) const;
3417
3418 const DescriptorUpdateMethod m_updateMethod;
3419 const bool m_viewOffset;
3420 const bool m_dynamicOffsetSet;
3421 const bool m_dynamicOffsetNonZero;
3422 const bool m_isPrimaryCmdBuf;
3423 const vk::VkDescriptorType m_descriptorType;
3424 const DescriptorSetCount m_descriptorSetCount;
3425 const ShaderInputInterface m_shaderInterface;
3426 const bool m_bind2;
3427 };
3428
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)3429 BufferDescriptorCase::BufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod,
3430 const char *name, bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
3431 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3432 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
3433 uint32_t flags, const bool bind2)
3434 : QuadrantRendederCase(testCtx, name, glu::GLSL_VERSION_310_ES, exitingStages, activeStages, descriptorSetCount)
3435 , m_updateMethod(updateMethod)
3436 , m_viewOffset((flags & FLAG_VIEW_OFFSET) != 0u)
3437 , m_dynamicOffsetSet((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u)
3438 , m_dynamicOffsetNonZero((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u)
3439 , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
3440 , m_descriptorType(descriptorType)
3441 , m_descriptorSetCount(descriptorSetCount)
3442 , m_shaderInterface(shaderInterface)
3443 , m_bind2(bind2)
3444 {
3445 }
3446
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const3447 std::string BufferDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
3448 {
3449 DE_UNREF(stage);
3450 return "";
3451 }
3452
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const3453 std::string BufferDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const
3454 {
3455 DE_UNREF(stage);
3456
3457 const bool isUniform = isUniformDescriptorType(m_descriptorType);
3458 const char *const storageType = (isUniform) ? ("uniform") : ("buffer");
3459 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
3460
3461 std::ostringstream buf;
3462
3463 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
3464 {
3465 // Result buffer is bound only to the first descriptor set in compute shader cases
3466 const int descBinding =
3467 numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
3468 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
3469 const uint32_t descriptorSet = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
3470
3471 switch (m_shaderInterface)
3472 {
3473 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3474 buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3475 << " BufferName" << setNdxPostfix << "\n"
3476 << "{\n"
3477 << " highp vec4 colorA;\n"
3478 << " highp vec4 colorB;\n"
3479 << "} b_instance" << setNdxPostfix << ";\n";
3480 break;
3481
3482 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3483 buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3484 << " BufferName" << setNdxPostfix << "A\n"
3485 << "{\n"
3486 << " highp vec4 colorA;\n"
3487 << " highp vec4 colorB;\n"
3488 << "} b_instance" << setNdxPostfix << "A;\n"
3489 << "layout(set = " << descriptorSet << ", binding = " << (descBinding + 1) << ", std140) "
3490 << storageType << " BufferName" << setNdxPostfix << "B\n"
3491 << "{\n"
3492 << " highp vec4 colorA;\n"
3493 << " highp vec4 colorB;\n"
3494 << "} b_instance" << setNdxPostfix << "B;\n";
3495 break;
3496
3497 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
3498 buf << "layout(set = " << descriptorSet << ", binding = " << de::toString(descBinding) << ", std140) "
3499 << storageType << " BufferName" << setNdxPostfix << "A\n"
3500 << "{\n"
3501 << " highp vec4 colorA;\n"
3502 << " highp vec4 colorB;\n"
3503 << "} b_instance" << setNdxPostfix << "A;\n"
3504 << "layout(set = " << descriptorSet << ", binding = " << de::toString(descBinding + 2) << ", std140) "
3505 << storageType << " BufferName" << setNdxPostfix << "B\n"
3506 << "{\n"
3507 << " highp vec4 colorA;\n"
3508 << " highp vec4 colorB;\n"
3509 << "} b_instance" << setNdxPostfix << "B;\n";
3510 break;
3511
3512 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
3513 buf << "layout(set = " << descriptorSet << ", binding = " << de::toString(getArbitraryBindingIndex(0))
3514 << ", std140) " << storageType << " BufferName" << setNdxPostfix << "A\n"
3515 << "{\n"
3516 << " highp vec4 colorA;\n"
3517 << " highp vec4 colorB;\n"
3518 << "} b_instance" << setNdxPostfix << "A;\n"
3519 << "layout(set = " << descriptorSet << ", binding = " << de::toString(getArbitraryBindingIndex(1))
3520 << ", std140) " << storageType << " BufferName" << setNdxPostfix << "B\n"
3521 << "{\n"
3522 << " highp vec4 colorA;\n"
3523 << " highp vec4 colorB;\n"
3524 << "} b_instance" << setNdxPostfix << "B;\n";
3525 break;
3526
3527 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3528 buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3529 << " BufferName" << setNdxPostfix << "\n"
3530 << "{\n"
3531 << " highp vec4 colorA;\n"
3532 << " highp vec4 colorB;\n"
3533 << "} b_instances" << setNdxPostfix << "[2];\n";
3534 break;
3535
3536 default:
3537 DE_FATAL("Impossible");
3538 }
3539 }
3540 return buf.str();
3541 }
3542
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const3543 std::string BufferDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
3544 {
3545 DE_UNREF(stage);
3546
3547 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
3548 std::ostringstream buf;
3549
3550 buf << " result_color = vec4(0.0);\n";
3551
3552 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
3553 {
3554 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
3555
3556 switch (m_shaderInterface)
3557 {
3558 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3559 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
3560 << " result_color += b_instance" << setNdxPostfix << ".colorA;\n"
3561 << " else\n"
3562 << " result_color += b_instance" << setNdxPostfix << ".colorB;\n";
3563 break;
3564
3565 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3566 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
3567 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
3568 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
3569 << " result_color += b_instance" << setNdxPostfix << "A.colorA;\n"
3570 << " else\n"
3571 << " result_color += b_instance" << setNdxPostfix << "B.colorB;\n";
3572 break;
3573
3574 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3575 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
3576 << " result_color += b_instances" << setNdxPostfix << "[0].colorA;\n"
3577 << " else\n"
3578 << " result_color += b_instances" << setNdxPostfix << "[1].colorB;\n";
3579 break;
3580
3581 default:
3582 DE_FATAL("Impossible");
3583 }
3584 }
3585
3586 if (getDescriptorSetCount(m_descriptorSetCount) > 1)
3587 buf << " result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
3588
3589 return buf.str();
3590 }
3591
genNoAccessSource(void) const3592 std::string BufferDescriptorCase::genNoAccessSource(void) const
3593 {
3594 return " if (quadrant_id == 1 || quadrant_id == 2)\n"
3595 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
3596 " else\n"
3597 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
3598 }
3599
createInstance(vkt::Context & context) const3600 vkt::TestInstance *BufferDescriptorCase::createInstance(vkt::Context &context) const
3601 {
3602 verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
3603 m_updateMethod, m_descriptorType, m_activeStages);
3604
3605 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
3606 {
3607 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
3608 return new BufferComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
3609 m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero,
3610 m_bind2);
3611 }
3612 else
3613 return new BufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
3614 m_descriptorSetCount, m_activeStages, m_exitingStages, m_shaderInterface,
3615 m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero, m_bind2);
3616 }
3617
checkSupport(Context & context) const3618 void BufferDescriptorCase::checkSupport(Context &context) const
3619 {
3620 if (m_bind2)
3621 context.requireDeviceFunctionality("VK_KHR_maintenance6");
3622 }
3623
3624 class ImageInstanceImages
3625 {
3626 public:
3627 ImageInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3628 vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3629 vk::VkImageViewType viewType, int numImages, uint32_t numLevels, uint32_t baseMipLevel,
3630 uint32_t baseArraySlice);
3631
3632 private:
3633 static std::vector<tcu::TextureLevelPyramid> createSourceImages(int numImages, int numLevels,
3634 vk::VkImageViewType viewType,
3635 tcu::TextureFormat imageFormat);
3636
3637 static std::vector<ImageHandleSp> createImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3638 vk::Allocator &allocator, uint32_t queueFamilyIndex,
3639 vk::VkQueue queue, vk::VkDescriptorType descriptorType,
3640 vk::VkImageViewType viewType, std::vector<AllocationSp> &imageMemory,
3641 const std::vector<tcu::TextureLevelPyramid> &sourceImages);
3642
3643 static std::vector<ImageViewHandleSp> createImageViews(const vk::DeviceInterface &vki, vk::VkDevice device,
3644 vk::VkImageViewType viewType,
3645 const std::vector<tcu::TextureLevelPyramid> &sourceImages,
3646 const std::vector<ImageHandleSp> &images,
3647 uint32_t baseMipLevel, uint32_t baseArraySlice);
3648
3649 static vk::Move<vk::VkImage> createImage(const vk::DeviceInterface &vki, vk::VkDevice device,
3650 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3651 vk::VkImageViewType viewType, const tcu::TextureLevelPyramid &sourceImage,
3652 de::MovePtr<vk::Allocation> *outAllocation);
3653
3654 static vk::Move<vk::VkImageView> createImageView(const vk::DeviceInterface &vki, vk::VkDevice device,
3655 vk::VkImageViewType viewType,
3656 const tcu::TextureLevelPyramid &sourceImage, vk::VkImage image,
3657 uint32_t baseMipLevel, uint32_t baseArraySlice);
3658
3659 static void populateSourceImage(tcu::TextureLevelPyramid *dst, vk::VkImageViewType viewType, int imageNdx);
3660
3661 static void uploadImage(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3662 vk::VkQueue queue, vk::Allocator &allocator, vk::VkImage image, vk::VkImageLayout layout,
3663 vk::VkImageViewType viewType, const tcu::TextureLevelPyramid &data);
3664
3665 protected:
3666 enum
3667 {
3668 IMAGE_SIZE = 64,
3669 ARRAY_SIZE = 2,
3670 };
3671
3672 const vk::VkImageViewType m_viewType;
3673 const uint32_t m_baseMipLevel;
3674 const uint32_t m_baseArraySlice;
3675 const tcu::TextureFormat m_imageFormat;
3676 const std::vector<tcu::TextureLevelPyramid> m_sourceImage;
3677 std::vector<AllocationSp> m_imageMemory;
3678 const std::vector<ImageHandleSp> m_image;
3679 const std::vector<ImageViewHandleSp> m_imageView;
3680 };
3681
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)3682 ImageInstanceImages::ImageInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3683 vk::VkQueue queue, vk::Allocator &allocator,
3684 vk::VkDescriptorType descriptorType, vk::VkImageViewType viewType,
3685 int numImages, uint32_t numLevels, uint32_t baseMipLevel,
3686 uint32_t baseArraySlice)
3687 : m_viewType(viewType)
3688 , m_baseMipLevel(baseMipLevel)
3689 , m_baseArraySlice(baseArraySlice)
3690 , m_imageFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
3691 , m_sourceImage(createSourceImages(numImages, numLevels, viewType, m_imageFormat))
3692 , m_imageMemory()
3693 , m_image(createImages(vki, device, allocator, queueFamilyIndex, queue, descriptorType, viewType, m_imageMemory,
3694 m_sourceImage))
3695 , m_imageView(createImageViews(vki, device, viewType, m_sourceImage, m_image, m_baseMipLevel, m_baseArraySlice))
3696 {
3697 }
3698
createSourceImages(int numImages,int numLevels,vk::VkImageViewType viewType,tcu::TextureFormat imageFormat)3699 std::vector<tcu::TextureLevelPyramid> ImageInstanceImages::createSourceImages(int numImages, int numLevels,
3700 vk::VkImageViewType viewType,
3701 tcu::TextureFormat imageFormat)
3702 {
3703 std::vector<tcu::TextureLevelPyramid> sourceImages(numImages, tcu::TextureLevelPyramid(imageFormat, numLevels));
3704
3705 for (int imageNdx = 0; imageNdx < numImages; imageNdx++)
3706 populateSourceImage(&sourceImages.at(imageNdx), viewType, imageNdx);
3707
3708 return sourceImages;
3709 }
3710
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)3711 std::vector<ImageHandleSp> ImageInstanceImages::createImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3712 vk::Allocator &allocator, uint32_t queueFamilyIndex,
3713 vk::VkQueue queue, vk::VkDescriptorType descriptorType,
3714 vk::VkImageViewType viewType,
3715 std::vector<AllocationSp> &imageMemory,
3716 const std::vector<tcu::TextureLevelPyramid> &sourceImages)
3717 {
3718 std::vector<ImageHandleSp> images;
3719 const vk::VkImageLayout layout = getImageLayoutForDescriptorType(descriptorType);
3720
3721 for (int imageNdx = 0; imageNdx < (int)sourceImages.size(); imageNdx++)
3722 {
3723 de::MovePtr<vk::Allocation> memory;
3724 vk::Move<vk::VkImage> image =
3725 createImage(vki, device, allocator, descriptorType, viewType, sourceImages[imageNdx], &memory);
3726
3727 uploadImage(vki, device, queueFamilyIndex, queue, allocator, *image, layout, viewType, sourceImages[imageNdx]);
3728
3729 imageMemory.push_back(AllocationSp(memory.release()));
3730 images.push_back(ImageHandleSp(new ImageHandleUp(image)));
3731 }
3732 return images;
3733 }
3734
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)3735 std::vector<ImageViewHandleSp> ImageInstanceImages::createImageViews(
3736 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkImageViewType viewType,
3737 const std::vector<tcu::TextureLevelPyramid> &sourceImages, const std::vector<ImageHandleSp> &images,
3738 uint32_t baseMipLevel, uint32_t baseArraySlice)
3739 {
3740 std::vector<ImageViewHandleSp> imageViews;
3741 for (int imageNdx = 0; imageNdx < (int)sourceImages.size(); imageNdx++)
3742 {
3743 vk::Move<vk::VkImageView> imageView = createImageView(vki, device, viewType, sourceImages[imageNdx],
3744 **images[imageNdx], baseMipLevel, baseArraySlice);
3745 imageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imageView)));
3746 }
3747 return imageViews;
3748 }
3749
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)3750 vk::Move<vk::VkImage> ImageInstanceImages::createImage(const vk::DeviceInterface &vki, vk::VkDevice device,
3751 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3752 vk::VkImageViewType viewType,
3753 const tcu::TextureLevelPyramid &sourceImage,
3754 de::MovePtr<vk::Allocation> *outAllocation)
3755 {
3756 const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
3757 const bool isCube = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
3758 const bool isStorage = (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
3759 const uint32_t readUsage = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
3760 const uint32_t arraySize =
3761 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3762 (baseLevel.getHeight()) :
3763 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ?
3764 (baseLevel.getDepth()) :
3765 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3766 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3767 (baseLevel.getDepth()) // cube: numFaces * numLayers
3768 :
3769 (0);
3770 const vk::VkExtent3D extent = {
3771 // x
3772 (uint32_t)baseLevel.getWidth(),
3773
3774 // y
3775 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3776 (1u) :
3777 (uint32_t)baseLevel.getHeight(),
3778
3779 // z
3780 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((uint32_t)baseLevel.getDepth()) : (1u),
3781 };
3782 const vk::VkImageCreateInfo createInfo = {
3783 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3784 DE_NULL,
3785 isCube ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (vk::VkImageCreateFlags)0,
3786 viewTypeToImageType(viewType), // imageType
3787 vk::mapTextureFormat(baseLevel.getFormat()), // format
3788 extent, // extent
3789 (uint32_t)sourceImage.getNumLevels(), // mipLevels
3790 arraySize, // arraySize
3791 vk::VK_SAMPLE_COUNT_1_BIT, // samples
3792 vk::VK_IMAGE_TILING_OPTIMAL, // tiling
3793 readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT, // usage
3794 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
3795 0u, // queueFamilyCount
3796 DE_NULL, // pQueueFamilyIndices
3797 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
3798 };
3799 vk::Move<vk::VkImage> image(vk::createImage(vki, device, &createInfo));
3800
3801 *outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any);
3802 return image;
3803 }
3804
createImageView(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & sourceImage,vk::VkImage image,uint32_t baseMipLevel,uint32_t baseArraySlice)3805 vk::Move<vk::VkImageView> ImageInstanceImages::createImageView(const vk::DeviceInterface &vki, vk::VkDevice device,
3806 vk::VkImageViewType viewType,
3807 const tcu::TextureLevelPyramid &sourceImage,
3808 vk::VkImage image, uint32_t baseMipLevel,
3809 uint32_t baseArraySlice)
3810 {
3811 const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
3812 const uint32_t viewTypeBaseSlice =
3813 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3814 (6 * baseArraySlice) :
3815 (baseArraySlice);
3816 const uint32_t viewArraySize =
3817 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D) ? (1) :
3818 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (baseLevel.getHeight() - viewTypeBaseSlice) :
3819 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D) ? (1) :
3820 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (baseLevel.getDepth() - viewTypeBaseSlice) :
3821 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3822 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE) ? (6) :
3823 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth() -
3824 viewTypeBaseSlice) // cube: numFaces * numLayers
3825 :
3826 (0);
3827
3828 DE_ASSERT(viewArraySize > 0);
3829
3830 const vk::VkImageSubresourceRange resourceRange = {
3831 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
3832 baseMipLevel, // baseMipLevel
3833 sourceImage.getNumLevels() - baseMipLevel, // mipLevels
3834 viewTypeBaseSlice, // baseArraySlice
3835 viewArraySize, // arraySize
3836 };
3837 const vk::VkImageViewCreateInfo createInfo = {
3838 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
3839 DE_NULL,
3840 (vk::VkImageViewCreateFlags)0,
3841 image, // image
3842 viewType, // viewType
3843 vk::mapTextureFormat(baseLevel.getFormat()), // format
3844 {vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B,
3845 vk::VK_COMPONENT_SWIZZLE_A}, // channels
3846 resourceRange, // subresourceRange
3847 };
3848 return vk::createImageView(vki, device, &createInfo);
3849 }
3850
populateSourceImage(tcu::TextureLevelPyramid * dst,vk::VkImageViewType viewType,int imageNdx)3851 void ImageInstanceImages::populateSourceImage(tcu::TextureLevelPyramid *dst, vk::VkImageViewType viewType, int imageNdx)
3852 {
3853 const int numLevels = dst->getNumLevels();
3854
3855 for (int level = 0; level < numLevels; ++level)
3856 {
3857 const int width = IMAGE_SIZE >> level;
3858 const int height = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3859 (ARRAY_SIZE) :
3860 (IMAGE_SIZE >> level);
3861 const int depth =
3862 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) :
3863 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (ARRAY_SIZE) :
3864 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3865 (6 * ARRAY_SIZE) :
3866 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (IMAGE_SIZE >> level) :
3867 (1);
3868
3869 dst->allocLevel(level, width, height, depth);
3870
3871 {
3872 const tcu::PixelBufferAccess levelAccess = dst->getLevel(level);
3873
3874 for (int z = 0; z < depth; ++z)
3875 for (int y = 0; y < height; ++y)
3876 for (int x = 0; x < width; ++x)
3877 {
3878 const int gradPos = x + y + z;
3879 const int gradMax = width + height + depth - 3;
3880
3881 int red = 255 * gradPos / gradMax; //!< gradient from 0 -> max (detects large offset errors)
3882 int green =
3883 ((gradPos % 2 == 0) ? (127) : (0)) +
3884 ((gradPos % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
3885 int blue =
3886 (128 * level / numLevels) +
3887 ((imageNdx % 2 == 0) ? 127 : 0); //!< level and image index (detects incorrect lod / image)
3888
3889 DE_ASSERT(de::inRange(red, 0, 255));
3890 DE_ASSERT(de::inRange(green, 0, 255));
3891 DE_ASSERT(de::inRange(blue, 0, 255));
3892
3893 if (imageNdx % 3 == 0)
3894 red = 255 - red;
3895 if (imageNdx % 4 == 0)
3896 green = 255 - green;
3897 if (imageNdx % 5 == 0)
3898 blue = 255 - blue;
3899
3900 levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z);
3901 }
3902 }
3903 }
3904 }
3905
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)3906 void ImageInstanceImages::uploadImage(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3907 vk::VkQueue queue, vk::Allocator &allocator, vk::VkImage image,
3908 vk::VkImageLayout layout, vk::VkImageViewType viewType,
3909 const tcu::TextureLevelPyramid &data)
3910 {
3911 const uint32_t arraySize =
3912 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3913 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3914 (6 * (uint32_t)ARRAY_SIZE) :
3915 ((uint32_t)ARRAY_SIZE);
3916 const uint32_t dataBufferSize = getTextureLevelPyramidDataSize(data);
3917 const vk::VkBufferCreateInfo bufferCreateInfo = {
3918 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
3919 DE_NULL,
3920 0u, // flags
3921 dataBufferSize, // size
3922 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
3923 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
3924 0u, // queueFamilyCount
3925 DE_NULL, // pQueueFamilyIndices
3926 };
3927
3928 const vk::Unique<vk::VkBuffer> dataBuffer(vk::createBuffer(vki, device, &bufferCreateInfo));
3929 const de::MovePtr<vk::Allocation> dataBufferMemory =
3930 allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible);
3931 std::vector<vk::VkBufferImageCopy> copySlices;
3932 // copy data to buffer
3933 writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, viewType, ©Slices);
3934 flushAlloc(vki, device, *dataBufferMemory);
3935
3936 // copy buffer to image
3937 copyBufferToImage(vki, device, queue, queueFamilyIndex, *dataBuffer, dataBufferSize, copySlices, DE_NULL,
3938 vk::VK_IMAGE_ASPECT_COLOR_BIT, data.getNumLevels(), arraySize, image, layout);
3939 }
3940
3941 class ImageFetchInstanceImages : private ImageInstanceImages
3942 {
3943 public:
3944 ImageFetchInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3945 vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3946 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
3947 vk::VkImageViewType viewType, uint32_t numLevels, uint32_t baseMipLevel,
3948 uint32_t baseArraySlice);
3949
3950 static tcu::IVec3 getFetchPos(vk::VkImageViewType viewType, uint32_t baseMipLevel, uint32_t baseArraySlice,
3951 int fetchPosNdx);
3952
3953 tcu::Vec4 fetchImageValue(int fetchPosNdx, int setNdx) const;
3954
getSourceImage(int ndx) const3955 inline tcu::TextureLevelPyramid getSourceImage(int ndx) const
3956 {
3957 return m_sourceImage[ndx];
3958 }
getImageView(int ndx) const3959 inline vk::VkImageView getImageView(int ndx) const
3960 {
3961 return **m_imageView[ndx % m_imageView.size()];
3962 }
3963
3964 private:
3965 enum
3966 {
3967 // some arbitrary sample points for all four quadrants
3968 SAMPLE_POINT_0_X = 6,
3969 SAMPLE_POINT_0_Y = 13,
3970 SAMPLE_POINT_0_Z = 49,
3971
3972 SAMPLE_POINT_1_X = 51,
3973 SAMPLE_POINT_1_Y = 40,
3974 SAMPLE_POINT_1_Z = 44,
3975
3976 SAMPLE_POINT_2_X = 42,
3977 SAMPLE_POINT_2_Y = 26,
3978 SAMPLE_POINT_2_Z = 19,
3979
3980 SAMPLE_POINT_3_X = 25,
3981 SAMPLE_POINT_3_Y = 25,
3982 SAMPLE_POINT_3_Z = 18,
3983 };
3984
3985 const ShaderInputInterface m_shaderInterface;
3986 };
3987
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)3988 ImageFetchInstanceImages::ImageFetchInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3989 uint32_t queueFamilyIndex, vk::VkQueue queue,
3990 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3991 DescriptorSetCount descriptorSetCount,
3992 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
3993 uint32_t numLevels, uint32_t baseMipLevel, uint32_t baseArraySlice)
3994 : ImageInstanceImages(vki, device, queueFamilyIndex, queue, allocator, descriptorType, viewType,
3995 getDescriptorSetCount(descriptorSetCount) *
3996 getInterfaceNumResources(shaderInterface), // numImages
3997 numLevels, baseMipLevel, baseArraySlice)
3998 , m_shaderInterface(shaderInterface)
3999 {
4000 }
4001
isImageViewTypeArray(vk::VkImageViewType type)4002 bool isImageViewTypeArray(vk::VkImageViewType type)
4003 {
4004 return type == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
4005 type == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
4006 }
4007
getFetchPos(vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,int fetchPosNdx)4008 tcu::IVec3 ImageFetchInstanceImages::getFetchPos(vk::VkImageViewType viewType, uint32_t baseMipLevel,
4009 uint32_t baseArraySlice, int fetchPosNdx)
4010 {
4011 const tcu::IVec3 fetchPositions[4] = {
4012 tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z),
4013 tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z),
4014 tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z),
4015 tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z),
4016 };
4017 const tcu::IVec3 coord = de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
4018 const uint32_t imageSize = (uint32_t)IMAGE_SIZE >> baseMipLevel;
4019 const uint32_t arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
4020
4021 switch (viewType)
4022 {
4023 case vk::VK_IMAGE_VIEW_TYPE_1D:
4024 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
4025 return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0);
4026 case vk::VK_IMAGE_VIEW_TYPE_2D:
4027 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
4028 return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize);
4029 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
4030 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
4031 return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6));
4032 case vk::VK_IMAGE_VIEW_TYPE_3D:
4033 return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize);
4034 default:
4035 DE_FATAL("Impossible");
4036 return tcu::IVec3();
4037 }
4038 }
4039
fetchImageValue(int fetchPosNdx,int setNdx) const4040 tcu::Vec4 ImageFetchInstanceImages::fetchImageValue(int fetchPosNdx, int setNdx) const
4041 {
4042 DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4));
4043
4044 const tcu::TextureLevelPyramid &fetchSrcA = getSourceImage(setNdx * getInterfaceNumResources(m_shaderInterface));
4045 const tcu::TextureLevelPyramid &fetchSrcB =
4046 (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ?
4047 fetchSrcA :
4048 getSourceImage(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
4049 const tcu::TextureLevelPyramid &fetchSrc =
4050 ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB
4051 tcu::IVec3 fetchPos = getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
4052
4053 // add base array layer into the appropriate coordinate, based on the view type
4054 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
4055 fetchPos.z() += 6 * m_baseArraySlice;
4056 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
4057 fetchPos.y() += m_baseArraySlice;
4058 else
4059 fetchPos.z() += m_baseArraySlice;
4060
4061 return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z());
4062 }
4063
4064 class ImageFetchRenderInstance : public SingleCmdRenderInstance
4065 {
4066 public:
4067 ImageFetchRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
4068 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4069 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
4070 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
4071 uint32_t baseArraySlice, const bool bind2);
4072
4073 private:
4074 static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
4075 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4076 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
4077 DescriptorUpdateMethod updateMethod);
4078
4079 static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
4080 const vk::DeviceInterface &vki, vk::VkDevice device,
4081 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
4082
4083 static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
4084 vk::VkDescriptorType descriptorType,
4085 DescriptorSetCount descriptorSetCount,
4086 ShaderInputInterface shaderInterface);
4087
4088 static std::vector<DescriptorSetHandleSp> createDescriptorSets(
4089 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
4090 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4091 ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
4092 vk::VkDescriptorPool pool, const ImageFetchInstanceImages &images,
4093 vk::DescriptorSetUpdateBuilder &updateBuilder,
4094 #ifndef CTS_USES_VULKANSC
4095 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
4096 #endif
4097 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = DE_NULL);
4098
4099 static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
4100 vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
4101 vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool, vk::VkImageView viewA,
4102 vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4103 vk::DescriptorSetUpdateBuilder &updateBuilder,
4104 std::vector<uint32_t> &descriptorsPerSet,
4105 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
4106
4107 #ifndef CTS_USES_VULKANSC
4108 static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
4109 vk::VkDescriptorType descriptorType,
4110 ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout,
4111 vk::VkDescriptorPool pool, vk::VkImageView viewA, vk::VkImageView viewB,
4112 vk::VkDescriptorSet descriptorSet,
4113 std::vector<UpdateTemplateHandleSp> &updateTemplates,
4114 std::vector<RawUpdateRegistry> ®istry, bool withPush = false,
4115 vk::VkPipelineLayout pipelineLayout = 0);
4116 #endif
4117
4118 void logTestPlan(void) const;
4119 vk::VkPipelineLayout getPipelineLayout(void) const;
4120 void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
4121 tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
4122
4123 enum
4124 {
4125 RENDER_SIZE = 128,
4126 };
4127
4128 const DescriptorUpdateMethod m_updateMethod;
4129 const vk::VkDescriptorType m_descriptorType;
4130 const DescriptorSetCount m_descriptorSetCount;
4131 const vk::VkShaderStageFlags m_stageFlags;
4132 const vk::VkShaderStageFlags m_existingStages;
4133 const ShaderInputInterface m_shaderInterface;
4134 const vk::VkImageViewType m_viewType;
4135 const uint32_t m_numLevels;
4136 const uint32_t m_baseMipLevel;
4137 const uint32_t m_baseArraySlice;
4138
4139 #ifndef CTS_USES_VULKANSC
4140 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
4141 std::vector<RawUpdateRegistry> m_updateRegistry;
4142 #endif
4143 vk::DescriptorSetUpdateBuilder m_updateBuilder;
4144 const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
4145 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
4146 const ImageFetchInstanceImages m_images;
4147 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
4148 std::vector<uint32_t> m_descriptorsPerSet;
4149 const std::vector<DescriptorSetHandleSp> m_descriptorSets;
4150 };
4151
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)4152 ImageFetchRenderInstance::ImageFetchRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
4153 bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
4154 DescriptorSetCount descriptorSetCount,
4155 vk::VkShaderStageFlags stageFlags,
4156 vk::VkShaderStageFlags existingStages,
4157 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
4158 uint32_t baseMipLevel, uint32_t baseArraySlice, const bool bind2)
4159 : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
4160 , m_updateMethod(updateMethod)
4161 , m_descriptorType(descriptorType)
4162 , m_descriptorSetCount(descriptorSetCount)
4163 , m_stageFlags(stageFlags)
4164 , m_existingStages(existingStages)
4165 , m_shaderInterface(shaderInterface)
4166 , m_viewType(viewType)
4167 , m_numLevels(baseMipLevel + 1u)
4168 , m_baseMipLevel(baseMipLevel)
4169 , m_baseArraySlice(baseArraySlice)
4170 #ifndef CTS_USES_VULKANSC
4171 , m_updateTemplates()
4172 , m_updateRegistry()
4173 #endif
4174 , m_updateBuilder()
4175 , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
4176 m_shaderInterface, m_stageFlags, m_updateMethod))
4177 , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
4178 , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
4179 m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice)
4180 , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
4181 , m_descriptorsPerSet()
4182 , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
4183 m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool, m_images,
4184 m_updateBuilder,
4185 #ifndef CTS_USES_VULKANSC
4186 m_updateTemplates, m_updateRegistry,
4187 #endif
4188 m_descriptorsPerSet, *m_pipelineLayout))
4189 {
4190 }
4191
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)4192 std::vector<DescriptorSetLayoutHandleSp> ImageFetchRenderInstance::createDescriptorSetLayouts(
4193 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4194 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
4195 DescriptorUpdateMethod updateMethod)
4196 {
4197 #ifdef CTS_USES_VULKANSC
4198 DE_UNREF(updateMethod);
4199 #endif
4200 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
4201 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
4202
4203 #ifndef CTS_USES_VULKANSC
4204 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
4205 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4206 {
4207 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
4208 }
4209 #endif
4210
4211 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
4212 {
4213 vk::DescriptorSetLayoutBuilder builder;
4214
4215 switch (shaderInterface)
4216 {
4217 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4218 builder.addSingleBinding(descriptorType, stageFlags);
4219 break;
4220
4221 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4222 builder.addSingleBinding(descriptorType, stageFlags);
4223 builder.addSingleBinding(descriptorType, stageFlags);
4224 break;
4225
4226 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4227 builder.addSingleIndexedBinding(descriptorType, stageFlags, 0u);
4228 builder.addSingleIndexedBinding(descriptorType, stageFlags, 2u);
4229 break;
4230
4231 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4232 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
4233 builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
4234 break;
4235
4236 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4237 builder.addArrayBinding(descriptorType, 2u, stageFlags);
4238 break;
4239
4240 default:
4241 DE_FATAL("Impossible");
4242 }
4243
4244 vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
4245 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
4246
4247 // Add an empty descriptor set layout between sets 0 and 2
4248 if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
4249 {
4250 vk::DescriptorSetLayoutBuilder emptyBuilder;
4251 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
4252 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
4253 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
4254 }
4255 }
4256 return descriptorSetLayouts;
4257 }
4258
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)4259 vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout(
4260 const vk::DeviceInterface &vki, vk::VkDevice device,
4261 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
4262 {
4263 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
4264 for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
4265 layoutHandles.push_back(**descriptorSetLayout[setNdx]);
4266
4267 const vk::VkPipelineLayoutCreateInfo createInfo = {
4268 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4269 DE_NULL,
4270 (vk::VkPipelineLayoutCreateFlags)0,
4271 (uint32_t)layoutHandles.size(), // descriptorSetCount
4272 &layoutHandles.front(), // pSetLayouts
4273 0u, // pushConstantRangeCount
4274 DE_NULL, // pPushConstantRanges
4275 };
4276 return vk::createPipelineLayout(vki, device, &createInfo);
4277 }
4278
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)4279 vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
4280 vk::VkDevice device,
4281 vk::VkDescriptorType descriptorType,
4282 DescriptorSetCount descriptorSetCount,
4283 ShaderInputInterface shaderInterface)
4284 {
4285 return vk::DescriptorPoolBuilder()
4286 .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
4287 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
4288 getDescriptorSetCount(descriptorSetCount));
4289 }
4290
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)4291 std::vector<DescriptorSetHandleSp> ImageFetchRenderInstance::createDescriptorSets(
4292 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
4293 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
4294 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool,
4295 const ImageFetchInstanceImages &images, vk::DescriptorSetUpdateBuilder &updateBuilder,
4296 #ifndef CTS_USES_VULKANSC
4297 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
4298 #endif
4299 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
4300 {
4301 #ifdef CTS_USES_VULKANSC
4302 DE_UNREF(pipelineLayout);
4303 #endif
4304 std::vector<DescriptorSetHandleSp> descriptorSets;
4305
4306 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
4307 {
4308 vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
4309
4310 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
4311 pool, 1u, &layout};
4312
4313 vk::VkImageView viewA = images.getImageView(setNdx * getInterfaceNumResources(shaderInterface));
4314 vk::VkImageView viewB = images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1);
4315
4316 vk::Move<vk::VkDescriptorSet> descriptorSet;
4317 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
4318 updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4319 {
4320 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
4321 }
4322 else
4323 {
4324 descriptorSet = vk::Move<vk::VkDescriptorSet>();
4325 }
4326
4327 #ifndef CTS_USES_VULKANSC
4328 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
4329 {
4330 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB,
4331 *descriptorSet, updateTemplates, updateRegistry);
4332 }
4333 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4334 {
4335 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB,
4336 *descriptorSet, updateTemplates, updateRegistry, true, pipelineLayout);
4337 }
4338 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4339 {
4340 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
4341 updateBuilder, descriptorsPerSet, updateMethod);
4342 }
4343 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4344 #endif
4345 {
4346 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
4347 updateBuilder, descriptorsPerSet);
4348 }
4349
4350 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
4351 }
4352 return descriptorSets;
4353 }
4354
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)4355 void ImageFetchRenderInstance::writeDescriptorSet(
4356 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4357 ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
4358 vk::VkImageView viewA, vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4359 vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
4360 DescriptorUpdateMethod updateMethod)
4361 {
4362 DE_UNREF(layout);
4363 DE_UNREF(pool);
4364 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(descriptorType);
4365 const vk::VkDescriptorImageInfo imageInfos[2] = {
4366 makeDescriptorImageInfo(viewA, imageLayout),
4367 makeDescriptorImageInfo(viewB, imageLayout),
4368 };
4369 uint32_t numDescriptors = 0u;
4370
4371 switch (shaderInterface)
4372 {
4373 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4374 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4375 &imageInfos[0]);
4376 numDescriptors++;
4377 break;
4378
4379 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4380 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4381 &imageInfos[0]);
4382 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
4383 &imageInfos[1]);
4384 numDescriptors += 2;
4385 break;
4386
4387 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4388 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4389 &imageInfos[0]);
4390 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
4391 &imageInfos[1]);
4392 numDescriptors += 2;
4393 break;
4394
4395 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4396 updateBuilder.writeSingle(descriptorSet,
4397 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
4398 descriptorType, &imageInfos[0]);
4399 updateBuilder.writeSingle(descriptorSet,
4400 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
4401 descriptorType, &imageInfos[1]);
4402 numDescriptors += 2;
4403 break;
4404
4405 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4406 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4407 2u, imageInfos);
4408 numDescriptors++;
4409 break;
4410
4411 default:
4412 DE_FATAL("Impossible");
4413 }
4414
4415 descriptorsPerSet.push_back(numDescriptors);
4416
4417 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4418 {
4419 updateBuilder.update(vki, device);
4420 updateBuilder.clear();
4421 }
4422 }
4423
4424 #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)4425 void ImageFetchRenderInstance::writeDescriptorSetWithTemplate(
4426 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4427 ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
4428 vk::VkImageView viewA, vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4429 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry, bool withPush,
4430 vk::VkPipelineLayout pipelineLayout)
4431 {
4432 DE_UNREF(pool);
4433 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
4434 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
4435 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
4436 DE_NULL,
4437 0,
4438 0, // updateCount
4439 DE_NULL, // pUpdates
4440 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
4441 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
4442 layout,
4443 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4444 pipelineLayout,
4445 0};
4446 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(descriptorType);
4447 const vk::VkDescriptorImageInfo imageInfos[2] = {
4448 makeDescriptorImageInfo(viewA, imageLayout),
4449 makeDescriptorImageInfo(viewB, imageLayout),
4450 };
4451
4452 RawUpdateRegistry updateRegistry;
4453
4454 updateRegistry.addWriteObject(imageInfos[0]);
4455 updateRegistry.addWriteObject(imageInfos[1]);
4456
4457 switch (shaderInterface)
4458 {
4459 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4460 updateEntries.push_back(
4461 createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4462 break;
4463
4464 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4465 updateEntries.push_back(
4466 createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4467 updateEntries.push_back(
4468 createTemplateBinding(1, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
4469 break;
4470
4471 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4472 updateEntries.push_back(
4473 createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4474 updateEntries.push_back(
4475 createTemplateBinding(2, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
4476 break;
4477
4478 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4479 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
4480 updateRegistry.getWriteObjectOffset(0), 0));
4481 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
4482 updateRegistry.getWriteObjectOffset(1), 0));
4483 break;
4484
4485 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4486 updateEntries.push_back(createTemplateBinding(0, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
4487 sizeof(imageInfos[0])));
4488 break;
4489
4490 default:
4491 DE_FATAL("Impossible");
4492 }
4493
4494 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
4495 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
4496
4497 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
4498 vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
4499 updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
4500 registry.push_back(updateRegistry);
4501
4502 if (!withPush)
4503 {
4504 vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
4505 registry.back().getRawPointer());
4506 }
4507 }
4508 #endif
4509
logTestPlan(void) const4510 void ImageFetchRenderInstance::logTestPlan(void) const
4511 {
4512 std::ostringstream msg;
4513
4514 msg << "Rendering 2x2 grid.\n"
4515 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
4516 "Multiple descriptor sets. ")
4517 << "Each descriptor set contains "
4518 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4519 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4520 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
4521 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
4522 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4523 (const char *)DE_NULL)
4524 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
4525 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4526
4527 if (m_baseMipLevel)
4528 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4529 if (m_baseArraySlice)
4530 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4531
4532 if (m_stageFlags == 0u)
4533 {
4534 msg << "Descriptors are not accessed in any shader stage.\n";
4535 }
4536 else
4537 {
4538 msg << "Color in each cell is fetched using the descriptor(s):\n";
4539
4540 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4541 {
4542 msg << "Test sample " << resultNdx << ": fetching at position "
4543 << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4544
4545 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4546 {
4547 const int srcResourceNdx = (resultNdx % 2); // ABAB source
4548 msg << " from descriptor " << srcResourceNdx;
4549 }
4550
4551 msg << "\n";
4552 }
4553
4554 msg << "Descriptors are accessed in {"
4555 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
4556 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
4557 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
4558 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
4559 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.";
4560 }
4561
4562 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
4563 }
4564
getPipelineLayout(void) const4565 vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout(void) const
4566 {
4567 return *m_pipelineLayout;
4568 }
4569
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const4570 void ImageFetchRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
4571 {
4572 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
4573 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4574 {
4575 std::vector<vk::VkDescriptorSet> sets;
4576 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4577 sets.push_back(**m_descriptorSets[setNdx]);
4578
4579 switch (m_descriptorSetCount)
4580 {
4581 case DESCRIPTOR_SET_COUNT_SINGLE:
4582 case DESCRIPTOR_SET_COUNT_MULTIPLE:
4583 {
4584 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4585 getPipelineLayout(), 0, (int)sets.size(), &sets.front(), 0, DE_NULL, m_bind2);
4586 break;
4587 }
4588 case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
4589 {
4590 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4591 {
4592 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
4593 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4594 getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], 0, DE_NULL, m_bind2);
4595 }
4596 break;
4597 }
4598 default:
4599 DE_FATAL("Impossible");
4600 }
4601 }
4602 #ifndef CTS_USES_VULKANSC
4603 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4604 {
4605 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4606 m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, **m_updateTemplates[setNdx], getPipelineLayout(),
4607 getDescriptorSetNdx(m_descriptorSetCount, setNdx),
4608 (const void *)m_updateRegistry[setNdx].getRawPointer());
4609 }
4610 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4611 {
4612 uint32_t descriptorNdx = 0u;
4613 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4614 {
4615 const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
4616 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout,
4617 getDescriptorSetNdx(m_descriptorSetCount, setNdx), descriptorNdx,
4618 numDescriptors);
4619 descriptorNdx += numDescriptors;
4620 }
4621 }
4622 #endif
4623
4624 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
4625 }
4626
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const4627 tcu::TestStatus ImageFetchRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
4628 {
4629 const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
4630 const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
4631 const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
4632 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
4633
4634 tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
4635
4636 tcu::Vec4 sample0 = tcu::Vec4(0.0f);
4637 tcu::Vec4 sample1 = tcu::Vec4(0.0f);
4638 tcu::Vec4 sample2 = tcu::Vec4(0.0f);
4639 tcu::Vec4 sample3 = tcu::Vec4(0.0f);
4640
4641 for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
4642 {
4643 sample0 += (!doFetch) ? (yellow) : (m_images.fetchImageValue(0, setNdx));
4644 sample1 += (!doFetch) ? (green) : (m_images.fetchImageValue(1, setNdx));
4645 sample2 += (!doFetch) ? (green) : (m_images.fetchImageValue(2, setNdx));
4646 sample3 += (!doFetch) ? (yellow) : (m_images.fetchImageValue(3, setNdx));
4647 }
4648
4649 if (numDescriptorSets > 1)
4650 {
4651 sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
4652 sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
4653 sample2 = sample2 / tcu::Vec4(float(numDescriptorSets));
4654 sample3 = sample3 / tcu::Vec4(float(numDescriptorSets));
4655 }
4656
4657 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
4658
4659 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
4660 result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
4661 return tcu::TestStatus::fail("Image verification failed");
4662 else
4663 return tcu::TestStatus::pass("Pass");
4664 }
4665
4666 class ImageFetchComputeInstance : public vkt::TestInstance
4667 {
4668 public:
4669 ImageFetchComputeInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
4670 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4671 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
4672 uint32_t baseArraySlice, const bool bind2);
4673
4674 private:
4675 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
4676 vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
4677 vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
4678 uint32_t setNdx);
4679 void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
4680 #ifndef CTS_USES_VULKANSC
4681 void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
4682 uint32_t setNdx, bool withPush = false,
4683 vk::VkPipelineLayout pipelineLayout = DE_NULL);
4684 #endif
4685
4686 tcu::TestStatus iterate(void);
4687 void logTestPlan(void) const;
4688 tcu::TestStatus testResourceAccess(void);
4689
4690 const DescriptorUpdateMethod m_updateMethod;
4691 const vk::VkDescriptorType m_descriptorType;
4692 const DescriptorSetCount m_descriptorSetCount;
4693 const ShaderInputInterface m_shaderInterface;
4694 const vk::VkImageViewType m_viewType;
4695 const uint32_t m_numLevels;
4696 const uint32_t m_baseMipLevel;
4697 const uint32_t m_baseArraySlice;
4698 const bool m_bind2;
4699 #ifndef CTS_USES_VULKANSC
4700 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
4701 #endif
4702 const vk::DeviceInterface &m_vki;
4703 const vk::VkDevice m_device;
4704 const vk::VkQueue m_queue;
4705 const uint32_t m_queueFamilyIndex;
4706 vk::Allocator &m_allocator;
4707 const ComputeInstanceResultBuffer m_result;
4708 const ImageFetchInstanceImages m_images;
4709 #ifndef CTS_USES_VULKANSC
4710 std::vector<RawUpdateRegistry> m_updateRegistry;
4711 #endif
4712 vk::DescriptorSetUpdateBuilder m_updateBuilder;
4713 std::vector<uint32_t> m_descriptorsPerSet;
4714 };
4715
ImageFetchComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,const bool bind2)4716 ImageFetchComputeInstance::ImageFetchComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
4717 vk::VkDescriptorType descriptorType,
4718 DescriptorSetCount descriptorSetCount,
4719 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
4720 uint32_t baseMipLevel, uint32_t baseArraySlice, const bool bind2)
4721 : vkt::TestInstance(context)
4722 , m_updateMethod(updateMethod)
4723 , m_descriptorType(descriptorType)
4724 , m_descriptorSetCount(descriptorSetCount)
4725 , m_shaderInterface(shaderInterface)
4726 , m_viewType(viewType)
4727 , m_numLevels(baseMipLevel + 1u)
4728 , m_baseMipLevel(baseMipLevel)
4729 , m_baseArraySlice(baseArraySlice)
4730 , m_bind2(bind2)
4731 #ifndef CTS_USES_VULKANSC
4732 , m_updateTemplates()
4733 #endif
4734 , m_vki(context.getDeviceInterface())
4735 , m_device(context.getDevice())
4736 , m_queue(context.getUniversalQueue())
4737 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
4738 , m_allocator(context.getDefaultAllocator())
4739 , m_result(m_vki, m_device, m_allocator)
4740 , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
4741 m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice)
4742 #ifndef CTS_USES_VULKANSC
4743 , m_updateRegistry()
4744 #endif
4745 , m_updateBuilder()
4746 , m_descriptorsPerSet()
4747 {
4748 }
4749
createDescriptorSetLayout(uint32_t setNdx) const4750 vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
4751 {
4752 vk::DescriptorSetLayoutBuilder builder;
4753 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
4754 uint32_t binding = 0;
4755
4756 #ifndef CTS_USES_VULKANSC
4757 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
4758 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4759 {
4760 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
4761 }
4762 #endif
4763
4764 if (setNdx == 0)
4765 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
4766 binding++);
4767
4768 switch (m_shaderInterface)
4769 {
4770 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4771 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4772 break;
4773
4774 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4775 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4776 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4777 break;
4778
4779 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4780 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding);
4781 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2);
4782 break;
4783
4784 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4785 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
4786 builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
4787 break;
4788
4789 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4790 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4791 break;
4792
4793 default:
4794 DE_FATAL("Impossible");
4795 }
4796
4797 return builder.build(m_vki, m_device, extraFlags);
4798 }
4799
createDescriptorPool(void) const4800 vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool(void) const
4801 {
4802 return vk::DescriptorPoolBuilder()
4803 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4804 .addType(m_descriptorType,
4805 getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
4806 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
4807 getDescriptorSetCount(m_descriptorSetCount));
4808 }
4809
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx)4810 vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
4811 vk::VkDescriptorSetLayout layout,
4812 uint32_t setNdx)
4813 {
4814 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
4815 pool, 1u, &layout};
4816
4817 vk::Move<vk::VkDescriptorSet> descriptorSet;
4818 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
4819 m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4820 {
4821 descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
4822 }
4823 else
4824 {
4825 descriptorSet = vk::Move<vk::VkDescriptorSet>();
4826 }
4827
4828 #ifndef CTS_USES_VULKANSC
4829 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
4830 {
4831 writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx);
4832 }
4833 else
4834 #endif
4835 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4836 {
4837 writeDescriptorSet(*descriptorSet, setNdx);
4838 }
4839
4840 return descriptorSet;
4841 }
4842
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)4843 void ImageFetchComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
4844 {
4845 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
4846 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4847 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(m_descriptorType);
4848 const vk::VkDescriptorImageInfo imageInfos[2] = {
4849 makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
4850 imageLayout),
4851 makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
4852 imageLayout),
4853 };
4854
4855 uint32_t binding = 0u;
4856 uint32_t numDescriptors = 0u;
4857
4858 // result
4859 if (setNdx == 0)
4860 {
4861 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4862 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4863 numDescriptors++;
4864 }
4865
4866 // images
4867 switch (m_shaderInterface)
4868 {
4869 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4870 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4871 m_descriptorType, &imageInfos[0]);
4872 numDescriptors++;
4873 break;
4874
4875 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4876 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4877 m_descriptorType, &imageInfos[0]);
4878 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4879 m_descriptorType, &imageInfos[1]);
4880 numDescriptors += 2;
4881 break;
4882
4883 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4884 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
4885 m_descriptorType, &imageInfos[0]);
4886 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
4887 m_descriptorType, &imageInfos[1]);
4888 numDescriptors += 2;
4889 break;
4890
4891 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4892 m_updateBuilder.writeSingle(descriptorSet,
4893 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
4894 m_descriptorType, &imageInfos[0]);
4895 m_updateBuilder.writeSingle(descriptorSet,
4896 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
4897 m_descriptorType, &imageInfos[1]);
4898 numDescriptors += 2;
4899 break;
4900
4901 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4902 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4903 m_descriptorType, 2u, imageInfos);
4904 numDescriptors++;
4905 break;
4906
4907 default:
4908 DE_FATAL("Impossible");
4909 }
4910
4911 m_descriptorsPerSet.push_back(numDescriptors);
4912
4913 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4914 {
4915 m_updateBuilder.update(m_vki, m_device);
4916 m_updateBuilder.clear();
4917 }
4918 }
4919
4920 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)4921 void ImageFetchComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
4922 vk::VkDescriptorSetLayout layout, uint32_t setNdx,
4923 bool withPush, vk::VkPipelineLayout pipelineLayout)
4924 {
4925 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
4926 m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4927 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(m_descriptorType);
4928 const vk::VkDescriptorImageInfo imageInfos[2] = {
4929 makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
4930 imageLayout),
4931 makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
4932 imageLayout),
4933 };
4934 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
4935 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
4936 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
4937 DE_NULL,
4938 0,
4939 0, // updateCount
4940 DE_NULL, // pUpdates
4941 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
4942 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
4943 layout,
4944 vk::VK_PIPELINE_BIND_POINT_COMPUTE,
4945 pipelineLayout,
4946 setNdx};
4947
4948 uint32_t binding = 0u;
4949 uint32_t offset = 0u;
4950 RawUpdateRegistry updateRegistry;
4951
4952 if (setNdx == 0)
4953 updateRegistry.addWriteObject(resultInfo);
4954
4955 updateRegistry.addWriteObject(imageInfos[0]);
4956 updateRegistry.addWriteObject(imageInfos[1]);
4957
4958 // result
4959 if (setNdx == 0)
4960 updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
4961 updateRegistry.getWriteObjectOffset(offset++), 0));
4962
4963 // images
4964 switch (m_shaderInterface)
4965 {
4966 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4967 updateEntries.push_back(
4968 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4969 break;
4970
4971 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4972 updateEntries.push_back(
4973 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4974 updateEntries.push_back(
4975 createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4976 break;
4977
4978 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4979 updateEntries.push_back(
4980 createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4981 updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
4982 updateRegistry.getWriteObjectOffset(offset++), 0));
4983 break;
4984
4985 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4986 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
4987 updateRegistry.getWriteObjectOffset(offset++), 0));
4988 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
4989 updateRegistry.getWriteObjectOffset(offset++), 0));
4990 break;
4991
4992 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4993 updateEntries.push_back(createTemplateBinding(
4994 binding++, 0, 2, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), sizeof(imageInfos[0])));
4995 break;
4996
4997 default:
4998 DE_FATAL("Impossible");
4999 }
5000
5001 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
5002 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
5003
5004 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
5005 vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
5006 m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
5007 m_updateRegistry.push_back(updateRegistry);
5008
5009 if (!withPush)
5010 {
5011 m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
5012 m_updateRegistry.back().getRawPointer());
5013 }
5014 }
5015 #endif
5016
iterate(void)5017 tcu::TestStatus ImageFetchComputeInstance::iterate(void)
5018 {
5019 logTestPlan();
5020 return testResourceAccess();
5021 }
5022
logTestPlan(void) const5023 void ImageFetchComputeInstance::logTestPlan(void) const
5024 {
5025 std::ostringstream msg;
5026
5027 msg << "Fetching 4 values from image in compute shader.\n"
5028 << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
5029 "Multiple descriptor sets. ")
5030 << "Each descriptor set contains "
5031 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
5032 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
5033 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
5034 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? "two" :
5035 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
5036 (const char *)DE_NULL)
5037 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5038 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
5039
5040 if (m_baseMipLevel)
5041 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
5042 if (m_baseArraySlice)
5043 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
5044
5045 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5046 {
5047 msg << "Test sample " << resultNdx << ": fetch at position "
5048 << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
5049
5050 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5051 {
5052 const int srcResourceNdx = (resultNdx % 2); // ABAB source
5053 msg << " from descriptor " << srcResourceNdx;
5054 }
5055
5056 msg << "\n";
5057 }
5058
5059 m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
5060 }
5061
testResourceAccess(void)5062 tcu::TestStatus ImageFetchComputeInstance::testResourceAccess(void)
5063 {
5064 const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
5065 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
5066 std::vector<DescriptorSetHandleSp> descriptorSets;
5067 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
5068 std::vector<vk::VkDescriptorSet> setHandles;
5069
5070 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5071 {
5072 vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
5073 vk::Move<vk::VkDescriptorSet> set = createDescriptorSet(*descriptorPool, *layout, setNdx);
5074
5075 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
5076 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
5077
5078 layoutHandles.push_back(**descriptorSetLayouts.back());
5079 setHandles.push_back(**descriptorSets.back());
5080
5081 // Add an empty descriptor set layout between sets 0 and 2
5082 if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
5083 {
5084 vk::DescriptorSetLayoutBuilder emptyBuilder;
5085 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
5086 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
5087
5088 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
5089 layoutHandles.push_back(**descriptorSetLayouts.back());
5090 }
5091 }
5092
5093 const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
5094 &layoutHandles.front());
5095 const uint32_t *const dynamicOffsets = DE_NULL;
5096 const int numDynamicOffsets = 0;
5097 const vk::VkBufferMemoryBarrier *const preBarriers = DE_NULL;
5098 const int numPreBarriers = 0;
5099 const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
5100 const int numPostBarriers = 1;
5101
5102 const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
5103 tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
5104 numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
5105 postBarriers, m_bind2);
5106
5107 tcu::Vec4 results[4];
5108 bool anyResultSet = false;
5109 bool allResultsOk = true;
5110
5111 #ifndef CTS_USES_VULKANSC
5112 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5113 {
5114 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5115 writeDescriptorSetWithTemplate(DE_NULL, layoutHandles[setNdx], setNdx, true, pipeline.getPipelineLayout());
5116
5117 compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
5118 }
5119 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5120 {
5121 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5122 writeDescriptorSet(DE_NULL, setNdx);
5123
5124 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
5125 }
5126 else
5127 #endif
5128 {
5129 compute.submitAndWait(m_queueFamilyIndex, m_queue);
5130 }
5131 m_result.readResultContentsTo(&results);
5132
5133 // verify
5134 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5135 {
5136 const tcu::Vec4 result = results[resultNdx];
5137
5138 tcu::Vec4 reference = tcu::Vec4(0.0f);
5139 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5140 reference += m_images.fetchImageValue(resultNdx, setNdx);
5141
5142 if (getDescriptorSetCount(m_descriptorSetCount) > 1)
5143 reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
5144
5145 const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
5146
5147 if (result != tcu::Vec4(-1.0f))
5148 anyResultSet = true;
5149
5150 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
5151 {
5152 allResultsOk = false;
5153
5154 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test sample " << resultNdx << ": Expected "
5155 << reference << ", got " << result << tcu::TestLog::EndMessage;
5156 }
5157 }
5158
5159 // read back and verify
5160 if (allResultsOk)
5161 return tcu::TestStatus::pass("Pass");
5162 else if (anyResultSet)
5163 return tcu::TestStatus::fail("Invalid result values");
5164 else
5165 {
5166 m_context.getTestContext().getLog()
5167 << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
5168 return tcu::TestStatus::fail("Result buffer was not written to");
5169 }
5170 }
5171
5172 class ImageSampleInstanceImages : private ImageInstanceImages
5173 {
5174 public:
5175 ImageSampleInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
5176 vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
5177 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
5178 vk::VkImageViewType viewType, uint32_t numLevels, uint32_t baseMipLevel,
5179 uint32_t baseArraySlice, bool immutable);
5180
5181 static std::vector<tcu::Sampler> getRefSamplers(DescriptorSetCount descriptorSetCount,
5182 ShaderInputInterface shaderInterface);
5183
5184 static std::vector<SamplerHandleSp> getSamplers(const vk::DeviceInterface &vki, vk::VkDevice device,
5185 std::vector<tcu::Sampler> &refSamplers,
5186 const tcu::TextureFormat imageFormat);
5187
5188 static tcu::Vec4 getSamplePos(vk::VkImageViewType viewType, uint32_t baseMipLevel, uint32_t baseArraySlice,
5189 int samplePosNdx);
5190 tcu::Vec4 fetchSampleValue(int samplePosNdx, int setNdx) const;
5191
getSourceImage(int ndx) const5192 inline tcu::TextureLevelPyramid getSourceImage(int ndx) const
5193 {
5194 return m_sourceImage[ndx % m_sourceImage.size()];
5195 }
getImageView(int ndx) const5196 inline vk::VkImageView getImageView(int ndx) const
5197 {
5198 return **m_imageView[ndx % m_imageView.size()];
5199 }
getRefSampler(int ndx) const5200 inline tcu::Sampler getRefSampler(int ndx) const
5201 {
5202 return m_refSampler[ndx % m_refSampler.size()];
5203 }
getSampler(int ndx) const5204 inline vk::VkSampler getSampler(int ndx) const
5205 {
5206 return **m_sampler[ndx % m_sampler.size()];
5207 }
isImmutable(void) const5208 inline bool isImmutable(void) const
5209 {
5210 return m_isImmutable;
5211 }
5212
5213 private:
5214 static int getNumImages(vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5215 ShaderInputInterface shaderInterface);
5216 static tcu::Sampler createRefSampler(int ndx);
5217 static vk::Move<vk::VkSampler> createSampler(const vk::DeviceInterface &vki, vk::VkDevice device,
5218 const tcu::Sampler &sampler, const tcu::TextureFormat &format);
5219
5220 static tcu::Texture1DArrayView getRef1DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5221 uint32_t baseArraySlice,
5222 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5223 static tcu::Texture2DArrayView getRef2DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5224 uint32_t baseArraySlice,
5225 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5226 static tcu::Texture3DView getRef3DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5227 uint32_t baseArraySlice,
5228 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5229 static tcu::TextureCubeArrayView getRefCubeView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5230 uint32_t baseArraySlice,
5231 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5232
5233 const vk::VkDescriptorType m_descriptorType;
5234 const ShaderInputInterface m_shaderInterface;
5235 const bool m_isImmutable;
5236
5237 std::vector<tcu::Sampler> m_refSampler;
5238 std::vector<SamplerHandleSp> m_sampler;
5239 };
5240
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)5241 ImageSampleInstanceImages::ImageSampleInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device,
5242 uint32_t queueFamilyIndex, vk::VkQueue queue,
5243 vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
5244 DescriptorSetCount descriptorSetCount,
5245 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
5246 uint32_t numLevels, uint32_t baseMipLevel, uint32_t baseArraySlice,
5247 bool immutable)
5248 : ImageInstanceImages(vki, device, queueFamilyIndex, queue, allocator, descriptorType, viewType,
5249 getNumImages(descriptorType, descriptorSetCount, shaderInterface), numLevels, baseMipLevel,
5250 baseArraySlice)
5251 , m_descriptorType(descriptorType)
5252 , m_shaderInterface(shaderInterface)
5253 , m_isImmutable(immutable)
5254 , m_refSampler(getRefSamplers(descriptorSetCount, shaderInterface))
5255 , m_sampler(getSamplers(vki, device, m_refSampler, m_imageFormat))
5256 {
5257 }
5258
getRefSamplers(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5259 std::vector<tcu::Sampler> ImageSampleInstanceImages::getRefSamplers(DescriptorSetCount descriptorSetCount,
5260 ShaderInputInterface shaderInterface)
5261 {
5262 std::vector<tcu::Sampler> refSamplers;
5263 for (uint32_t samplerNdx = 0;
5264 samplerNdx < getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
5265 samplerNdx++)
5266 refSamplers.push_back(createRefSampler(samplerNdx));
5267
5268 return refSamplers;
5269 }
5270
getSamplers(const vk::DeviceInterface & vki,vk::VkDevice device,std::vector<tcu::Sampler> & refSamplers,const tcu::TextureFormat imageFormat)5271 std::vector<SamplerHandleSp> ImageSampleInstanceImages::getSamplers(const vk::DeviceInterface &vki, vk::VkDevice device,
5272 std::vector<tcu::Sampler> &refSamplers,
5273 const tcu::TextureFormat imageFormat)
5274 {
5275 std::vector<SamplerHandleSp> samplers;
5276 for (uint32_t samplerNdx = 0; samplerNdx < (uint32_t)refSamplers.size(); samplerNdx++)
5277 {
5278 vk::Move<vk::VkSampler> sampler = createSampler(vki, device, refSamplers[samplerNdx], imageFormat);
5279 samplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
5280 }
5281 return samplers;
5282 }
5283
getSamplePos(vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,int samplePosNdx)5284 tcu::Vec4 ImageSampleInstanceImages::getSamplePos(vk::VkImageViewType viewType, uint32_t baseMipLevel,
5285 uint32_t baseArraySlice, int samplePosNdx)
5286 {
5287 DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
5288
5289 const uint32_t imageSize = (uint32_t)IMAGE_SIZE >> baseMipLevel;
5290 const uint32_t arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
5291
5292 // choose arbitrary values that are not ambiguous with NEAREST filtering
5293
5294 switch (viewType)
5295 {
5296 case vk::VK_IMAGE_VIEW_TYPE_1D:
5297 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5298 case vk::VK_IMAGE_VIEW_TYPE_2D:
5299 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5300 case vk::VK_IMAGE_VIEW_TYPE_3D:
5301 {
5302 const tcu::Vec3 coords[4] = {
5303 tcu::Vec3(0.75f, 0.5f, (float)(12u % imageSize) + 0.25f),
5304
5305 tcu::Vec3((float)(23u % imageSize) + 0.25f, (float)(73u % imageSize) + 0.5f,
5306 (float)(16u % imageSize) + 0.5f + (float)imageSize),
5307
5308 tcu::Vec3(-(float)(43u % imageSize) + 0.25f, (float)(84u % imageSize) + 0.5f + (float)imageSize,
5309 (float)(117u % imageSize) + 0.75f),
5310
5311 tcu::Vec3((float)imageSize + 0.5f, (float)(75u % imageSize) + 0.25f,
5312 (float)(83u % imageSize) + 0.25f + (float)imageSize),
5313 };
5314 const uint32_t slices[4] = {
5315 0u % arraySize,
5316 4u % arraySize,
5317 9u % arraySize,
5318 2u % arraySize,
5319 };
5320
5321 switch (viewType)
5322 {
5323 case vk::VK_IMAGE_VIEW_TYPE_1D:
5324 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5325 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, (float)slices[samplePosNdx], 0.0f, 0.0f);
5326 case vk::VK_IMAGE_VIEW_TYPE_2D:
5327 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5328 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, coords[samplePosNdx].y() / (float)imageSize,
5329 (float)slices[samplePosNdx], 0.0f);
5330 case vk::VK_IMAGE_VIEW_TYPE_3D:
5331 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, coords[samplePosNdx].y() / (float)imageSize,
5332 coords[samplePosNdx].z() / (float)imageSize, 0.0f);
5333 default:
5334 DE_FATAL("Impossible");
5335 return tcu::Vec4();
5336 }
5337 }
5338
5339 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
5340 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
5341 {
5342 // \note these values are in [0, texSize]*3 space for convenience
5343 const tcu::Vec3 coords[4] = {
5344 tcu::Vec3(0.75f, 0.5f, (float)imageSize),
5345
5346 tcu::Vec3((float)(13u % imageSize) + 0.25f, 0.0f, (float)(16u % imageSize) + 0.5f),
5347
5348 tcu::Vec3(0.0f, (float)(84u % imageSize) + 0.5f, (float)(10u % imageSize) + 0.75f),
5349
5350 tcu::Vec3((float)imageSize, (float)(75u % imageSize) + 0.25f, (float)(83u % imageSize) + 0.75f),
5351 };
5352 const uint32_t slices[4] = {
5353 1u % arraySize,
5354 2u % arraySize,
5355 9u % arraySize,
5356 5u % arraySize,
5357 };
5358
5359 DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize));
5360 DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize));
5361 DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize));
5362
5363 // map to [-1, 1]*3 space
5364 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f,
5365 coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f,
5366 coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f, (float)slices[samplePosNdx]);
5367 }
5368
5369 default:
5370 DE_FATAL("Impossible");
5371 return tcu::Vec4();
5372 }
5373 }
5374
fetchSampleValue(int samplePosNdx,int setNdx) const5375 tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue(int samplePosNdx, int setNdx) const
5376 {
5377 DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
5378
5379 // texture order is ABAB
5380 const bool isSamplerCase = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
5381 const uint32_t numImages = (isSamplerCase) ? 1 : getInterfaceNumResources(m_shaderInterface);
5382 const tcu::TextureLevelPyramid &sampleSrcA = getSourceImage(setNdx * numImages);
5383 const tcu::TextureLevelPyramid &sampleSrcB =
5384 (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? sampleSrcA : getSourceImage(setNdx * numImages + 1);
5385 const tcu::TextureLevelPyramid &sampleSrc = (isSamplerCase) ? (sampleSrcA) :
5386 ((samplePosNdx % 2) == 0) ? (sampleSrcA) :
5387 (sampleSrcB);
5388
5389 // sampler order is ABAB
5390 const tcu::Sampler &samplerA = getRefSampler(setNdx * getInterfaceNumResources(m_shaderInterface));
5391 const tcu::Sampler &samplerB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ?
5392 (samplerA) :
5393 getRefSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
5394 const tcu::Sampler &sampler = ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB);
5395
5396 const tcu::Vec4 samplePos = getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
5397 const float lod = 0.0f;
5398 std::vector<tcu::ConstPixelBufferAccess> levelStorage;
5399
5400 switch (m_viewType)
5401 {
5402 case vk::VK_IMAGE_VIEW_TYPE_1D:
5403 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5404 return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5405 .sample(sampler, samplePos.x(), samplePos.y(), lod);
5406 case vk::VK_IMAGE_VIEW_TYPE_2D:
5407 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5408 return getRef2DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5409 .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
5410 case vk::VK_IMAGE_VIEW_TYPE_3D:
5411 return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5412 .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
5413 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
5414 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
5415 return getRefCubeView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5416 .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), samplePos.w(), lod);
5417
5418 default:
5419 {
5420 DE_FATAL("Impossible");
5421 return tcu::Vec4();
5422 }
5423 }
5424 }
5425
getNumImages(vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5426 int ImageSampleInstanceImages::getNumImages(vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5427 ShaderInputInterface shaderInterface)
5428 {
5429 // If we are testing separate samplers, just one image is enough
5430 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5431 return getDescriptorSetCount(descriptorSetCount);
5432 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5433 {
5434 // combined: numImages == numSamplers
5435 return getInterfaceNumResources(shaderInterface) * getDescriptorSetCount(descriptorSetCount);
5436 }
5437 else
5438 {
5439 DE_FATAL("Impossible");
5440 return 0;
5441 }
5442 }
5443
createRefSampler(int ndx)5444 tcu::Sampler ImageSampleInstanceImages::createRefSampler(int ndx)
5445 {
5446 if (ndx % 2 == 0)
5447 {
5448 // linear, wrapping
5449 return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
5450 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
5451 tcu::Vec4(0.0f), true);
5452 }
5453 else
5454 {
5455 // nearest, clamping
5456 return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
5457 tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
5458 tcu::Vec4(0.0f), true);
5459 }
5460 }
5461
createSampler(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::Sampler & sampler,const tcu::TextureFormat & format)5462 vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler(const vk::DeviceInterface &vki, vk::VkDevice device,
5463 const tcu::Sampler &sampler,
5464 const tcu::TextureFormat &format)
5465 {
5466 const vk::VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, format);
5467
5468 return vk::createSampler(vki, device, &createInfo);
5469 }
5470
getRef1DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5471 tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView(const tcu::TextureLevelPyramid &source,
5472 uint32_t baseMipLevel, uint32_t baseArraySlice,
5473 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5474 {
5475 DE_ASSERT(levelStorage->empty());
5476
5477 const uint32_t numSlices = (uint32_t)source.getLevel(0).getHeight();
5478 const uint32_t numLevels = (uint32_t)source.getNumLevels();
5479
5480 // cut pyramid from baseMipLevel
5481 for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5482 {
5483 // cut levels from baseArraySlice
5484 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5485 const tcu::ConstPixelBufferAccess cutLevel =
5486 tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice);
5487 levelStorage->push_back(cutLevel);
5488 }
5489
5490 return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front());
5491 }
5492
getRef2DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5493 tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView(const tcu::TextureLevelPyramid &source,
5494 uint32_t baseMipLevel, uint32_t baseArraySlice,
5495 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5496 {
5497 DE_ASSERT(levelStorage->empty());
5498
5499 const uint32_t numSlices = (uint32_t)source.getLevel(0).getDepth();
5500 const uint32_t numLevels = (uint32_t)source.getNumLevels();
5501
5502 // cut pyramid from baseMipLevel
5503 for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5504 {
5505 // cut levels from baseArraySlice
5506 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5507 const tcu::ConstPixelBufferAccess cutLevel =
5508 tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(),
5509 numSlices - baseArraySlice);
5510 levelStorage->push_back(cutLevel);
5511 }
5512
5513 return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front());
5514 }
5515
getRef3DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5516 tcu::Texture3DView ImageSampleInstanceImages::getRef3DView(const tcu::TextureLevelPyramid &source,
5517 uint32_t baseMipLevel, uint32_t baseArraySlice,
5518 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5519 {
5520 DE_ASSERT(levelStorage->empty());
5521 DE_ASSERT(baseArraySlice == 0);
5522 DE_UNREF(baseArraySlice);
5523
5524 const uint32_t numLevels = (uint32_t)source.getNumLevels();
5525
5526 // cut pyramid from baseMipLevel
5527 for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5528 levelStorage->push_back(source.getLevel(level));
5529
5530 return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front());
5531 }
5532
getRefCubeView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5533 tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView(
5534 const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel, uint32_t baseArraySlice,
5535 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5536 {
5537 DE_ASSERT(levelStorage->empty());
5538
5539 const uint32_t numSlices = (uint32_t)source.getLevel(0).getDepth() / 6;
5540 const uint32_t numLevels = (uint32_t)source.getNumLevels();
5541
5542 // cut pyramid from baseMipLevel
5543 for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5544 {
5545 // cut levels from baseArraySlice
5546 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5547 const tcu::ConstPixelBufferAccess cutLevel =
5548 tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(),
5549 (numSlices - baseArraySlice) * 6);
5550 levelStorage->push_back(cutLevel);
5551 }
5552
5553 return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front());
5554 }
5555
5556 class ImageSampleRenderInstance : public SingleCmdRenderInstance
5557 {
5558 public:
5559 ImageSampleRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
5560 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5561 vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
5562 ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
5563 uint32_t baseArraySlice, bool isImmutable, const bool bind2);
5564
5565 private:
5566 static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
5567 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
5568 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
5569 const ImageSampleInstanceImages &images, DescriptorUpdateMethod updateMethod);
5570
5571 static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
5572 const vk::DeviceInterface &vki, vk::VkDevice device,
5573 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
5574
5575 static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
5576 vk::VkDescriptorType descriptorType,
5577 DescriptorSetCount descriptorSetCount,
5578 ShaderInputInterface shaderInterface);
5579
5580 static std::vector<DescriptorSetHandleSp> createDescriptorSets(
5581 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
5582 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5583 ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
5584 vk::VkDescriptorPool pool, bool isImmutable, const ImageSampleInstanceImages &images,
5585 vk::DescriptorSetUpdateBuilder &updateBuilder,
5586 #ifndef CTS_USES_VULKANSC
5587 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
5588 #endif
5589 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = DE_NULL);
5590
5591 static void writeSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5592 ShaderInputInterface shaderInterface, bool isImmutable,
5593 const ImageSampleInstanceImages &images, vk::VkDescriptorSet descriptorSet,
5594 uint32_t setNdx, vk::DescriptorSetUpdateBuilder &updateBuilder,
5595 std::vector<uint32_t> &descriptorsPerSet,
5596 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
5597
5598 static void writeImageSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5599 ShaderInputInterface shaderInterface, bool isImmutable,
5600 const ImageSampleInstanceImages &images,
5601 vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
5602 vk::DescriptorSetUpdateBuilder &updateBuilder,
5603 std::vector<uint32_t> &descriptorsPerSet,
5604 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
5605
5606 static void writeSamplerDescriptorSetWithTemplate(
5607 const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
5608 ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
5609 vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
5610 #ifndef CTS_USES_VULKANSC
5611 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry,
5612 #endif
5613 bool withPush = false, vk::VkPipelineLayout pipelineLayout = 0);
5614
5615 static void writeImageSamplerDescriptorSetWithTemplate(
5616 const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
5617 ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
5618 vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
5619 #ifndef CTS_USES_VULKANSC
5620 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry,
5621 #endif
5622 bool withPush = false, vk::VkPipelineLayout pipelineLayout = 0);
5623
5624 void logTestPlan(void) const;
5625 vk::VkPipelineLayout getPipelineLayout(void) const;
5626 void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
5627 tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
5628
5629 enum
5630 {
5631 RENDER_SIZE = 128,
5632 };
5633
5634 const DescriptorUpdateMethod m_updateMethod;
5635 const vk::VkDescriptorType m_descriptorType;
5636 const DescriptorSetCount m_descriptorSetCount;
5637 const vk::VkShaderStageFlags m_stageFlags;
5638 const vk::VkShaderStageFlags m_existingStages;
5639 const ShaderInputInterface m_shaderInterface;
5640 const vk::VkImageViewType m_viewType;
5641 const uint32_t m_numLevels;
5642 const uint32_t m_baseMipLevel;
5643 const uint32_t m_baseArraySlice;
5644
5645 #ifndef CTS_USES_VULKANSC
5646 std::vector<UpdateTemplateHandleSp> m_updateTemplates;
5647 std::vector<RawUpdateRegistry> m_updateRegistry;
5648 #endif
5649 vk::DescriptorSetUpdateBuilder m_updateBuilder;
5650 const ImageSampleInstanceImages m_images;
5651 std::vector<uint32_t> m_descriptorsPerSet;
5652 const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
5653 const vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
5654 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
5655 const std::vector<DescriptorSetHandleSp> m_descriptorSets;
5656 };
5657
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)5658 ImageSampleRenderInstance::ImageSampleRenderInstance(
5659 vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
5660 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, vk::VkShaderStageFlags stageFlags,
5661 vk::VkShaderStageFlags existingStages, ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
5662 uint32_t baseMipLevel, uint32_t baseArraySlice, bool isImmutable, const bool bind2)
5663 : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
5664 , m_updateMethod(updateMethod)
5665 , m_descriptorType(descriptorType)
5666 , m_descriptorSetCount(descriptorSetCount)
5667 , m_stageFlags(stageFlags)
5668 , m_existingStages(existingStages)
5669 , m_shaderInterface(shaderInterface)
5670 , m_viewType(viewType)
5671 , m_numLevels(baseMipLevel + 1u)
5672 , m_baseMipLevel(baseMipLevel)
5673 , m_baseArraySlice(baseArraySlice)
5674 #ifndef CTS_USES_VULKANSC
5675 , m_updateTemplates()
5676 , m_updateRegistry()
5677 #endif
5678 , m_updateBuilder()
5679 , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
5680 m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice, isImmutable)
5681 , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
5682 m_shaderInterface, m_stageFlags, m_images, m_updateMethod))
5683 , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
5684 , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
5685 , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
5686 m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool, isImmutable,
5687 m_images, m_updateBuilder,
5688 #ifndef CTS_USES_VULKANSC
5689 m_updateTemplates, m_updateRegistry,
5690 #endif
5691 m_descriptorsPerSet, *m_pipelineLayout))
5692 {
5693 }
5694
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,const ImageSampleInstanceImages & images,DescriptorUpdateMethod updateMethod)5695 std::vector<DescriptorSetLayoutHandleSp> ImageSampleRenderInstance::createDescriptorSetLayouts(
5696 const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
5697 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
5698 const ImageSampleInstanceImages &images, DescriptorUpdateMethod updateMethod)
5699 {
5700 #ifdef CTS_USES_VULKANSC
5701 DE_UNREF(updateMethod);
5702 #endif
5703 std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
5704
5705 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
5706 {
5707 const vk::VkSampler samplers[2] = {
5708 images.getSampler(setNdx * getInterfaceNumResources(shaderInterface)),
5709 images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1),
5710 };
5711
5712 vk::DescriptorSetLayoutBuilder builder;
5713 const bool addSeparateImage = descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER;
5714 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
5715
5716 #ifndef CTS_USES_VULKANSC
5717 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
5718 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5719 {
5720 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
5721 }
5722 #endif
5723
5724 // (combined)samplers follow
5725 switch (shaderInterface)
5726 {
5727 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5728 if (addSeparateImage)
5729 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5730 builder.addSingleSamplerBinding(descriptorType, stageFlags,
5731 (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
5732 break;
5733
5734 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5735 if (addSeparateImage)
5736 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5737 builder.addSingleSamplerBinding(descriptorType, stageFlags,
5738 (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
5739 builder.addSingleSamplerBinding(descriptorType, stageFlags,
5740 (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
5741 break;
5742
5743 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5744 builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, 0u,
5745 (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
5746 if (addSeparateImage)
5747 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags, 1u);
5748 builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, 2u,
5749 (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
5750 break;
5751
5752 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
5753 if (addSeparateImage)
5754 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5755 builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0),
5756 (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
5757 builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1),
5758 (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
5759 break;
5760
5761 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5762 if (addSeparateImage)
5763 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5764 builder.addArraySamplerBinding(descriptorType, 2u, stageFlags,
5765 (images.isImmutable()) ? (samplers) : (DE_NULL));
5766 break;
5767
5768 default:
5769 DE_FATAL("Impossible");
5770 }
5771
5772 vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
5773 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
5774
5775 // Add an empty descriptor set layout between sets 0 and 2
5776 if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
5777 {
5778 vk::DescriptorSetLayoutBuilder emptyBuilder;
5779 vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
5780 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
5781 descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
5782 }
5783 }
5784
5785 return descriptorSetLayouts;
5786 }
5787
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)5788 vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout(
5789 const vk::DeviceInterface &vki, vk::VkDevice device,
5790 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
5791 {
5792 std::vector<vk::VkDescriptorSetLayout> layoutHandles;
5793 for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
5794 layoutHandles.push_back(**descriptorSetLayout[setNdx]);
5795
5796 const vk::VkPipelineLayoutCreateInfo createInfo = {
5797 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
5798 DE_NULL,
5799 (vk::VkPipelineLayoutCreateFlags)0,
5800 (uint32_t)layoutHandles.size(), // descriptorSetCount
5801 &layoutHandles.front(), // pSetLayouts
5802 0u, // pushConstantRangeCount
5803 DE_NULL, // pPushConstantRanges
5804 };
5805 return vk::createPipelineLayout(vki, device, &createInfo);
5806 }
5807
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5808 vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
5809 vk::VkDevice device,
5810 vk::VkDescriptorType descriptorType,
5811 DescriptorSetCount descriptorSetCount,
5812 ShaderInputInterface shaderInterface)
5813 {
5814 vk::DescriptorPoolBuilder builder;
5815
5816 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5817 {
5818 // separate samplers need image to sample
5819 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, getDescriptorSetCount(descriptorSetCount));
5820
5821 // also need sample to use, indifferent of whether immutable or not
5822 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER,
5823 getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface));
5824 }
5825 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5826 {
5827 // combined image samplers
5828 builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
5829 getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface));
5830 }
5831 else
5832 DE_FATAL("Impossible");
5833
5834 return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
5835 getDescriptorSetCount(descriptorSetCount));
5836 }
5837
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)5838 std::vector<DescriptorSetHandleSp> ImageSampleRenderInstance::createDescriptorSets(
5839 const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
5840 vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
5841 const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool, bool isImmutable,
5842 const ImageSampleInstanceImages &images, vk::DescriptorSetUpdateBuilder &updateBuilder,
5843 #ifndef CTS_USES_VULKANSC
5844 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
5845 #endif
5846 std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
5847 {
5848 #ifdef CTS_USES_VULKANSC
5849 DE_UNREF(pipelineLayout);
5850 #endif
5851 std::vector<DescriptorSetHandleSp> descriptorSets;
5852
5853 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
5854 {
5855 vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
5856
5857 const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
5858 pool, 1u, &layout};
5859
5860 vk::Move<vk::VkDescriptorSet> descriptorSet;
5861 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
5862 updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5863 {
5864 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
5865 }
5866 else
5867 {
5868 descriptorSet = vk::Move<vk::VkDescriptorSet>();
5869 }
5870
5871 #ifndef CTS_USES_VULKANSC
5872 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
5873 {
5874 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5875 writeSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface, isImmutable,
5876 images, *descriptorSet, setNdx, layout, updateTemplates,
5877 updateRegistry);
5878 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5879 writeImageSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface,
5880 isImmutable, images, *descriptorSet, setNdx, layout,
5881 updateTemplates, updateRegistry);
5882 else
5883 DE_FATAL("Impossible");
5884 }
5885 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5886 {
5887 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5888 writeSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface, isImmutable,
5889 images, DE_NULL, setNdx, layout, updateTemplates, updateRegistry,
5890 true, pipelineLayout);
5891 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5892 writeImageSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface,
5893 isImmutable, images, DE_NULL, setNdx, layout,
5894 updateTemplates, updateRegistry, true, pipelineLayout);
5895 else
5896 DE_FATAL("Impossible");
5897 }
5898 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5899 {
5900 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5901 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, setNdx,
5902 updateBuilder, descriptorsPerSet, updateMethod);
5903 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5904 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet,
5905 setNdx, updateBuilder, descriptorsPerSet, updateMethod);
5906 else
5907 DE_FATAL("Impossible");
5908 }
5909 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
5910 #endif
5911 {
5912 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5913 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, setNdx,
5914 updateBuilder, descriptorsPerSet);
5915 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5916 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet,
5917 setNdx, updateBuilder, descriptorsPerSet);
5918 else
5919 DE_FATAL("Impossible");
5920 }
5921
5922 descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
5923 }
5924 return descriptorSets;
5925 }
5926
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)5927 void ImageSampleRenderInstance::writeSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5928 ShaderInputInterface shaderInterface, bool isImmutable,
5929 const ImageSampleInstanceImages &images,
5930 vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
5931 vk::DescriptorSetUpdateBuilder &updateBuilder,
5932 std::vector<uint32_t> &descriptorsPerSet,
5933 DescriptorUpdateMethod updateMethod)
5934 {
5935 const vk::VkDescriptorImageInfo imageInfo =
5936 makeDescriptorImageInfo(images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
5937 vk::VkDescriptorImageInfo samplersInfos[2] = {
5938 makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
5939 makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
5940 };
5941
5942 if (isImmutable)
5943 {
5944 samplersInfos[0].sampler = VK_NULL_HANDLE;
5945 samplersInfos[1].sampler = VK_NULL_HANDLE;
5946 }
5947
5948 const uint32_t samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
5949 uint32_t numDescriptors = 1u;
5950
5951 // stand alone texture
5952 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(samplerLocation),
5953 vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
5954
5955 // samplers
5956 if (!isImmutable || (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH))
5957 {
5958 switch (shaderInterface)
5959 {
5960 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5961 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5962 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5963 numDescriptors++;
5964 break;
5965
5966 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5967 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5968 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5969 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
5970 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5971 numDescriptors += 2;
5972 break;
5973
5974 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5975 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
5976 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5977 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
5978 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5979 numDescriptors += 2;
5980 break;
5981
5982 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
5983 updateBuilder.writeSingle(descriptorSet,
5984 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
5985 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5986 updateBuilder.writeSingle(descriptorSet,
5987 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
5988 vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5989 numDescriptors += 2;
5990 break;
5991
5992 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5993 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5994 vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
5995 numDescriptors++;
5996 break;
5997
5998 default:
5999 DE_FATAL("Impossible");
6000 }
6001 }
6002
6003 descriptorsPerSet.push_back(numDescriptors);
6004
6005 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6006 {
6007 updateBuilder.update(vki, device);
6008 updateBuilder.clear();
6009 }
6010 }
6011
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)6012 void ImageSampleRenderInstance::writeImageSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
6013 ShaderInputInterface shaderInterface, bool isImmutable,
6014 const ImageSampleInstanceImages &images,
6015 vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
6016 vk::DescriptorSetUpdateBuilder &updateBuilder,
6017 std::vector<uint32_t> &descriptorsPerSet,
6018 DescriptorUpdateMethod updateMethod)
6019 {
6020 const vk::VkSampler samplers[2] = {
6021 (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ?
6022 (0) :
6023 (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6024 (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ?
6025 (0) :
6026 (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6027 };
6028 const vk::VkDescriptorImageInfo imageSamplers[2] = {
6029 vk::makeDescriptorImageInfo(samplers[0],
6030 images.getImageView(setNdx * getInterfaceNumResources(shaderInterface)),
6031 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6032 vk::makeDescriptorImageInfo(samplers[1],
6033 images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1),
6034 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6035 };
6036 uint32_t numDescriptors = 0u;
6037
6038 // combined image samplers
6039 switch (shaderInterface)
6040 {
6041 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6042 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6043 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6044 numDescriptors++;
6045 break;
6046
6047 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6048 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6049 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6050 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
6051 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6052 numDescriptors += 2;
6053 break;
6054
6055 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6056 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6057 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6058 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
6059 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6060 numDescriptors += 2;
6061 break;
6062
6063 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6064 updateBuilder.writeSingle(descriptorSet,
6065 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
6066 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6067 updateBuilder.writeSingle(descriptorSet,
6068 vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
6069 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6070 numDescriptors += 2;
6071 break;
6072
6073 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6074 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6075 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
6076 numDescriptors++;
6077 break;
6078
6079 default:
6080 DE_FATAL("Impossible");
6081 }
6082
6083 descriptorsPerSet.push_back(numDescriptors);
6084
6085 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6086 {
6087 updateBuilder.update(vki, device);
6088 updateBuilder.clear();
6089 }
6090 }
6091
6092 #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)6093 void ImageSampleRenderInstance::writeSamplerDescriptorSetWithTemplate(
6094 const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
6095 ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
6096 vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
6097 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry, bool withPush,
6098 vk::VkPipelineLayout pipelineLayout)
6099 {
6100 const vk::VkDescriptorImageInfo imageInfo =
6101 makeDescriptorImageInfo(images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
6102 const vk::VkDescriptorImageInfo samplersInfos[2] = {
6103 makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6104 makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6105 };
6106
6107 const uint32_t samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
6108
6109 std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
6110 vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
6111 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
6112 DE_NULL,
6113 0,
6114 0, // updateCount
6115 DE_NULL, // pUpdates
6116 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
6117 vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
6118 layout,
6119 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6120 pipelineLayout,
6121 getDescriptorSetNdx(descriptorSetCount, setNdx)};
6122
6123 RawUpdateRegistry updateRegistry;
6124
6125 updateRegistry.addWriteObject(imageInfo);
6126 updateRegistry.addWriteObject(samplersInfos[0]);
6127 updateRegistry.addWriteObject(samplersInfos[1]);
6128
6129 // stand alone texture
6130 updateEntries.push_back(createTemplateBinding(samplerLocation, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
6131 updateRegistry.getWriteObjectOffset(0), 0));
6132
6133 // samplers
6134 if (!isImmutable || withPush)
6135 {
6136 switch (shaderInterface)
6137 {
6138 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6139 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6140 updateRegistry.getWriteObjectOffset(1), 0));
6141 break;
6142
6143 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6144 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6145 updateRegistry.getWriteObjectOffset(1), 0));
6146 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6147 updateRegistry.getWriteObjectOffset(2), 0));
6148 break;
6149
6150 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6151 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6152 updateRegistry.getWriteObjectOffset(1), 0));
6153 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6154 updateRegistry.getWriteObjectOffset(2), 0));
6155 break;
6156
6157 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6158 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
6159 vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6160 updateRegistry.getWriteObjectOffset(1), 0));
6161 updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
6162 vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6163 updateRegistry.getWriteObjectOffset(2), 0));
6164 break;
6165
6166 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6167 updateEntries.push_back(createTemplateBinding(1, 0, 2, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6168 updateRegistry.getWriteObjectOffset(1),
6169 sizeof(samplersInfos[0])));
6170 break;
6171
6172 default:
6173 DE_FATAL("Impossible");
6174 }
6175 }
6176
6177 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0];
6178 templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
6179
6180 vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
6181 vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
6182 updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
6183 registry.push_back(updateRegistry);
6184
6185 if (!withPush)
6186 {
6187 vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
6188 registry.back().getRawPointer());
6189 }
6190 }
6191
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)6192 void ImageSampleRenderInstance::writeImageSamplerDescriptorSetWithTemplate(
6193 const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
6194 ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
6195 vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
6196 std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> ®istry, bool withPush,
6197 vk::VkPipelineLayout pipelineLayout)
6198 {
6199 const vk::VkSampler samplers[2] = {
6200 (isImmutable && !withPush) ? (0) : (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6201 (isImmutable && !withPush) ? (0) : (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 DE_NULL,
6216 0,
6217 0, // updateCount
6218 DE_NULL, // 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 (const char *)DE_NULL)
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 (const char *)DE_NULL)
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, DE_NULL,
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, DE_NULL,
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.cmdPushDescriptorSetWithTemplateKHR(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 = DE_NULL);
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 = DE_NULL);
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 = DE_NULL);
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]) : (DE_NULL));
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]) : (DE_NULL));
6617 builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding++,
6618 (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
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]) : (DE_NULL));
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]) : (DE_NULL));
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]) : (DE_NULL));
6638 builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6639 getArbitraryBindingIndex(1),
6640 (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
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) : (DE_NULL));
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, DE_NULL,
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 DE_NULL,
6843 0,
6844 0, // updateCount
6845 DE_NULL, // 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 (0) :
6943 (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
6944 (m_isImmutableSampler && (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) ?
6945 (0) :
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 (0) :
7033 (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
7034 (m_isImmutableSampler && !withPush) ?
7035 (0) :
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 DE_NULL,
7049 0,
7050 0, // updateCount
7051 DE_NULL, // 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 (const char *)DE_NULL)
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 (const char *)DE_NULL)
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 = DE_NULL;
7240 const int numDynamicOffsets = 0;
7241 const vk::VkBufferMemoryBarrier *const preBarriers = DE_NULL;
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(DE_NULL, 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(DE_NULL, 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 (DE_NULL);
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 (DE_NULL);
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 (DE_NULL);
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 (DE_NULL);
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 (DE_NULL);
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 DE_NULL;
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 DE_NULL,
8141 0u, // flags
8142 (vk::VkDeviceSize)BUFFER_SIZE, // size
8143 usage, // usage
8144 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
8145 0u, // queueFamilyCount
8146 DE_NULL, // 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 DE_NULL,
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 DE_NULL,
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 = DE_NULL);
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 = 0);
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 DE_NULL,
8449 (vk::VkPipelineLayoutCreateFlags)0,
8450 (uint32_t)layoutHandles.size(), // descriptorSetCount
8451 &layoutHandles.front(), // pSetLayouts
8452 0u, // pushConstantRangeCount
8453 DE_NULL, // 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, DE_NULL,
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 DE_NULL,
8622 0,
8623 0, // updateCount
8624 DE_NULL, // 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 (const char *)DE_NULL)
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, DE_NULL, 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, DE_NULL, 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.cmdPushDescriptorSetWithTemplateKHR(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 = DE_NULL);
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, DE_NULL,
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 DE_NULL,
9113 0,
9114 0, // updateCount
9115 DE_NULL, // 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 (const char *)DE_NULL)
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 = DE_NULL;
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(DE_NULL, layoutHandles[setNdx], setNdx, true, pipeline.getPipelineLayout());
9286
9287 compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
9288 }
9289 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
9290 {
9291 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9292 writeDescriptorSet(DE_NULL, setNdx);
9293
9294 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
9295 }
9296 else
9297 #endif
9298 {
9299 compute.submitAndWait(m_queueFamilyIndex, m_queue);
9300 }
9301 m_result.readResultContentsTo(&results);
9302
9303 // verify
9304 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
9305 {
9306 const tcu::Vec4 result = results[resultNdx];
9307 const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
9308
9309 tcu::Vec4 reference = tcu::Vec4(0.0f);
9310 for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9311 reference += m_texelBuffers.fetchTexelValue(resultNdx, setNdx);
9312
9313 reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
9314
9315 if (result != tcu::Vec4(-1.0f))
9316 anyResultSet = true;
9317
9318 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
9319 {
9320 allResultsOk = false;
9321
9322 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test sample " << resultNdx << ": Expected "
9323 << reference << ", got " << result << tcu::TestLog::EndMessage;
9324 }
9325 }
9326
9327 // read back and verify
9328 if (allResultsOk)
9329 return tcu::TestStatus::pass("Pass");
9330 else if (anyResultSet)
9331 return tcu::TestStatus::fail("Invalid result values");
9332 else
9333 {
9334 m_context.getTestContext().getLog()
9335 << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
9336 return tcu::TestStatus::fail("Result buffer was not written to");
9337 }
9338 }
9339
9340 class TexelBufferDescriptorCase : public QuadrantRendederCase
9341 {
9342 public:
9343 enum
9344 {
9345 FLAG_VIEW_OFFSET = (1u << 1u),
9346 };
9347 // enum continues where resource flags ends
9348 DE_STATIC_ASSERT((uint32_t)FLAG_VIEW_OFFSET == (uint32_t)RESOURCE_FLAG_LAST);
9349
9350 TexelBufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name,
9351 bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
9352 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9353 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
9354 uint32_t flags, const bool m_bind2);
9355
9356 void checkSupport(Context &context) const;
9357
9358 private:
9359 std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
9360 std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
9361 std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
9362 std::string genNoAccessSource(void) const;
9363
9364 vkt::TestInstance *createInstance(vkt::Context &context) const;
9365
9366 const DescriptorUpdateMethod m_updateMethod;
9367 const bool m_isPrimaryCmdBuf;
9368 const vk::VkDescriptorType m_descriptorType;
9369 const DescriptorSetCount m_descriptorSetCount;
9370 const ShaderInputInterface m_shaderInterface;
9371 const bool m_nonzeroViewOffset;
9372 const bool m_bind2;
9373 };
9374
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)9375 TexelBufferDescriptorCase::TexelBufferDescriptorCase(
9376 tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name, bool isPrimaryCmdBuf,
9377 vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9378 DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, uint32_t flags, const bool bind2)
9379 : QuadrantRendederCase(testCtx, name, glu::GLSL_VERSION_310_ES, exitingStages, activeStages, descriptorSetCount)
9380 , m_updateMethod(updateMethod)
9381 , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
9382 , m_descriptorType(descriptorType)
9383 , m_descriptorSetCount(descriptorSetCount)
9384 , m_shaderInterface(shaderInterface)
9385 , m_nonzeroViewOffset(((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u))
9386 , m_bind2(bind2)
9387 {
9388 }
9389
checkSupport(Context & context) const9390 void TexelBufferDescriptorCase::checkSupport(Context &context) const
9391 {
9392 if (m_bind2)
9393 context.requireDeviceFunctionality("VK_KHR_maintenance6");
9394 }
9395
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const9396 std::string TexelBufferDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
9397 {
9398 DE_UNREF(stage);
9399 return "#extension GL_EXT_texture_buffer : require\n";
9400 }
9401
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const9402 std::string TexelBufferDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage,
9403 int numUsedBindings) const
9404 {
9405 DE_UNREF(stage);
9406
9407 const bool isUniform = isUniformDescriptorType(m_descriptorType);
9408 const char *const storageType = (isUniform) ? ("textureBuffer ") : ("readonly imageBuffer ");
9409 const char *const formatQualifier = (isUniform) ? ("") : (", rgba8");
9410 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
9411
9412 std::ostringstream buf;
9413
9414 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
9415 {
9416 // Result buffer is bound only to the first descriptor set in compute shader cases
9417 const int descBinding =
9418 numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
9419 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
9420 const uint32_t descriptorSet = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
9421
9422 switch (m_shaderInterface)
9423 {
9424 case SHADER_INPUT_SINGLE_DESCRIPTOR:
9425 buf << "layout(set = " << descriptorSet
9426 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9427 "u_texelBuffer"
9428 << setNdxPostfix << ";\n";
9429 break;
9430 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
9431 buf << "layout(set = " << descriptorSet
9432 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9433 "u_texelBuffer"
9434 << setNdxPostfix
9435 << "A;\n"
9436 "layout(set = "
9437 << descriptorSet
9438 << ", binding = " + de::toString(descBinding + 1) + formatQualifier + ") uniform highp " + storageType +
9439 "u_texelBuffer"
9440 << setNdxPostfix << "B;\n";
9441 break;
9442 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
9443 buf << "layout(set = " << descriptorSet
9444 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9445 "u_texelBuffer"
9446 << setNdxPostfix
9447 << "A;\n"
9448 "layout(set = "
9449 << descriptorSet
9450 << ", binding = " + de::toString(descBinding + 2) + formatQualifier + ") uniform highp " + storageType +
9451 "u_texelBuffer"
9452 << setNdxPostfix << "B;\n";
9453 break;
9454 case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
9455 buf << "layout(set = " << descriptorSet
9456 << ", binding = " + de::toString(getArbitraryBindingIndex(0)) + formatQualifier + ") uniform highp " +
9457 storageType + "u_texelBuffer"
9458 << setNdxPostfix
9459 << "A;\n"
9460 "layout(set = "
9461 << descriptorSet
9462 << ", binding = " + de::toString(getArbitraryBindingIndex(1)) + formatQualifier + ") uniform highp " +
9463 storageType + "u_texelBuffer"
9464 << setNdxPostfix << "B;\n";
9465 break;
9466 case SHADER_INPUT_DESCRIPTOR_ARRAY:
9467 buf << "layout(set = " << descriptorSet
9468 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9469 "u_texelBuffer"
9470 << setNdxPostfix << "[2];\n";
9471 break;
9472 default:
9473 DE_FATAL("Impossible");
9474 return "";
9475 }
9476 }
9477 return buf.str();
9478 }
9479
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const9480 std::string TexelBufferDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
9481 {
9482 DE_UNREF(stage);
9483
9484 const char *const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") :
9485 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("A") :
9486 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("A") :
9487 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? ("A") :
9488 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]") :
9489 (DE_NULL);
9490 const char *const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") :
9491 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("B") :
9492 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("B") :
9493 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) ? ("B") :
9494 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]") :
9495 (DE_NULL);
9496 const char *const fetchFunc = (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad");
9497 const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
9498
9499 std::ostringstream buf;
9500
9501 buf << " result_color = vec4(0.0);\n";
9502
9503 for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
9504 {
9505 const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
9506
9507 buf << " if (quadrant_id == 0)\n"
9508 << " result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixA << ", "
9509 << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n"
9510 << " else if (quadrant_id == 1)\n"
9511 << " result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixB << ", "
9512 << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n"
9513 << " else if (quadrant_id == 2)\n"
9514 << " result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixA << ", "
9515 << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n"
9516 << " else\n"
9517 << " result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixB << ", "
9518 << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n";
9519 }
9520
9521 if (getDescriptorSetCount(m_descriptorSetCount) > 1)
9522 buf << " result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
9523
9524 return buf.str();
9525 }
9526
genNoAccessSource(void) const9527 std::string TexelBufferDescriptorCase::genNoAccessSource(void) const
9528 {
9529 return " if (quadrant_id == 1 || quadrant_id == 2)\n"
9530 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
9531 " else\n"
9532 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
9533 }
9534
createInstance(vkt::Context & context) const9535 vkt::TestInstance *TexelBufferDescriptorCase::createInstance(vkt::Context &context) const
9536 {
9537 verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
9538 m_updateMethod, m_descriptorType, m_activeStages);
9539
9540 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
9541 {
9542 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
9543 return new TexelBufferComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
9544 m_shaderInterface, m_nonzeroViewOffset, m_bind2);
9545 }
9546 else
9547 return new TexelBufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
9548 m_descriptorSetCount, m_activeStages, m_exitingStages, m_shaderInterface,
9549 m_nonzeroViewOffset, m_bind2);
9550 }
9551
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)9552 void createShaderAccessImageTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf, DescriptorUpdateMethod updateMethod,
9553 vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages,
9554 vk::VkShaderStageFlags activeStages, DescriptorSetCount descriptorSetCount,
9555 ShaderInputInterface dimension, uint32_t resourceFlags, const bool bind2)
9556 {
9557 static const struct
9558 {
9559 vk::VkImageViewType viewType;
9560 const char *name;
9561 uint32_t flags;
9562 } s_imageTypes[] = {
9563 {vk::VK_IMAGE_VIEW_TYPE_1D, "1d", 0u},
9564 {vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9565 {vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9566
9567 {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array", 0u},
9568 {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9569 {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9570
9571 {vk::VK_IMAGE_VIEW_TYPE_2D, "2d", 0u},
9572 {vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9573 {vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9574
9575 {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array", 0u},
9576 {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9577 {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9578
9579 {vk::VK_IMAGE_VIEW_TYPE_3D, "3d", 0u},
9580 {vk::VK_IMAGE_VIEW_TYPE_3D, "3d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9581 // no 3d array textures
9582
9583 {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube", 0u},
9584 {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9585 {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9586
9587 {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array", 0u},
9588 {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9589 {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE}};
9590
9591 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx)
9592 {
9593 // never overlap
9594 DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u);
9595
9596 // skip some image view variations to avoid unnecessary bloating
9597 if ((descriptorType != vk::VK_DESCRIPTOR_TYPE_SAMPLER) &&
9598 (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) &&
9599 (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9600 continue;
9601
9602 if ((dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) &&
9603 (activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) &&
9604 (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9605 continue;
9606
9607 if ((dimension == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) &&
9608 (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9609 continue;
9610
9611 if ((descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS) &&
9612 (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9613 continue;
9614
9615 group->addChild(new ImageDescriptorCase(group->getTestContext(), s_imageTypes[ndx].name, isPrimaryCmdBuf,
9616 updateMethod, descriptorType, exitingStages, activeStages,
9617 descriptorSetCount, dimension, s_imageTypes[ndx].viewType,
9618 s_imageTypes[ndx].flags | resourceFlags, bind2));
9619 }
9620 }
9621
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)9622 void createShaderAccessTexelBufferTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf,
9623 DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
9624 vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9625 DescriptorSetCount descriptorSetCount, ShaderInputInterface dimension,
9626 uint32_t resourceFlags, const bool bind2)
9627 {
9628 DE_ASSERT(resourceFlags == 0);
9629 DE_UNREF(resourceFlags);
9630
9631 static const struct
9632 {
9633 const char *name;
9634 uint32_t flags;
9635 } s_texelBufferTypes[] = {
9636 // View offset is zero
9637 {"offset_zero", 0u},
9638 // View offset is non-zero
9639 {"offset_nonzero", TexelBufferDescriptorCase::FLAG_VIEW_OFFSET},
9640 };
9641
9642 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx)
9643 {
9644 group->addChild(new TexelBufferDescriptorCase(
9645 group->getTestContext(), updateMethod, s_texelBufferTypes[ndx].name, isPrimaryCmdBuf, descriptorType,
9646 exitingStages, activeStages, descriptorSetCount, dimension, s_texelBufferTypes[ndx].flags, bind2));
9647 }
9648 }
9649
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)9650 void createShaderAccessBufferTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf, DescriptorUpdateMethod updateMethod,
9651 vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages,
9652 vk::VkShaderStageFlags activeStages, DescriptorSetCount descriptorSetCount,
9653 ShaderInputInterface dimension, uint32_t resourceFlags, const bool bind2)
9654 {
9655 DE_ASSERT(resourceFlags == 0u);
9656 DE_UNREF(resourceFlags);
9657
9658 static const struct
9659 {
9660 const char *name;
9661 bool isForDynamicCases;
9662 uint32_t flags;
9663 } s_bufferTypes[] = {
9664 {"offset_view_zero", false, 0u},
9665 {"offset_view_nonzero", false, BufferDescriptorCase::FLAG_VIEW_OFFSET},
9666
9667 {"offset_view_zero_dynamic_zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO},
9668 {"offset_view_zero_dynamic_nonzero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO},
9669 {"offset_view_nonzero_dynamic_zero", true,
9670 BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO},
9671 {"offset_view_nonzero_dynamic_nonzero", true,
9672 BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO},
9673 };
9674
9675 const bool isDynamicCase = isDynamicDescriptorType(descriptorType);
9676
9677 if (isDynamicCase)
9678 {
9679 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH ||
9680 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9681 {
9682 // Can't support push descriptor sets with dynamic UBOs or SSBOs
9683 return;
9684 }
9685 }
9686
9687 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx)
9688 {
9689 if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases)
9690 group->addChild(new BufferDescriptorCase(group->getTestContext(), updateMethod, s_bufferTypes[ndx].name,
9691 isPrimaryCmdBuf, descriptorType, exitingStages, activeStages,
9692 descriptorSetCount, dimension, s_bufferTypes[ndx].flags, bind2));
9693 }
9694 }
9695
9696 } // namespace
9697
createShaderAccessTests(tcu::TestContext & testCtx)9698 tcu::TestCaseGroup *createShaderAccessTests(tcu::TestContext &testCtx)
9699 {
9700 static const struct
9701 {
9702 const bool isPrimary;
9703 const char *name;
9704 } s_bindTypes[] = {
9705 // Bind in primary command buffer
9706 {true, "primary_cmd_buf"},
9707 // Bind in secondary command buffer
9708 {false, "secondary_cmd_buf"},
9709 };
9710 static const struct
9711 {
9712 const DescriptorUpdateMethod method;
9713 const char *name;
9714 } s_updateMethods[] = {
9715 {DESCRIPTOR_UPDATE_METHOD_NORMAL, ""},
9716 #ifndef CTS_USES_VULKANSC
9717 // Use descriptor update templates
9718 {DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE, "with_template"},
9719 // Use push descriptor updates
9720 {DESCRIPTOR_UPDATE_METHOD_WITH_PUSH, "with_push"},
9721 // Use push descriptor update templates
9722 {DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE, "with_push_template"},
9723 #endif
9724 };
9725 static const struct
9726 {
9727 const vk::VkDescriptorType descriptorType;
9728 const char *name;
9729 const char *description;
9730 uint32_t flags;
9731 } s_descriptorTypes[] = {
9732 {vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_mutable", "VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler", 0u},
9733 {vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_immutable", "VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler",
9734 RESOURCE_FLAG_IMMUTABLE_SAMPLER},
9735 {vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_mutable",
9736 "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler", 0u},
9737 {vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_immutable",
9738 "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER},
9739 // \note No way to access SAMPLED_IMAGE without a sampler
9740 //{ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image", "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE", 0u },
9741 {vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image", "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE", 0u},
9742 {vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, "uniform_texel_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER",
9743 0u},
9744 {vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "storage_texel_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER",
9745 0u},
9746 {vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER", 0u},
9747 {vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER", 0u},
9748 {vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic",
9749 "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC", 0u},
9750 {vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic",
9751 "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC", 0u},
9752 };
9753 static const struct
9754 {
9755 const char *name;
9756 vk::VkShaderStageFlags existingStages; //!< stages that exists
9757 vk::VkShaderStageFlags activeStages; //!< stages that access resource
9758 bool supportsSecondaryCmdBufs;
9759 } s_shaderStages[] = {
9760 // No accessing stages
9761 {
9762 "no_access",
9763 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9764 0u,
9765 true,
9766 },
9767 // Vertex stage
9768 {
9769 "vertex",
9770 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9771 vk::VK_SHADER_STAGE_VERTEX_BIT,
9772 true,
9773 },
9774 // Tessellation control stage
9775 {
9776 "tess_ctrl",
9777 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
9778 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9779 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
9780 true,
9781 },
9782 // Tessellation evaluation stage
9783 {
9784 "tess_eval",
9785 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
9786 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9787 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
9788 true,
9789 },
9790 // Geometry stage
9791 {
9792 "geometry",
9793 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9794 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
9795 true,
9796 },
9797 // Fragment stage
9798 {
9799 "fragment",
9800 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9801 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9802 true,
9803 },
9804 // Compute stage
9805 {
9806 "compute",
9807 vk::VK_SHADER_STAGE_COMPUTE_BIT,
9808 vk::VK_SHADER_STAGE_COMPUTE_BIT,
9809 false,
9810 },
9811 // Vertex and fragment stages
9812 {
9813 "vertex_fragment",
9814 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9815 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9816 true,
9817 }};
9818 static const struct
9819 {
9820 ShaderInputInterface dimension;
9821 const char *name;
9822 } s_variableDimensions[] = {
9823 {SHADER_INPUT_SINGLE_DESCRIPTOR, "single_descriptor"},
9824 {SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, "multiple_contiguous_descriptors"},
9825 {SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, "multiple_discontiguous_descriptors"},
9826 {SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS, "multiple_arbitrary_descriptors"},
9827 {SHADER_INPUT_DESCRIPTOR_ARRAY, "descriptor_array"},
9828 };
9829 static const struct
9830 {
9831 const bool bind2;
9832 const char *name;
9833 const char *description;
9834 } s_bindCommand[] = {
9835 {false, "bind", "use_vkCmdBindDescriptors"},
9836 {true, "bind2", "use vkCmdBindDescriptors2"},
9837 };
9838
9839 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access"));
9840
9841 // .primary_cmd_buf...
9842 for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx)
9843 {
9844 de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name));
9845
9846 for (int bindCommandNdx = 0; bindCommandNdx < DE_LENGTH_OF_ARRAY(s_bindCommand); ++bindCommandNdx)
9847 {
9848 de::MovePtr<tcu::TestCaseGroup> bindCommandGroup(
9849 new tcu::TestCaseGroup(testCtx, s_bindCommand[bindCommandNdx].name));
9850
9851 for (int updateMethodNdx = 0; updateMethodNdx < DE_LENGTH_OF_ARRAY(s_updateMethods); ++updateMethodNdx)
9852 {
9853 de::MovePtr<tcu::TestCaseGroup> updateMethodGroup(
9854 new tcu::TestCaseGroup(testCtx, s_updateMethods[updateMethodNdx].name));
9855
9856 // .sampler, .combined_image_sampler, other resource types ...
9857 for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx)
9858 {
9859 de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(
9860 testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description));
9861
9862 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx)
9863 {
9864 if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs)
9865 {
9866 de::MovePtr<tcu::TestCaseGroup> stageGroup(
9867 new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name));
9868 de::MovePtr<tcu::TestCaseGroup> multipleGroup(new tcu::TestCaseGroup(
9869 testCtx, "multiple_descriptor_sets", "Multiple descriptor sets"));
9870 de::MovePtr<tcu::TestCaseGroup> multipleDiscontiguousGroup(
9871 new tcu::TestCaseGroup(testCtx, "multiple_discontiguous_descriptor_sets",
9872 "Multiple discontiguous descriptor sets"));
9873
9874 for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions);
9875 ++dimensionNdx)
9876 {
9877 de::MovePtr<tcu::TestCaseGroup> dimensionSingleDescriptorSetGroup(
9878 new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9879 de::MovePtr<tcu::TestCaseGroup> dimensionMultipleDescriptorSetsGroup(
9880 new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9881 de::MovePtr<tcu::TestCaseGroup> dimensionMultipleDiscontiguousDescriptorSetsGroup(
9882 new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9883 void (*createTestsFunc)(
9884 tcu::TestCaseGroup *group, bool isPrimaryCmdBuf,
9885 DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
9886 vk::VkShaderStageFlags existingStages, vk::VkShaderStageFlags activeStages,
9887 DescriptorSetCount descriptorSetCount, ShaderInputInterface dimension,
9888 uint32_t resourceFlags, const bool bind2);
9889
9890 switch (s_descriptorTypes[descriptorNdx].descriptorType)
9891 {
9892 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
9893 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
9894 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
9895 createTestsFunc = createShaderAccessImageTests;
9896 break;
9897
9898 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
9899 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
9900 createTestsFunc = createShaderAccessTexelBufferTests;
9901 break;
9902
9903 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
9904 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
9905 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
9906 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
9907 createTestsFunc = createShaderAccessBufferTests;
9908 break;
9909
9910 default:
9911 createTestsFunc = DE_NULL;
9912 DE_FATAL("Impossible");
9913 }
9914
9915 if (createTestsFunc)
9916 {
9917 createTestsFunc(
9918 dimensionSingleDescriptorSetGroup.get(), s_bindTypes[bindTypeNdx].isPrimary,
9919 s_updateMethods[updateMethodNdx].method,
9920 s_descriptorTypes[descriptorNdx].descriptorType,
9921 s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9922 DESCRIPTOR_SET_COUNT_SINGLE, s_variableDimensions[dimensionNdx].dimension,
9923 s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9924
9925 createTestsFunc(
9926 dimensionMultipleDescriptorSetsGroup.get(), s_bindTypes[bindTypeNdx].isPrimary,
9927 s_updateMethods[updateMethodNdx].method,
9928 s_descriptorTypes[descriptorNdx].descriptorType,
9929 s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9930 DESCRIPTOR_SET_COUNT_MULTIPLE, s_variableDimensions[dimensionNdx].dimension,
9931 s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9932
9933 createTestsFunc(
9934 dimensionMultipleDiscontiguousDescriptorSetsGroup.get(),
9935 s_bindTypes[bindTypeNdx].isPrimary, s_updateMethods[updateMethodNdx].method,
9936 s_descriptorTypes[descriptorNdx].descriptorType,
9937 s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9938 DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS,
9939 s_variableDimensions[dimensionNdx].dimension,
9940 s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9941 }
9942 else
9943 DE_FATAL("Impossible");
9944
9945 stageGroup->addChild(dimensionSingleDescriptorSetGroup.release());
9946
9947 // Only one descriptor set layout can be created with VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR set
9948 if (s_updateMethods[updateMethodNdx].method == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH ||
9949 s_updateMethods[updateMethodNdx].method ==
9950 DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9951 continue;
9952
9953 multipleGroup->addChild(dimensionMultipleDescriptorSetsGroup.release());
9954 multipleDiscontiguousGroup->addChild(
9955 dimensionMultipleDiscontiguousDescriptorSetsGroup.release());
9956 }
9957
9958 stageGroup->addChild(multipleGroup.release());
9959 stageGroup->addChild(multipleDiscontiguousGroup.release());
9960 typeGroup->addChild(stageGroup.release());
9961 }
9962 }
9963
9964 if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL)
9965 {
9966 updateMethodGroup->addChild(typeGroup.release());
9967 }
9968 else
9969 {
9970 bindCommandGroup->addChild(typeGroup.release());
9971 }
9972 }
9973
9974 if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL)
9975 {
9976 bindCommandGroup->addChild(updateMethodGroup.release());
9977 }
9978 }
9979 bindGroup->addChild(bindCommandGroup.release());
9980 }
9981
9982 group->addChild(bindGroup.release());
9983 }
9984
9985 return group.release();
9986 }
9987
9988 } // namespace BindingModel
9989 } // namespace vkt
9990