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