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