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