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