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