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